UV Tool: add patch support

patch controls move modifiers: shift = only move along the axis with the biggest move, ctrl = snap hard to grid and povit lines
fix a couple of Patch::Calculate_AvgNormal() and Patch::NaturalTexture() problems
This commit is contained in:
Garux 2019-06-10 15:17:57 +03:00
parent 684187c4ec
commit 2426697f65
6 changed files with 784 additions and 314 deletions

View File

@ -59,6 +59,12 @@ BasicVector3( const BasicVector3<OtherElement>& other ){
y() = static_cast<Element>( other.y() );
z() = static_cast<Element>( other.z() );
}
template<typename OtherElement>
explicit BasicVector3( const BasicVector2<OtherElement>& vec2 ){
x() = static_cast<Element>( vec2.x() );
y() = static_cast<Element>( vec2.y() );
z() = 0;
}
BasicVector3( const Element& x_, const Element& y_, const Element& z_ ){
x() = x_;
y() = y_;

View File

@ -1581,7 +1581,7 @@ double Det3x3( double a00, double a01, double a02,
+ a02 * ( a10 * a21 - a11 * a20 );
}
void BP_from_ST( brushprimit_texdef_t& bp, const DoubleVector3 points[3], const DoubleVector3 st[3], const DoubleVector3& normal ){
void BP_from_ST( brushprimit_texdef_t& bp, const DoubleVector3 points[3], const DoubleVector3 st[3], const DoubleVector3& normal, const bool normalize = true ){
double xyI[2], xyJ[2], xyK[2];
double stI[2], stJ[2], stK[2];
double D, D0, D1, D2;
@ -1627,7 +1627,7 @@ void BP_from_ST( brushprimit_texdef_t& bp, const DoubleVector3 points[3], const
);
bp.coords[i][0] = D0 / D;
bp.coords[i][1] = D1 / D;
bp.coords[i][2] = fmod( D2 / D, 1.0 );
bp.coords[i][2] = normalize? fmod( D2 / D, 1.0 ) : ( D2 / D );
}
// 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";
}
@ -2172,6 +2172,22 @@ void Texdef_from_ST( TextureProjection& projection, const DoubleVector3 points[3
}
}
void Texdef_Construct_local2tex_from_ST( const DoubleVector3 points[3], const DoubleVector3 st[3], Matrix4& local2tex ){
const Plane3 plane( plane3_for_points( points ) );
brushprimit_texdef_t bp;
BP_from_ST( bp, points, st, plane.normal(), false );
BPTexdef_toTransform( bp, local2tex );
{
// Texdef_basisForNormal
Matrix4 basis = g_matrix4_identity;
ComputeAxisBase( plane.normal(), vector4_to_vector3( basis.x() ), vector4_to_vector3( basis.y() ) );
vector4_to_vector3( basis.z() ) = plane.normal();
matrix4_transpose( basis );
matrix4_multiply_by_matrix4( local2tex, basis );
}
}
#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 );

View File

@ -106,6 +106,7 @@ void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, st
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, bool only_dimension );
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_Construct_local2tex_from_ST( const DoubleVector3 points[3], const DoubleVector3 st[3], Matrix4& local2tex );
void Texdef_EmitTextureCoordinates( const TextureProjection& projection, std::size_t width, std::size_t height, Winding& w, const Vector3& normal, const Matrix4& localToWorld );
void ShiftScaleRotate_fromFace( texdef_t& shiftScaleRotate, const TextureProjection& projection );

View File

