void Face_GetScale_BrushPrimit(face_t *face, float *s, float *t, float *rot) { idVec3D texS, texT; ComputeAxisBase(face->plane.Normal(), texS, texT); if (face == NULL || face->face_winding == NULL) { return; } // find ST coordinates for the center of the face double Os = 0, Ot = 0; for (int i = 0; i < face->face_winding->GetNumPoints(); i++) { Os += DotProduct((*face->face_winding)[i], texS); Ot += DotProduct((*face->face_winding)[i], texT); } Os /= face->face_winding->GetNumPoints(); Ot /= face->face_winding->GetNumPoints(); brushprimit_texdef_t *pBP = &face->brushprimit_texdef; // here we have a special case, M is a translation and it's inverse is easy float BPO[2][3]; float aux[2][3]; float m[2][3]; memset(&m, 0, sizeof (float) *6); m[0][0] = 1; m[1][1] = 1; m[0][2] = -Os; m[1][2] = -Ot; BPMatMul(m, pBP->coords, aux); m[0][2] = Os; m[1][2] = Ot; // now M^-1 BPMatMul(aux, m, BPO); // apply a given scale (on S and T) ConvertTexMatWithQTexture(BPO, face->d_texture, aux, NULL); *s = idMath::Sqrt(aux[0][0] * aux[0][0] + aux[1][0] * aux[1][0]); *t = idMath::Sqrt(aux[0][1] * aux[0][1] + aux[1][1] * aux[1][1]); // compute rotate value if (idMath::Fabs(face->brushprimit_texdef.coords[0][0]) < ZERO_EPSILON) { // rotate is +-90 if (face->brushprimit_texdef.coords[1][0] > 0) { *rot = 90.0f; } else { *rot = -90.0f; } } else { *rot = RAD2DEG(atan2(face->brushprimit_texdef.coords[1][0] / (*s) ? (*s) : 1.0f, face->brushprimit_texdef.coords[0][0] / (*t) ? (*t) : 1.0f)); } }
/* ======================================================================================================================= ======================================================================================================================= */ void BPMatRotate(float A[2][3], float theta) { float m[2][3]; float aux[2][3]; memset(&m, 0, sizeof (float) *6); m[0][0] = cos( DEG2RAD( theta ) ); m[0][1] = -sin( DEG2RAD( theta ) ); m[1][0] = -m[0][1]; m[1][1] = m[0][0]; BPMatMul(A, m, aux); BPMatCopy(aux, A); }
/* ======================================================================================================================= ======================================================================================================================= */ void Face_SetExplicitScale_BrushPrimit(face_t *face, float s, float t) { idVec3D texS, texT; ComputeAxisBase(face->plane.Normal(), texS, texT); // find ST coordinates for the center of the face double Os = 0, Ot = 0; for (int i = 0; i < face->face_winding->GetNumPoints(); i++) { Os += DotProduct((*face->face_winding)[i], texS); Ot += DotProduct((*face->face_winding)[i], texT); } Os /= face->face_winding->GetNumPoints(); Ot /= face->face_winding->GetNumPoints(); brushprimit_texdef_t *pBP = &face->brushprimit_texdef; // here we have a special case, M is a translation and it's inverse is easy float BPO[2][3]; float aux[2][3]; float m[2][3]; memset(&m, 0, sizeof (float) *6); m[0][0] = 1; m[1][1] = 1; m[0][2] = -Os; m[1][2] = -Ot; BPMatMul(m, pBP->coords, aux); m[0][2] = Os; m[1][2] = Ot; // now M^-1 BPMatMul(aux, m, BPO); // apply a given scale (on S and T) ConvertTexMatWithQTexture(BPO, face->d_texture, aux, NULL); // reset the scale (normalize the matrix) double v1, v2; v1 = idMath::Sqrt(aux[0][0] * aux[0][0] + aux[1][0] * aux[1][0]); v2 = idMath::Sqrt(aux[0][1] * aux[0][1] + aux[1][1] * aux[1][1]); if (s == 0.0) { s = v1; } if (t == 0.0) { t = v2; } double sS, sT; // put the values for scale on S and T here: sS = s / v1; sT = t / v2; aux[0][0] *= sS; aux[1][0] *= sS; aux[0][1] *= sT; aux[1][1] *= sT; ConvertTexMatWithQTexture(aux, NULL, BPO, face->d_texture); BPMatMul(m, BPO, aux); // m is M^-1 m[0][2] = -Os; m[1][2] = -Ot; BPMatMul(aux, m, pBP->coords); // now emit the coordinates on the winding EmitBrushPrimitTextureCoordinates(face, face->face_winding); }
// experimental stuff, work directly on BP static void OnTest( GtkWidget *widget, gpointer data ){ if ( !g_qeglobals.m_bBrushPrimitMode ) { Sys_FPrintf( SYS_WRN, "BP mode required\n" ); return; } if ( g_ptrSelectedFaces.GetSize() != 1 ) { Sys_FPrintf( SYS_WRN, "Expected single face selection\n" ); return; } brush_t *b = reinterpret_cast<brush_t*>( g_ptrSelectedFaceBrushes.GetAt( 0 ) ); face_t *selFace = reinterpret_cast<face_t*>( g_ptrSelectedFaces.GetAt( 0 ) ); // get the ST axis base for the face vec3_t texS,texT; ComputeAxisBase( selFace->plane.normal, texS, texT ); // find ST coordinates for the center of the face float Os = 0,Ot = 0; int i; for ( i = 0; i < selFace->face_winding->numpoints; i++ ) { Os += DotProduct( selFace->face_winding->points[i],texS ); Ot += DotProduct( selFace->face_winding->points[i],texT ); } Os /= selFace->face_winding->numpoints; Ot /= selFace->face_winding->numpoints; brushprimit_texdef_t *pBP = &selFace->brushprimit_texdef; // (FIXME: initial version, before axis base change optimize) // we need to compute our BP matrix in this new axis base (O,texS,texT) // the general case if BPO = M * BP * M^-1 // where BPO is transformation expressed in (O,texS,texT) // M is the axis base change from (origin,texS,texT) to (O,texS,texT) // here we have a special case, M is a translation and it's inverse is easy vec_t BPO[2][3]; vec_t aux[2][3]; vec_t m[2][3]; memset( &m, 0, sizeof( vec_t ) * 6 ); m[0][0] = 1; m[1][1] = 1; m[0][2] = -Os; m[1][2] = -Ot; BPMatMul( m, pBP->coords, aux ); m[0][2] = Os; m[1][2] = Ot; // now M^-1 BPMatMul( aux, m, BPO ); #if 0 // apply a scaling // scale factors against S and T axis, we apply on top of the existing matrix // <1 will decrease the texel/world resolution, >1 will increase float sS = 1.025,sT = 1.025; BPMatScale( BPO,sS,sT ); #endif #if 0 // apply a rotation float theta = 5; BPMatRotate( BPO,theta ); #endif #if 0 // read the scale ConvertTexMatWithQTexture( BPO, selFace->d_texture, aux, NULL ); // reset the scale (normalize the matrix) vec_t v1,v2; v1 = sqrt( aux[0][0] * aux[0][0] + aux[1][0] * aux[1][0] ); v2 = sqrt( aux[0][1] * aux[0][1] + aux[1][1] * aux[1][1] ); // if reading the scale values, we have them here: Sys_Printf( "Current Scale: S: %g T: %g\n", v1, v2 ); return; #endif #if 1 // apply a given scale (on S and T) ConvertTexMatWithQTexture( BPO, selFace->d_texture, aux, NULL ); // reset the scale (normalize the matrix) vec_t v1,v2; v1 = sqrt( aux[0][0] * aux[0][0] + aux[1][0] * aux[1][0] ); v2 = sqrt( aux[0][1] * aux[0][1] + aux[1][1] * aux[1][1] ); vec_t sS,sT; // put the values for scale on S and T here: sS = 1.2 / v1; sT = 0.8 / v2; aux[0][0] *= sS; aux[1][0] *= sS; aux[0][1] *= sT; aux[1][1] *= sT; ConvertTexMatWithQTexture( aux, NULL, BPO, selFace->d_texture ); #endif // now BPO must be expressed back in (origin,texS,texT) axis base BP = M^-1 * BPO * M BPMatMul( m, BPO, aux ); // m is M^-1 m[0][2] = -Os; m[1][2] = -Ot; BPMatMul( aux, m, pBP->coords ); // now emit the coordinates on the winding EmitBrushPrimitTextureCoordinates( selFace, selFace->face_winding ); Sys_UpdateWindows( W_CAMERA ); }