* UV Tool (edit texture alignment of selected face) modifiers:
pivot control point and lines: ctrl = snap hard to face vertices and grid grid density controls: shift = change density of both axes synchronously, ctrl = power of two grid scale lines: shift = scale axes synchronously, ctrl = snap hard to vertices alt + m1 on grid = skew texture (is possible alright in BP and Valve220 map formats, not in AP); ctrl = snap hard to edges texture move: shift = only move along the axis with the biggest move, ctrl = snap grid lines hard to vertices and pivot rotate: shift = rotate with step of 15 degrees, ctrl = snap hard to edges
This commit is contained in:
parent
3ce07bb310
commit
aa99f4d254
|
|
@ -91,6 +91,7 @@ enum EManipulatorMode
|
|||
eDrag,
|
||||
eClip,
|
||||
eBuild,
|
||||
eUV,
|
||||
};
|
||||
|
||||
virtual void SetMode( EMode mode ) = 0;
|
||||
|
|
|
|||
|
|
@ -153,5 +153,16 @@ inline double plane3_distance_to_point( const Plane3& plane, const BasicVector3<
|
|||
return vector3_dot( point, plane.normal() ) - plane.dist();
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline BasicVector3<T> plane3_project_point( const Plane3& plane, const BasicVector3<T>& point, const BasicVector3<U>& direction ){
|
||||
const double f = vector3_dot( plane.normal(), direction );
|
||||
const double d = ( vector3_dot( plane.normal() * plane.dist() - point, plane.normal() ) ) / f;
|
||||
return point + direction * d;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline BasicVector3<T> plane3_project_point( const Plane3& plane, const BasicVector3<T>& point ){
|
||||
return ( point - plane.normal() * vector3_dot( point, plane.normal() ) + plane.normal() * plane.dist() );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -240,17 +240,17 @@ static Shader* getShader(){
|
|||
return StaticShader::instance();
|
||||
}
|
||||
|
||||
RenderablePivot(){
|
||||
RenderablePivot( std::size_t size = 16 ){
|
||||
m_vertices.reserve( 6 );
|
||||
|
||||
m_vertices.push_back( PointVertex( Vertex3f( 0, 0, 0 ), g_colour_x ) );
|
||||
m_vertices.push_back( PointVertex( Vertex3f( 16, 0, 0 ), g_colour_x ) );
|
||||
m_vertices.push_back( PointVertex( Vertex3f( size, 0, 0 ), g_colour_x ) );
|
||||
|
||||
m_vertices.push_back( PointVertex( Vertex3f( 0, 0, 0 ), g_colour_y ) );
|
||||
m_vertices.push_back( PointVertex( Vertex3f( 0, 16, 0 ), g_colour_y ) );
|
||||
m_vertices.push_back( PointVertex( Vertex3f( 0, size, 0 ), g_colour_y ) );
|
||||
|
||||
m_vertices.push_back( PointVertex( Vertex3f( 0, 0, 0 ), g_colour_z ) );
|
||||
m_vertices.push_back( PointVertex( Vertex3f( 0, 0, 16 ), g_colour_z ) );
|
||||
m_vertices.push_back( PointVertex( Vertex3f( 0, 0, size ), g_colour_z ) );
|
||||
}
|
||||
|
||||
void render( RenderStateFlags state ) const {
|
||||
|
|
|
|||
|
|
@ -1099,6 +1099,14 @@ void texdef_from_points(){
|
|||
Brush_textureChanged();
|
||||
}
|
||||
|
||||
void transform_texdef( const Matrix4& matrix, const Vector3& invariant = g_vector3_identity ){
|
||||
revertTexdef();
|
||||
// Texdef_transformLocked( m_texdefTransformed, m_shader.width(), m_shader.height(), m_plane.plane3(), matrix, static_cast<Vector3>( m_plane.plane3().normal() * m_plane.plane3().dist() ) );
|
||||
Texdef_transform( m_texdefTransformed, m_shader.width(), m_shader.height(), m_plane.plane3(), matrix, invariant );
|
||||
EmitTextureCoordinates();
|
||||
Brush_textureChanged();
|
||||
}
|
||||
|
||||
void transform( const Matrix4& matrix, bool mirror ){
|
||||
if ( g_brush_texturelock_enabled ) {
|
||||
Texdef_transformLocked( m_texdefTransformed, m_shader.width(), m_shader.height(), m_plane.plane3(), matrix, contributes() ? m_centroid_cached : static_cast<Vector3>( m_plane.plane3().normal() * m_plane.plane3().dist() ) );
|
||||
|
|
|
|||
|
|
@ -243,19 +243,19 @@ void Texdef_normalise( TextureProjection& projection, float width, float height
|
|||
// NOTE : ComputeAxisBase here and in q3map code must always BE THE SAME !
|
||||
// WARNING : special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere when x == 0
|
||||
// rotation by (0,RotY,RotZ) assigns X to normal
|
||||
template <typename Element>
|
||||
void ComputeAxisBase( const BasicVector3<Element>& normal, BasicVector3<Element>& texS, BasicVector3<Element>& texT ){
|
||||
template <typename Element, typename OtherElement>
|
||||
void ComputeAxisBase( const BasicVector3<Element>& normal, BasicVector3<OtherElement>& texS, BasicVector3<OtherElement>& texT ){
|
||||
#if 1
|
||||
const BasicVector3<Element> up( 0, 0, 1 );
|
||||
const BasicVector3<Element> down( 0, 0, -1 );
|
||||
|
||||
if ( vector3_equal_epsilon( normal, up, Element(1e-6) ) ) {
|
||||
texS = BasicVector3<Element>( 0, 1, 0 );
|
||||
texT = BasicVector3<Element>( 1, 0, 0 );
|
||||
texS = BasicVector3<OtherElement>( 0, 1, 0 );
|
||||
texT = BasicVector3<OtherElement>( 1, 0, 0 );
|
||||
}
|
||||
else if ( vector3_equal_epsilon( normal, down, Element(1e-6) ) ) {
|
||||
texS = BasicVector3<Element>( 0, 1, 0 );
|
||||
texT = BasicVector3<Element>( -1, 0, 0 );
|
||||
texS = BasicVector3<OtherElement>( 0, 1, 0 );
|
||||
texT = BasicVector3<OtherElement>( -1, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1633,16 +1633,6 @@ void BP_from_ST( brushprimit_texdef_t& bp, const DoubleVector3 points[3], const
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return point + direction * d;
|
||||
}
|
||||
|
||||
Vector3 plane3_project_point( const Plane3& plane, const Vector3& point ){
|
||||
return ( point - plane.normal() * vector3_dot( point, plane.normal() ) + plane.normal() * plane.dist() );
|
||||
}
|
||||
|
||||
const Vector3 BaseAxes[] = {
|
||||
Vector3( 0.0, 0.0, 1.0), Vector3( 1.0, 0.0, 0.0), Vector3( 0.0, -1.0, 0.0),
|
||||
Vector3( 0.0, 0.0, -1.0), Vector3( 1.0, 0.0, 0.0), Vector3( 0.0, -1.0, 0.0),
|
||||
|
|
@ -1680,8 +1670,72 @@ std::size_t planeNormalIndex( const Vector3& normal ) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void AP_from_axes( const Vector3& axisX, const Vector3& axisY, const DoubleVector3& normal, std::size_t width, std::size_t height, const Vector3& invariant, const Vector2& invariantTexCoords, texdef_t& texdef ){
|
||||
// obtain the texture plane norm and the base texture axes
|
||||
const std::size_t index = planeNormalIndex( normal );
|
||||
Vector3 xAxis = BaseAxes[index * 3 + 1];
|
||||
Vector3 yAxis = BaseAxes[index * 3 + 2];
|
||||
Vector3 zAxis = BaseAxes[( index / 2 ) * 6];
|
||||
|
||||
void Texdef_transformLocked( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const Matrix4& identity2transformed, const Vector3 centroid ){
|
||||
const Plane3 texturePlane( zAxis, 0 );
|
||||
|
||||
// project the transformed texture axes onto the new texture projection plane
|
||||
const Vector3 projectedXAxis = plane3_project_point( texturePlane, axisX );
|
||||
const Vector3 projectedYAxis = plane3_project_point( texturePlane, axisY );
|
||||
|
||||
const Vector3 normalizedXAxis = vector3_normalised( projectedXAxis );
|
||||
const Vector3 normalizedYAxis = vector3_normalised( projectedYAxis );
|
||||
|
||||
// determine the rotation angle from the dot product of the new base axes and the transformed, projected and normalized texture axes
|
||||
float cosX = vector3_dot( xAxis, normalizedXAxis );
|
||||
float cosY = vector3_dot( yAxis, normalizedYAxis );
|
||||
|
||||
float radX = std::acos( cosX );
|
||||
if( vector3_dot( vector3_cross( xAxis, normalizedXAxis ), zAxis ) < 0.0 )
|
||||
radX *= -1.0f;
|
||||
|
||||
float radY = std::acos( cosY );
|
||||
if( vector3_dot( vector3_cross( yAxis, normalizedYAxis ), zAxis ) < 0.0 )
|
||||
radY *= -1.0f;
|
||||
|
||||
// choosing between the X and Y axis rotations
|
||||
float rad = width >= height ? radX : radY;
|
||||
|
||||
// for some reason, when the texture plane normal is the Y axis, we must rotation clockwise
|
||||
if( ( index / 2 ) * 6 == 12 )
|
||||
rad *= -1.0f;
|
||||
|
||||
// doSetRotation( newNormal, newRotation, newRotation );
|
||||
const Matrix4 rotmat = matrix4_rotation_for_axisangle( vector3_cross( yAxis, xAxis ), rad );
|
||||
matrix4_transform_direction( rotmat, xAxis );
|
||||
matrix4_transform_direction( rotmat, yAxis );
|
||||
|
||||
// finally compute the scaling factors
|
||||
Vector2 scale( vector3_length( projectedXAxis ),
|
||||
vector3_length( projectedYAxis ) );
|
||||
|
||||
// the sign of the scaling factors depends on the angle between the new texture axis and the projected transformed axis
|
||||
if( vector3_dot( xAxis, normalizedXAxis ) < 0 )
|
||||
scale[0] *= -1.0f;
|
||||
if( vector3_dot( yAxis, normalizedYAxis ) < 0 )
|
||||
scale[1] *= -1.0f;
|
||||
|
||||
// determine the new texture coordinates of the transformed center of the face, sans offsets
|
||||
const Vector2 newInvariantTexCoords( vector3_dot( xAxis / scale[0], invariant ),
|
||||
vector3_dot( yAxis / scale[1], invariant ) );
|
||||
// globalOutputStream() << "newInvariantTexCoords: " << newInvariantTexCoords[0] << " " << newInvariantTexCoords[1] << "\n";
|
||||
// since the center should be invariant, the offsets are determined by the difference of the current and
|
||||
// the original texture coordinates of the center
|
||||
texdef.shift[0] = invariantTexCoords[0] - newInvariantTexCoords[0];
|
||||
texdef.shift[1] = invariantTexCoords[1] - newInvariantTexCoords[1];
|
||||
texdef.scale[0] = scale[0];
|
||||
texdef.scale[1] = scale[1];
|
||||
texdef.rotate = radians_to_degrees( rad );
|
||||
Texdef_normalise( texdef, (float)width, (float)height );
|
||||
}
|
||||
|
||||
|
||||
void Texdef_transformLocked( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const Matrix4& identity2transformed, const Vector3& invariant ){
|
||||
if( identity2transformed == g_matrix4_identity ){
|
||||
//globalOutputStream() << "identity2transformed == g_matrix4_identity\n";
|
||||
return; //TODO FIXME !!! this (and whole pipeline?) is called with g_matrix4_identity after every transform //now only on freezeTransform, it seems
|
||||
|
|
@ -1714,14 +1768,13 @@ void Texdef_transformLocked( TextureProjection& projection, std::size_t width, s
|
|||
BP_from_ST( projection.m_brushprimit_texdef, points, st, normalTransformed );
|
||||
}
|
||||
else if( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_QUAKE ) {
|
||||
// globalOutputStream() << "\t\t***: " << centroid << "\n";
|
||||
// globalOutputStream() << "\t\t***: " << invariant << "\n";
|
||||
// globalOutputStream() << "identity2transformed: " << identity2transformed << "\n";
|
||||
// printAP( projection );
|
||||
if( projection.m_texdef.scale[0] == 0.0f || projection.m_texdef.scale[1] == 0.0f ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Vector3 oldInvariant( centroid );
|
||||
#if 0//not ok, if scaling
|
||||
const Vector3 offset = matrix4_transformed_point( identity2transformed, Vector3( 0, 0, 0 ) );
|
||||
Vector3 newNormal = matrix4_transformed_point( identity2transformed, plane.normal() ) - offset;
|
||||
|
|
@ -1755,82 +1808,19 @@ void Texdef_transformLocked( TextureProjection& projection, std::size_t width, s
|
|||
matrix4_transform_direction( rotmat, xAxis );
|
||||
matrix4_transform_direction( rotmat, yAxis );
|
||||
|
||||
const Vector2 oldInvariantTexCoords( vector3_dot( xAxis / projection.m_texdef.scale[0], oldInvariant ) + projection.m_texdef.shift[0],
|
||||
vector3_dot( yAxis / projection.m_texdef.scale[1], oldInvariant ) + projection.m_texdef.shift[1] );
|
||||
// globalOutputStream() << "oldInvariantTexCoords: " << oldInvariantTexCoords[0] << " " << oldInvariantTexCoords[1] << "\n";
|
||||
const Vector2 invariantTexCoords( vector3_dot( xAxis / projection.m_texdef.scale[0], invariant ) + projection.m_texdef.shift[0],
|
||||
vector3_dot( yAxis / projection.m_texdef.scale[1], invariant ) + projection.m_texdef.shift[1] );
|
||||
// globalOutputStream() << "invariantTexCoords: " << invariantTexCoords[0] << " " << invariantTexCoords[1] << "\n";
|
||||
// project the texture axes onto the boundary plane along the texture Z axis
|
||||
const Vector3 boundaryOffset = plane3_project_point( plane, Vector3( 0, 0, 0 ), zAxis );
|
||||
const Vector3 oldXAxisOnBoundary = plane3_project_point( plane, xAxis * projection.m_texdef.scale[0], zAxis ) - boundaryOffset;
|
||||
const Vector3 oldYAxisOnBoundary = plane3_project_point( plane, yAxis * projection.m_texdef.scale[1], zAxis ) - boundaryOffset;
|
||||
const Vector3 boundaryOffset = plane3_project_point( plane, Vector3( 0, 0, 0 ), zAxis );
|
||||
const Vector3 xAxisOnBoundary = plane3_project_point( plane, xAxis * projection.m_texdef.scale[0], zAxis ) - boundaryOffset;
|
||||
const Vector3 yAxisOnBoundary = plane3_project_point( plane, yAxis * projection.m_texdef.scale[1], zAxis ) - boundaryOffset;
|
||||
|
||||
// transform the projected texture axes and compensate the translational component
|
||||
const Vector3 transformedXAxis = matrix4_transformed_direction( identity2transformed, oldXAxisOnBoundary );
|
||||
const Vector3 transformedYAxis = matrix4_transformed_direction( identity2transformed, oldYAxisOnBoundary );
|
||||
const Vector3 transformedXAxis = matrix4_transformed_direction( identity2transformed, xAxisOnBoundary );
|
||||
const Vector3 transformedYAxis = matrix4_transformed_direction( identity2transformed, yAxisOnBoundary );
|
||||
|
||||
// obtain the new texture plane norm and the new base texture axes
|
||||
const std::size_t newIndex = planeNormalIndex( newNormal );
|
||||
xAxis = BaseAxes[newIndex * 3 + 1];
|
||||
yAxis = BaseAxes[newIndex * 3 + 2];
|
||||
zAxis = BaseAxes[( newIndex / 2 ) * 6];
|
||||
|
||||
const Plane3 newTexturePlane( zAxis, 0 );
|
||||
|
||||
// project the transformed texture axes onto the new texture projection plane
|
||||
const Vector3 projectedTransformedXAxis = plane3_project_point( newTexturePlane, transformedXAxis );
|
||||
const Vector3 projectedTransformedYAxis = plane3_project_point( newTexturePlane, transformedYAxis );
|
||||
|
||||
const Vector3 normalizedXAxis = vector3_normalised( projectedTransformedXAxis );
|
||||
const Vector3 normalizedYAxis = vector3_normalised( projectedTransformedYAxis );
|
||||
|
||||
// determine the rotation angle from the dot product of the new base axes and the transformed, projected and normalized texture axes
|
||||
float cosX = vector3_dot( xAxis, normalizedXAxis );
|
||||
float cosY = vector3_dot( yAxis, normalizedYAxis );
|
||||
|
||||
float radX = std::acos( cosX );
|
||||
if( vector3_dot( vector3_cross( xAxis, normalizedXAxis ), zAxis ) < 0.0 )
|
||||
radX *= -1.0f;
|
||||
|
||||
float radY = std::acos( cosY );
|
||||
if( vector3_dot( vector3_cross( yAxis, normalizedYAxis ), zAxis ) < 0.0 )
|
||||
radY *= -1.0f;
|
||||
|
||||
// choosing between the X and Y axis rotations
|
||||
float rad = width >= height ? radX : radY;
|
||||
|
||||
// for some reason, when the texture plane normal is the Y axis, we must rotation clockwise
|
||||
if( ( newIndex / 2 ) * 6 == 12 )
|
||||
rad *= -1.0f;
|
||||
|
||||
// doSetRotation( newNormal, newRotation, newRotation );
|
||||
rotmat = matrix4_rotation_for_axisangle( vector3_cross( yAxis, xAxis ), rad );
|
||||
matrix4_transform_direction( rotmat, xAxis );
|
||||
matrix4_transform_direction( rotmat, yAxis );
|
||||
|
||||
// finally compute the scaling factors
|
||||
Vector2 newScale( vector3_length( projectedTransformedXAxis ),
|
||||
vector3_length( projectedTransformedYAxis ) );
|
||||
|
||||
// the sign of the scaling factors depends on the angle between the new texture axis and the projected transformed axis
|
||||
if( vector3_dot( xAxis, normalizedXAxis ) < 0 )
|
||||
newScale[0] *= -1.0f;
|
||||
if( vector3_dot( yAxis, normalizedYAxis ) < 0 )
|
||||
newScale[1] *= -1.0f;
|
||||
|
||||
// compute the parameters of the transformed texture coordinate system
|
||||
const Vector3 newInvariant = matrix4_transformed_point( identity2transformed, oldInvariant );
|
||||
|
||||
// determine the new texture coordinates of the transformed center of the face, sans offsets
|
||||
const Vector2 newInvariantTexCoords( vector3_dot( xAxis / newScale[0], newInvariant ),
|
||||
vector3_dot( yAxis / newScale[1], newInvariant ) );
|
||||
// globalOutputStream() << "newInvariantTexCoords: " << newInvariantTexCoords[0] << " " << newInvariantTexCoords[1] << "\n";
|
||||
// since the center should be invariant, the offsets are determined by the difference of the current and
|
||||
// the original texture coordinates of the center
|
||||
projection.m_texdef.shift[0] = oldInvariantTexCoords[0] - newInvariantTexCoords[0];
|
||||
projection.m_texdef.shift[1] = oldInvariantTexCoords[1] - newInvariantTexCoords[1];
|
||||
projection.m_texdef.scale[0] = newScale[0];
|
||||
projection.m_texdef.scale[1] = newScale[1];
|
||||
projection.m_texdef.rotate = radians_to_degrees( rad );
|
||||
Texdef_normalise( projection, (float)width, (float)height );
|
||||
AP_from_axes( transformedXAxis, transformedYAxis, newNormal, width, height, matrix4_transformed_point( identity2transformed, invariant ), invariantTexCoords, projection.m_texdef );
|
||||
// globalOutputStream() << "new "; printAP( projection );
|
||||
}
|
||||
else{ //TEXDEFTYPEID_VALVE
|
||||
|
|
@ -1886,6 +1876,49 @@ void Texdef_transformLocked( TextureProjection& projection, std::size_t width, s
|
|||
}
|
||||
}
|
||||
|
||||
void Texdef_transform( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const Matrix4& identity2transformed, const Vector3& invariant ){
|
||||
if( identity2transformed == g_matrix4_identity ){
|
||||
//globalOutputStream() << "identity2transformed == g_matrix4_identity\n";
|
||||
return; //TODO FIXME !!! this (and whole pipeline?) is called with g_matrix4_identity after every transform //now only on freezeTransform, it seems
|
||||
}
|
||||
if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ||
|
||||
g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_VALVE ) {
|
||||
Texdef_transformLocked( projection, width, height, plane, identity2transformed, invariant );
|
||||
}
|
||||
else if( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_QUAKE ) {
|
||||
// globalOutputStream() << "\t\t***: " << invariant << "\n";
|
||||
// globalOutputStream() << "identity2transformed: " << identity2transformed << "\n";
|
||||
// printAP( projection );
|
||||
if( projection.m_texdef.scale[0] == 0.0f || projection.m_texdef.scale[1] == 0.0f ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate the current texture coordinates of the origin
|
||||
const std::size_t index = planeNormalIndex( plane.normal() );
|
||||
Vector3 xAxis = BaseAxes[index * 3 + 1];
|
||||
Vector3 yAxis = BaseAxes[index * 3 + 2];
|
||||
Vector3 zAxis = BaseAxes[( index / 2 ) * 6];
|
||||
// globalOutputStream() << xAxis << " " << yAxis << " " << zAxis << "\n";
|
||||
Matrix4 rotmat = matrix4_rotation_for_axisangle( vector3_cross( yAxis, xAxis ), degrees_to_radians( projection.m_texdef.rotate ) );
|
||||
matrix4_transform_direction( rotmat, xAxis );
|
||||
matrix4_transform_direction( rotmat, yAxis );
|
||||
|
||||
const Vector2 invariantTexCoords( vector3_dot( xAxis / projection.m_texdef.scale[0], invariant ) + projection.m_texdef.shift[0],
|
||||
vector3_dot( yAxis / projection.m_texdef.scale[1], invariant ) + projection.m_texdef.shift[1] );
|
||||
// globalOutputStream() << "invariantTexCoords: " << invariantTexCoords[0] << " " << invariantTexCoords[1] << "\n";
|
||||
// project the texture axes onto the boundary plane along the texture Z axis
|
||||
const Vector3 boundaryOffset = plane3_project_point( plane, Vector3( 0, 0, 0 ), zAxis );
|
||||
const Vector3 xAxisOnBoundary = plane3_project_point( plane, xAxis * projection.m_texdef.scale[0], zAxis ) - boundaryOffset;
|
||||
const Vector3 yAxisOnBoundary = plane3_project_point( plane, yAxis * projection.m_texdef.scale[1], zAxis ) - boundaryOffset;
|
||||
|
||||
// transform the projected texture axes and compensate the translational component
|
||||
const Vector3 transformedXAxis = matrix4_transformed_direction( identity2transformed, xAxisOnBoundary );
|
||||
const Vector3 transformedYAxis = matrix4_transformed_direction( identity2transformed, yAxisOnBoundary );
|
||||
|
||||
AP_from_axes( transformedXAxis, transformedYAxis, plane.normal(), width, height, matrix4_transformed_point( identity2transformed, invariant ), invariantTexCoords, projection.m_texdef );
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Q3_to_matrix( const texdef_t& texdef, float width, float height, const Vector3& normal, Matrix4& matrix ){
|
||||
Normal_GetTransform( normal, matrix );
|
||||
|
|
@ -2028,75 +2061,12 @@ void AP_from_BP( TextureProjection& projection, const Plane3& plane, std::size_t
|
|||
Matrix4 local2tex;
|
||||
Texdef_Construct_local2tex( projection, width, height, plane.normal(), local2tex );
|
||||
const Vector3 st = matrix4_transformed_point( local2tex, invariant );
|
||||
const Vector2 oldInvariantTexCoords( st[0] * width, st[1] * height );
|
||||
const Vector2 invariantTexCoords( st[0] * width, st[1] * height );
|
||||
// globalOutputStream() << "local2tex: " << local2tex << "\n";
|
||||
// globalOutputStream() << "oldInvariantTexCoords: " << oldInvariantTexCoords[0] << " " << oldInvariantTexCoords[1] << "\n";
|
||||
// globalOutputStream() << "invariantTexCoords: " << invariantTexCoords[0] << " " << invariantTexCoords[1] << "\n";
|
||||
|
||||
// obtain AP base texture axes
|
||||
const std::size_t newIndex = planeNormalIndex( plane.normal() );
|
||||
Vector3 xAxis = BaseAxes[newIndex * 3 + 1];
|
||||
Vector3 yAxis = BaseAxes[newIndex * 3 + 2];
|
||||
const Vector3 zAxis = BaseAxes[( newIndex / 2 ) * 6];
|
||||
|
||||
/* hacky hack: transform BP by scale 0 @ zAxis */
|
||||
const Matrix4 transform( matrix4_scale_for_vec3( Vector3( zAxis[0] == 0? 1 : 0, zAxis[1] == 0? 1 : 0, zAxis[2] == 0? 1 : 0 ) ) );
|
||||
Texdef_transformLocked( projection, width, height, plane, transform, g_vector3_identity );
|
||||
Texdef_Construct_local2tex( projection, width, height, BaseAxes[newIndex * 3], local2tex );
|
||||
|
||||
const Vector3 projectedTransformedXAxis( Vector3( local2tex[0], local2tex[4], local2tex[8] ) * width );
|
||||
const Vector3 projectedTransformedYAxis( Vector3( local2tex[1], local2tex[5], local2tex[9] ) * height );
|
||||
// globalOutputStream() << "projectedTransformedXAxis: " << projectedTransformedXAxis << "\n";
|
||||
// globalOutputStream() << "projectedTransformedYAxis: " << projectedTransformedYAxis << "\n";
|
||||
|
||||
const Vector3 normalizedXAxis = vector3_normalised( projectedTransformedXAxis );
|
||||
const Vector3 normalizedYAxis = vector3_normalised( projectedTransformedYAxis );
|
||||
|
||||
// determine the rotation angle from the dot product of base axes and the transformed, projected and normalized texture axes
|
||||
float cosX = vector3_dot( xAxis, normalizedXAxis );
|
||||
float cosY = vector3_dot( yAxis, normalizedYAxis );
|
||||
|
||||
float radX = std::acos( cosX );
|
||||
if( vector3_dot( vector3_cross( xAxis, normalizedXAxis ), zAxis ) < 0.0 )
|
||||
radX *= -1.0f;
|
||||
|
||||
float radY = std::acos( cosY );
|
||||
if( vector3_dot( vector3_cross( yAxis, normalizedYAxis ), zAxis ) < 0.0 )
|
||||
radY *= -1.0f;
|
||||
|
||||
// choosing between the X and Y axis rotations
|
||||
float rad = width >= height ? radX : radY;
|
||||
|
||||
// for some reason, when the texture plane normal is the Y axis, we must rotation clockwise
|
||||
if( ( newIndex / 2 ) * 6 == 12 )
|
||||
rad *= -1.0f;
|
||||
|
||||
// doSetRotation( newNormal, newRotation, newRotation );
|
||||
const Matrix4 rotmat = matrix4_rotation_for_axisangle( vector3_cross( yAxis, xAxis ), rad );
|
||||
matrix4_transform_direction( rotmat, xAxis );
|
||||
matrix4_transform_direction( rotmat, yAxis );
|
||||
|
||||
// finally compute the scaling factors
|
||||
Vector2 newScale( 1.0 / vector3_length( projectedTransformedXAxis ),
|
||||
1.0 / vector3_length( projectedTransformedYAxis ) );
|
||||
|
||||
// the sign of the scaling factors depends on the angle between the new texture axis and the projected transformed axis
|
||||
if( vector3_dot( xAxis, normalizedXAxis ) < 0 )
|
||||
newScale[0] *= -1.0f;
|
||||
if( vector3_dot( yAxis, normalizedYAxis ) < 0 )
|
||||
newScale[1] *= -1.0f;
|
||||
|
||||
// determine the new texture coordinates of the transformed center of the face, sans offsets
|
||||
const Vector2 newInvariantTexCoords( vector3_dot( xAxis / newScale[0], invariant ),
|
||||
vector3_dot( yAxis / newScale[1], invariant ) );
|
||||
// globalOutputStream() << "newInvariantTexCoords: " << newInvariantTexCoords[0] << " " << newInvariantTexCoords[1] << "\n";
|
||||
// since the center should be invariant, the offsets are determined by the difference of the current and
|
||||
// the original texture coordinates of the center
|
||||
projection.m_texdef.shift[0] = oldInvariantTexCoords[0] - newInvariantTexCoords[0];
|
||||
projection.m_texdef.shift[1] = oldInvariantTexCoords[1] - newInvariantTexCoords[1];
|
||||
projection.m_texdef.scale[0] = newScale[0];
|
||||
projection.m_texdef.scale[1] = newScale[1];
|
||||
projection.m_texdef.rotate = radians_to_degrees( rad );
|
||||
Texdef_normalise( projection.m_texdef, (float)width, (float)height );
|
||||
const Matrix4 tex2local = matrix4_affine_inverse( local2tex );
|
||||
AP_from_axes( vector4_to_vector3( tex2local.x() ) / width, vector4_to_vector3( tex2local.y() ) / height, plane.normal(), width, height, invariant, invariantTexCoords, projection.m_texdef );
|
||||
}
|
||||
|
||||
void Valve220_from_BP( TextureProjection& projection, const Plane3& plane, std::size_t width, std::size_t height ) {
|
||||
|
|
@ -2201,3 +2171,30 @@ void Texdef_from_ST( TextureProjection& projection, const DoubleVector3 points[3
|
|||
Valve220_from_BP( projection, plane, width, height );
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Texdef_getTexAxes( const TextureProjection& projection, const Plane3& plane, std::size_t width, std::size_t height, Matrix4& local2tex, Matrix4& tex2local, Matrix4& basis ){
|
||||
Texdef_Construct_local2tex( projection, width, height, plane.normal(), local2tex );
|
||||
basis = matrix4_affine_inverse( local2tex ); //natural texture basis in world space
|
||||
|
||||
TextureProjection proj( projection );
|
||||
if( g_bp_globals.m_texdefTypeId != TEXDEFTYPEID_BRUSHPRIMITIVES ){
|
||||
BPTexdef_fromST011( proj, plane, local2tex );
|
||||
}
|
||||
|
||||
// rest is equal to inverse( BP local2tex ), but hopefully has more precision
|
||||
BPTexdef_toTransform( proj.m_brushprimit_texdef, local2tex );
|
||||
tex2local = matrix4_affine_inverse( local2tex );
|
||||
|
||||
//Texdef_basisForNormal( proj, plane.normal(), xyz2st ); minus inverse of orthogonal basis via transpose
|
||||
Matrix4 xyz2st = g_matrix4_identity;
|
||||
ComputeAxisBase( plane.normal(), vector4_to_vector3( xyz2st.x() ), vector4_to_vector3( xyz2st.y() ) );
|
||||
vector4_to_vector3( xyz2st.z() ) = plane.normal();
|
||||
|
||||
// natural texture basis, aligned to the plane
|
||||
matrix4_premultiply_by_matrix4( tex2local, xyz2st ); // ( A B )-1 = B-1 A-1
|
||||
|
||||
// return BP local2tex to have STs range according to tex2local
|
||||
matrix4_multiply_by_matrix4( local2tex, matrix4_transposed( xyz2st ) );
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -111,7 +111,8 @@ void Texdef_EmitTextureCoordinates( const TextureProjection& projection, std::si
|
|||
void ShiftScaleRotate_fromFace( texdef_t& shiftScaleRotate, const TextureProjection& projection );
|
||||
void ShiftScaleRotate_toFace( const texdef_t& shiftScaleRotate, TextureProjection& projection );
|
||||
|
||||
void Texdef_transformLocked( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const Matrix4& transform, const Vector3 centroid = Vector3( 0, 0, 0 ) );
|
||||
void Texdef_transformLocked( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const Matrix4& transform, const Vector3& invariant = g_vector3_identity );
|
||||
void Texdef_transform( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const Matrix4& transform, const Vector3& invariant = g_vector3_identity );
|
||||
void Texdef_normalise( TextureProjection& projection, float width, float height );
|
||||
|
||||
enum TexdefTypeId
|
||||
|
|
@ -131,7 +132,7 @@ 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, const DoubleVector3 points[3], const DoubleVector3 st[3], std::size_t width, std::size_t height );
|
||||
template <typename Element>
|
||||
void ComputeAxisBase( const BasicVector3<Element>& normal, BasicVector3<Element>& texS, BasicVector3<Element>& texT );
|
||||
template <typename Element, typename OtherElement>
|
||||
void ComputeAxisBase( const BasicVector3<Element>& normal, BasicVector3<OtherElement>& texS, BasicVector3<OtherElement>& texT );
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2088,7 +2088,7 @@ void CamWnd::Cam_Draw(){
|
|||
|
||||
Scene_Render( renderer, m_view );
|
||||
|
||||
if( g_camwindow_globals_private.m_bShowWorkzone && GlobalSelectionSystem().countSelected() != 0 ){
|
||||
if( g_camwindow_globals_private.m_bShowWorkzone && GlobalSelectionSystem().countSelected() != 0 && GlobalSelectionSystem().ManipulatorMode() != SelectionSystem::eUV ){
|
||||
m_draw_workzone.render( renderer, m_state_workzone );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1441,6 +1441,10 @@ void BuildToolExport( const BoolImportCallback& importCallback ){
|
|||
importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eBuild );
|
||||
}
|
||||
|
||||
void UVToolExport( const BoolImportCallback& importCallback ){
|
||||
importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eUV );
|
||||
}
|
||||
|
||||
FreeCaller1<const BoolImportCallback&, TranslateToolExport> g_translatemode_button_caller;
|
||||
BoolExportCallback g_translatemode_button_callback( g_translatemode_button_caller );
|
||||
ToggleItem g_translatemode_button( g_translatemode_button_callback );
|
||||
|
|
@ -1469,6 +1473,10 @@ FreeCaller1<const BoolImportCallback&, BuildToolExport> g_build_button_caller;
|
|||
BoolExportCallback g_build_button_callback( g_build_button_caller );
|
||||
ToggleItem g_build_button( g_build_button_callback );
|
||||
|
||||
FreeCaller1<const BoolImportCallback&, UVToolExport> g_uv_button_caller;
|
||||
BoolExportCallback g_uv_button_callback( g_uv_button_caller );
|
||||
ToggleItem g_uv_button( g_uv_button_callback );
|
||||
|
||||
void ToolChanged(){
|
||||
g_translatemode_button.update();
|
||||
g_rotatemode_button.update();
|
||||
|
|
@ -1477,6 +1485,7 @@ void ToolChanged(){
|
|||
g_dragmode_button.update();
|
||||
g_clipper_button.update();
|
||||
g_build_button.update();
|
||||
g_uv_button.update();
|
||||
}
|
||||
|
||||
const char* const c_ResizeMode_status = "QE4 Drag Tool: move and resize objects";
|
||||
|
|
@ -1615,6 +1624,28 @@ void BuildMode(){
|
|||
}
|
||||
|
||||
|
||||
const char* const c_UVMode_status = "UV Tool: edit texture alignment";
|
||||
|
||||
void UVMode(){
|
||||
if ( g_currentToolMode == UVMode && g_defaultToolMode != UVMode ) {
|
||||
g_defaultToolMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_currentToolMode = UVMode;
|
||||
g_currentToolModeSupportsComponentEditing = false;
|
||||
|
||||
SelectionSystem_DefaultMode();
|
||||
ComponentModeChanged();
|
||||
|
||||
Sys_Status( c_UVMode_status );
|
||||
GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eUV );
|
||||
ToolChanged();
|
||||
ModeChangeNotify();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ToggleRotateScaleModes(){
|
||||
return g_currentToolMode == RotateMode? ScaleMode() : RotateMode();
|
||||
}
|
||||
|
|
@ -2404,6 +2435,7 @@ void Manipulators_registerShortcuts(){
|
|||
toggle_add_accelerator( "MouseDrag" );
|
||||
toggle_add_accelerator( "ToggleClipper" );
|
||||
toggle_add_accelerator( "MouseBuild" );
|
||||
toggle_add_accelerator( "MouseUV" );
|
||||
|
||||
command_connect_accelerator( "MouseRotateOrScale" );
|
||||
command_connect_accelerator( "MouseDragOrTransform" );
|
||||
|
|
@ -2535,6 +2567,7 @@ void Manipulators_constructToolbar( GtkToolbar* toolbar ){
|
|||
toolbar_append_toggle_button( toolbar, "Resize (Q)", "select_mouseresize.png", "MouseDrag" );
|
||||
toolbar_append_toggle_button( toolbar, "Clipper (X)", "select_clipper.png", "ToggleClipper" );
|
||||
// toolbar_append_toggle_button( toolbar, "Build (B)", "select_mouserotate.png", "MouseBuild" );
|
||||
toolbar_append_toggle_button( toolbar, "UV Tool (G)", "select_mouseuv.png", "MouseUV" );
|
||||
}
|
||||
|
||||
GtkToolbar* create_main_toolbar( MainFrame::EViewStyle style ){
|
||||
|
|
@ -3604,6 +3637,7 @@ void MainFrame_Construct(){
|
|||
GlobalToggles_insert( "MouseTransform", FreeCaller<SkewMode>(), ToggleItem::AddCallbackCaller( g_skewmode_button ) );
|
||||
GlobalToggles_insert( "MouseDrag", FreeCaller<DragMode>(), ToggleItem::AddCallbackCaller( g_dragmode_button ) );
|
||||
GlobalToggles_insert( "MouseBuild", FreeCaller<BuildMode>(), ToggleItem::AddCallbackCaller( g_build_button ), Accelerator( 'B' ) );
|
||||
GlobalToggles_insert( "MouseUV", FreeCaller<UVMode>(), ToggleItem::AddCallbackCaller( g_uv_button ), Accelerator( Accelerator( 'G' ) ) );
|
||||
GlobalCommands_insert( "MouseRotateOrScale", FreeCaller<ToggleRotateScaleModes>() );
|
||||
GlobalCommands_insert( "MouseDragOrTransform", FreeCaller<ToggleDragSkewModes>(), Accelerator( 'Q' ) );
|
||||
|
||||
|
|
|
|||
|
|
@ -2201,6 +2201,11 @@ void OpenGLShader::construct( const char* name ){
|
|||
hiddenLine.m_linewidth = 2;
|
||||
hiddenLine.m_depthfunc = GL_GREATER;
|
||||
}
|
||||
else if ( string_equal( name + 1, "BLENDLINE" ) ) {
|
||||
state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_BLEND;
|
||||
state.m_sort = OpenGLState::eSortGUI0 - 1;
|
||||
state.m_linewidth = 1;
|
||||
}
|
||||
else if ( string_equal( name + 1, "LATTICE" ) ) {
|
||||
state.m_colour[0] = 1;
|
||||
state.m_colour[1] = 0.5;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
BIN
setup/data/tools/bitmaps/select_mouseuv.png
Normal file
BIN
setup/data/tools/bitmaps/select_mouseuv.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 365 B |
Loading…
Reference in New Issue
Block a user