@ -604,42 +604,52 @@ 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;
void Patch::Calculate_AvgAxes( Vector3& wDir, Vector3& hDir ) const {
wDir = hDir = g_vector3_identity;
for ( std::size_t r = 0; r < m_height; ++r ){
wDir += ctrlAt( r, m_width - 1 ).m_vertex - ctrlAt( r, 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;
for ( std::size_t c = 0; c < m_width; ++c ){
hDir += ctrlAt( m_height - 1, c ).m_vertex - ctrlAt( 0, c ).m_vertex;
}
/* fallback */
if ( vector3_equal_epsilon( wDir, g_vector3_identity, 1e-3f ) || vector3_equal_epsilon( hDir, g_vector3_identity, 1e-3f ) ) {
for ( std::size_t i = 0; i < m_height; ++i ){
for ( std::size_t j = 0; j < m_width - 1; ++j ){
wDir = ctrlAt( i, j + 1 ).m_vertex - ctrlAt( i, j ).m_vertex;
if ( !vector3_equal_epsilon( wDir, g_vector3_identity, 1e-3f ) )
goto break1;
}
}
break1:
for ( std::size_t i = 0; i < m_width; ++i ){
for ( std::size_t j = 0; j < m_height; ++j ){
hDir = ctrlAt( j + 1, i ).m_vertex - ctrlAt( j, i ).m_vertex;
if ( !vector3_equal_epsilon( hDir, g_vector3_identity, 1e-3f ) )
goto break2;
/* fallback to longest hord */
if ( vector3_equal_epsilon( wDir, g_vector3_identity, 1.f ) ){
float bestLength = 0;
for ( std::size_t r = 0; r < m_height; ++r ){
for ( std::size_t c = 0; c < m_width - 1; ++c ){
const Vector3 dir = ctrlAt( r, c + 1 ).m_vertex - ctrlAt( r, c ).m_vertex;
const float length = vector3_length( dir );
if ( length - bestLength > 1 ){
bestLength = length;
wDir = dir;
}
}
}
}
if( vector3_equal_epsilon( hDir, g_vector3_identity, 1.f ) ){
float bestLength = 0;
for ( std::size_t c = 0; c < m_width; ++c ){
for ( std::size_t r = 0; r < m_height - 1; ++r ){
const Vector3 dir = ctrlAt( r + 1, c ).m_vertex - ctrlAt( r, c ).m_vertex;
const float length = vector3_length( dir );
if ( length - bestLength > 1 ){
bestLength = length;
hDir = dir;
}
}
}
}
break2:
Vector3 normal( vector3_cross( wDir, hDir ) );
if ( vector3_equal( normal, g_vector3_identity ) ) {
normal = Vector3( 0, 0, 1 );
if ( vector3_equal_epsilon( vector3_cross( wDir, hDir ), g_vector3_identity, 0.1f ) ) {
wDir = g_vector3_axis_x;
hDir = g_vector3_axis_y;
}
else{
vector3_normalise( normal );
}
return normal;
}
Vector3 Patch::Calculate_AvgNormal() const {
Vector3 wDir, hDir;
Calculate_AvgAxes( wDir, hDir );
return vector3_normalised( vector3_cross( wDir, hDir ) );
}
inline int texture_axis( const Vector3& normal ){
@ -693,16 +703,16 @@ void Patch::NaturalTexture(){
undoSave();
{
float fSize = (float)m_state->getTexture().width * Texdef_getDefaultTextureScale();
const double texSize = (double)m_state->getTexture().width * Texdef_getDefaultTextureScale();
double texBest = 0;
double tex = 0;
PatchControl* pWidth = m_ctrl.data();
for ( std::size_t w = 0; w < m_width; w++, pWidth++ )
for ( std::size_t w = 0; w < m_width; ++w, ++pWidth )
{
{
PatchControl* pHeight = pWidth;
for ( std::size_t h = 0; h < m_height; h++, pHeight += m_width )
for ( std::size_t h = 0; h < m_height; ++h, pHeight += m_width )
pHeight->m_texcoord[0] = static_cast<float>( tex );
}
@ -711,12 +721,11 @@ void Patch::NaturalTexture(){
}
{
PatchControl* pHeight = pWidth;
for ( std::size_t h = 0; h < m_height; h++, pHeight += m_width )
const PatchControl* pHeight = pWidth;
for ( std::size_t h = 0; h < m_height; ++h, pHeight += m_width )
{
Vector3 v( vector3_subtracted( pHeight->m_vertex, ( pHeight + 1 )->m_vertex ) );
double length = tex + ( vector3_length( v ) / fSize );
if ( fabs( length ) > texBest ) {
const double length = tex + ( vector3_length( pHeight->m_vertex - ( pHeight + 1 )->m_vertex ) / texSize );
if ( fabs( length ) > fabs( texBest ) ) { // comparing abs values supports possible negative Texdef_getDefaultTextureScale()
texBest = length;
}
}
@ -727,16 +736,16 @@ void Patch::NaturalTexture(){
}
{
float fSize = -(float)m_state->getTexture().height * Texdef_getDefaultTextureScale();
const double texSize = -(double)m_state->getTexture().height * Texdef_getDefaultTextureScale();
double texBest = 0;
double tex = 0;
PatchControl* pHeight = m_ctrl.data();
for ( std::size_t h = 0; h < m_height; h++, pHeight += m_width )
for ( std::size_t h = 0; h < m_height; ++h, pHeight += m_width )
{
{
PatchControl* pWidth = pHeight;
for ( std::size_t w = 0; w < m_width; w++, pWidth++ )
for ( std::size_t w = 0; w < m_width; ++w, ++pWidth )
pWidth->m_texcoord[1] = static_cast<float>( tex );
}
@ -745,12 +754,11 @@ void Patch::NaturalTexture(){
}
{
PatchControl* pWidth = pHeight;
for ( std::size_t w = 0; w < m_width; w++, pWidth++ )
const PatchControl* pWidth = pHeight;
for ( std::size_t w = 0; w < m_width; ++w, ++pWidth )
{
Vector3 v( vector3_subtracted( pWidth->m_vertex, ( pWidth + m_width )->m_vertex ) );
double length = tex + ( vector3_length( v ) / fSize );
if ( fabs( length ) > texBest ) {
const double length = tex + ( vector3_length( pWidth->m_vertex - ( pWidth + m_width )->m_vertex ) / texSize );
if ( fabs( length ) > fabs( texBest ) ) {
texBest = length;
}
}

View File

@ -930,7 +930,8 @@ void RotateTexture( float angle );
void SetTextureRepeat( float s, float t ); // call with s=1 t=1 for FIT
void CapTexture();
void NaturalTexture();
Vector3 Calculate_AvgNormal();
Vector3 Calculate_AvgNormal() const;
void Calculate_AvgAxes( Vector3& wDir, Vector3& hDir ) const;
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 );

File diff suppressed because it is too large Load Diff