binds...
	* ctrl + shift + m3/drag: project tex from face in tex clipboard to brushes(BP format) and curves

misc...
	* fixed and improved normal finding in patch texture autocap algorithm
	* removed axis cycling in patch cap texture; using autocap
	* patch cap texture: project, using brush texture projection math of current mapformat to make it seamless with brushes by default
	* Surface inspector->Project functions work for curves (in AP map format too)
This commit is contained in:
Garux 2017-08-02 09:47:05 +03:00
parent b0c4caa9d1
commit da43652df1
10 changed files with 225 additions and 46 deletions

View File

@ -598,6 +598,10 @@ void ProjectTexture( const Plane3& plane, const texdef_t& texdef, const Vector3*
Texdef_ProjectTexture( m_projection, m_shader.width(), m_shader.height(), plane, texdef, direction );
}
void ProjectTexture( const Plane3& plane, const TextureProjection& projection, const Vector3& normal ){
Texdef_ProjectTexture( m_projection, m_shader.width(), m_shader.height(), plane, projection, normal );
}
void fit( const Vector3& normal, const Winding& winding, float s_repeat, float t_repeat ){
Texdef_FitTexture( m_projection, m_shader.width(), m_shader.height(), normal, winding, s_repeat, t_repeat );
}
@ -1213,6 +1217,12 @@ void ProjectTexture( const texdef_t& texdef, const Vector3* direction ){
texdefChanged();
}
void ProjectTexture( const TextureProjection& projection, const Vector3& normal ){
undoSave();
m_texdef.ProjectTexture( m_plane.plane3(), projection, normal );
texdefChanged();
}
void FitTexture( float s_repeat, float t_repeat ){
undoSave();
m_texdef.fit( m_plane.plane3().normal(), m_winding, s_repeat, t_repeat );

View File

@ -256,6 +256,15 @@ void Texdef_basisForNormal( const TextureProjection& projection, const Vector3&
}
}
void Texdef_Construct_local2tex( const TextureProjection& projection, std::size_t width, std::size_t height, const Vector3& normal, Matrix4& local2tex ){
Texdef_toTransform( projection, (float)width, (float)height, local2tex );
{
Matrix4 xyz2st;
Texdef_basisForNormal( projection, normal, xyz2st );
matrix4_multiply_by_matrix4( local2tex, xyz2st );
}
}
void Texdef_EmitTextureCoordinates( const TextureProjection& projection, std::size_t width, std::size_t height, Winding& w, const Vector3& normal, const Matrix4& localToWorld ){
if ( w.numpoints < 3 ) {
return;
@ -1552,8 +1561,7 @@ void Q3_to_BP( const texdef_t& texdef, float width, float height, const Vector3&
/// for arbitrary texture projections
void Emit3TextureCoordinates( const texdef_t& texdef, std::size_t width, std::size_t height, const Vector3& normal, DoubleVector3 points[3], DoubleVector3 st[3], const Vector3* direction ){
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 ){
Texdef_toTransform( texdef, (float)width, (float)height, local2tex );
{
if( direction ){ //arbitrary
@ -1570,14 +1578,6 @@ void Emit3TextureCoordinates( const texdef_t& texdef, std::size_t width, std::si
matrix4_multiply_by_matrix4( local2tex, xyz2st );
}
}
for ( std::size_t i = 0; i < 3; ++i )
{
DoubleVector3 texcoord = matrix4_transformed_point( local2tex, points[i] );
//globalOutputStream() << texcoord << "\n";
st[i][0] = texcoord[0];
st[i][1] = texcoord[1];
}
}
void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const texdef_t& texdef, const Vector3* direction ){
@ -1602,7 +1602,16 @@ void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, st
points[0] = anchor;
points[1] = texX + anchor;
points[2] = texY + anchor;
Emit3TextureCoordinates( texdef, width, height, plane.normal(), points, st, direction );
Matrix4 local2tex;
Texdef_Construct_local2tex4projection( texdef, width, height, plane.normal(), direction, local2tex );
for ( std::size_t i = 0; i < 3; ++i )
{
DoubleVector3 texcoord = matrix4_transformed_point( local2tex, points[i] );
//globalOutputStream() << texcoord << "\n";
st[i][0] = texcoord[0];
st[i][1] = texcoord[1];
}
// compute texture matrix
projection.m_brushprimit_texdef.coords[0][2] = st[0][0];
projection.m_brushprimit_texdef.coords[1][2] = st[0][1];
@ -1613,3 +1622,55 @@ void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, st
Texdef_normalise( projection, (float)width, (float)height );
}
void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, TextureProjection other_proj, const Vector3& other_normal ){
if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) {
other_proj.m_brushprimit_texdef.addScale( width, height );
DoubleVector3 texX, texY;
// compute axis base
ComputeAxisBase( plane.normal(), texX, texY );
// compute projection vector
const DoubleVector3 anchor = plane.normal() * plane.dist();
// (0,0) in plane axis base is (0,0,0) in world coordinates + projection on the affine plane
// (1,0) in plane axis base is texX in world coordinates + projection on the affine plane
// (0,1) in plane axis base is texY in world coordinates + projection on the affine plane
// use old texture code to compute the ST coords of these points
// ST of (0,0) (1,0) (0,1)
DoubleVector3 points[3];
DoubleVector3 st[3];
points[0] = anchor;
points[1] = texX + anchor;
points[2] = texY + anchor;
Matrix4 local2tex;
Texdef_Construct_local2tex( other_proj, width, height, other_normal, local2tex );
for ( std::size_t i = 0; i < 3; ++i )
{
DoubleVector3 texcoord = matrix4_transformed_point( local2tex, points[i] );
//globalOutputStream() << texcoord << "\n";
st[i][0] = texcoord[0];
st[i][1] = texcoord[1];
}
// compute texture matrix
projection.m_brushprimit_texdef.coords[0][2] = st[0][0];
projection.m_brushprimit_texdef.coords[1][2] = st[0][1];
projection.m_brushprimit_texdef.coords[0][0] = st[1][0] - st[0][0];
projection.m_brushprimit_texdef.coords[1][0] = st[1][1] - st[0][1];
projection.m_brushprimit_texdef.coords[0][1] = st[2][0] - st[0][0];
projection.m_brushprimit_texdef.coords[1][1] = st[2][1] - st[0][1];
Texdef_normalise( projection, (float)width, (float)height );
}
else
{
Texdef_Assign( projection.m_texdef, other_proj.m_texdef );
if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE ) {
projection.m_basis_s = other_proj.m_basis_s;
projection.m_basis_t = other_proj.m_basis_t;
}
}
}

View File

@ -107,7 +107,10 @@ 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 );
void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const texdef_t& texdef, const Vector3* direction );
void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, TextureProjection other_proj, const Vector3& other_normal );
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 );
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_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

@ -168,7 +168,7 @@ void BezierCurveTree_FromCurveList( BezierCurveTree *pTree, GSList *pCurveList,
}
int Patch::m_CycleCapIndex = 0;
//int Patch::m_CycleCapIndex = 0;
void Patch::setDims( std::size_t w, std::size_t h ){
@ -600,12 +600,31 @@ 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;
}
for ( std::size_t i = 0; i < m_width; ++i ){
hDir += ctrlAt( m_height - 1, i ).m_vertex - ctrlAt( 0, i ).m_vertex;
}
Vector3 normal( vector3_cross( wDir, hDir ) );
if ( vector3_equal( normal, g_vector3_identity ) ) {
normal = Vector3( 0, 0, 1 );
}
else{
vector3_normalise( normal );
}
return normal;
}
inline int texture_axis( const Vector3& normal ){
// axis dominance order: Z, X, Y
return ( normal.x() >= normal.y() ) ? ( normal.x() > normal.z() ) ? 0 : 2 : ( normal.y() > normal.z() ) ? 1 : 2;
}
void Patch::CapTexture(){
#if 0
const PatchControl& p1 = m_ctrl[m_width];
const PatchControl& p2 = m_ctrl[m_width * ( m_height - 1 )];
const PatchControl& p3 = m_ctrl[( m_width * m_height ) - 1];
@ -636,6 +655,12 @@ void Patch::CapTexture(){
normal[2] = fabs( normal[2] );
ProjectTexture( texture_axis( normal ) );
#else
Vector3 normal = Calculate_AvgNormal();
TextureProjection projection;
TexDef_Construct_Default( projection );
ProjectTexture( projection, normal );
#endif
}
// uses longest parallel chord to calculate texture coords for each row/col
@ -1125,7 +1150,7 @@ void Patch::ConstructSeam( EPatchCap eType, Vector3* p, std::size_t width ){
CapTexture();
controlPointsChanged();
}
#if 0
void Patch::ProjectTexture( int nAxis ){
undoSave();
@ -1161,6 +1186,41 @@ void Patch::ProjectTexture( int nAxis ){
controlPointsChanged();
}
#else
void Patch::ProjectTexture( TextureProjection projection, const Vector3& normal ){
undoSave();
projection.m_brushprimit_texdef.addScale( m_state->getTexture().width, m_state->getTexture().height );
Matrix4 local2tex;
Texdef_Construct_local2tex( projection, m_state->getTexture().width, m_state->getTexture().height, normal, local2tex );
for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i )
{
Vector3 texcoord = matrix4_transformed_point( local2tex, ( *i ).m_vertex );
( *i ).m_texcoord[0] = texcoord[0];
( *i ).m_texcoord[1] = texcoord[1];
}
controlPointsChanged();
}
#endif
void Patch::ProjectTexture( const texdef_t& texdef, const Vector3* direction ){
undoSave();
Matrix4 local2tex;
Texdef_Construct_local2tex4projection( texdef, m_state->getTexture().width, m_state->getTexture().height, Calculate_AvgNormal(), direction, local2tex );
for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i )
{
Vector3 texcoord = matrix4_transformed_point( local2tex, ( *i ).m_vertex );
( *i ).m_texcoord[0] = texcoord[0];
( *i ).m_texcoord[1] = texcoord[1];
}
controlPointsChanged();
}
void Patch::constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height ){
setDims( width, height );

View File

@ -64,6 +64,8 @@
#include "xml/ixml.h"
#include "dragplanes.h"
#include "brush_primit.h"
enum EPatchType
{
ePatchTypeQuake3,
@ -467,7 +469,7 @@ void construct(){
public:
Callback m_lightsChanged;
static int m_CycleCapIndex; // = 0;
//static int m_CycleCapIndex; // = 0;
static EPatchType m_type;
STRING_CONSTANT( Name, "Patch" );
@ -921,7 +923,9 @@ void RotateTexture( float angle );
void SetTextureRepeat( float s, float t ); // call with s=1 t=1 for FIT
void CapTexture();
void NaturalTexture();
void ProjectTexture( int nAxis );
Vector3 Calculate_AvgNormal();
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 );
void createThickenedWall(const Patch& sourcePatch, const Patch& targetPatch, const int wallIndex);

View File

@ -291,13 +291,31 @@ class PatchCapTexture
{
public:
void operator()( Patch& patch ) const {
patch.ProjectTexture( Patch::m_CycleCapIndex );
//patch.ProjectTexture( Patch::m_CycleCapIndex );
patch.CapTexture();
}
};
void Scene_PatchCapTexture_Selected( scene::Graph& graph ){
Scene_forEachVisibleSelectedPatch( PatchCapTexture() );
Patch::m_CycleCapIndex = ( Patch::m_CycleCapIndex + 1 ) % 3;
//Patch::m_CycleCapIndex = ( Patch::m_CycleCapIndex + 1 ) % 3;
SceneChangeNotify();
}
class PatchProjectTexture
{
const texdef_t& m_texdef;
const Vector3* m_direction;
public:
PatchProjectTexture( const texdef_t& texdef, const Vector3* direction ) : m_texdef( texdef ), m_direction( direction ) {
}
void operator()( Patch& patch ) const {
patch.ProjectTexture( m_texdef, m_direction );
}
};
void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction ){
Scene_forEachVisibleSelectedPatch( PatchProjectTexture( texdef, direction ) );
SceneChangeNotify();
}
@ -674,12 +692,6 @@ void Patch_Cap(){
Scene_PatchDoCap_Selected( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) );
}
void Patch_CycleProjection(){
UndoableCommand undo( "patchCycleUVProjectionAxis" );
Scene_PatchCapTexture_Selected( GlobalSceneGraph() );
}
///\todo Unfinished.
void Patch_OverlayOn(){
}
@ -849,7 +861,7 @@ void Patch_registerCommands(){
GlobalCommands_insert( "SmoothCols", FreeCaller<Patch_SmoothCols>(), Accelerator( 'W', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
GlobalCommands_insert( "MatrixTranspose", FreeCaller<Patch_Transpose>(), Accelerator( 'M', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
GlobalCommands_insert( "CapCurrentCurve", FreeCaller<Patch_Cap>(), Accelerator( 'C', (GdkModifierType)GDK_SHIFT_MASK ) );
GlobalCommands_insert( "CycleCapTexturePatch", FreeCaller<Patch_CycleProjection>(), Accelerator( 'N', (GdkModifierType)GDK_SHIFT_MASK ) );
GlobalCommands_insert( "PatchCapTexture", FreeCaller<Patch_CapTexture>(), Accelerator( 'N', (GdkModifierType)GDK_SHIFT_MASK ) );
// GlobalCommands_insert( "MakeOverlayPatch", FreeCaller<Patch_OverlayOn>(), Accelerator( 'Y' ) );
// GlobalCommands_insert( "ClearPatchOverlays", FreeCaller<Patch_OverlayOff>(), Accelerator( 'L', (GdkModifierType)GDK_CONTROL_MASK ) );
GlobalCommands_insert( "PatchDeform", FreeCaller<Patch_Deform>() );
@ -928,7 +940,7 @@ void Patch_constructMenu( GtkMenu* menu ){
if ( g_Layout_enableDetachableMenus.m_value ) {
menu_tearoff( menu_in_menu );
}
create_menu_item_with_mnemonic( menu_in_menu, "Cycle Projection", "CycleCapTexturePatch" );
create_menu_item_with_mnemonic( menu_in_menu, "Project", "PatchCapTexture" );
create_menu_item_with_mnemonic( menu_in_menu, "Naturalize", "NaturalizePatch" );
create_menu_item_with_mnemonic( menu_in_menu, "Invert X", "InvertCurveTextureX" );
create_menu_item_with_mnemonic( menu_in_menu, "Invert Y", "InvertCurveTextureY" );

View File

@ -42,6 +42,10 @@ void Scene_PatchFindReplaceShader( scene::Graph& graph, const char* find, const
void Scene_PatchFindReplaceShader_Selected( scene::Graph& graph, const char* find, const char* replace );
void Scene_PatchCapTexture_Selected( scene::Graph& graph );
class texdef_t;
template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3;
void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction );
void Scene_PatchNaturalTexture_Selected( scene::Graph& graph );
void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t );

View File

@ -891,6 +891,7 @@ void Select_Touching( void ){
void Select_ProjectTexture( const texdef_t& texdef, const Vector3* direction ){
if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) {
Scene_BrushProjectTexture_Selected( GlobalSceneGraph(), texdef, direction );
Scene_PatchProjectTexture_Selected( GlobalSceneGraph(), texdef, direction );
}
Scene_BrushProjectTexture_Component_Selected( GlobalSceneGraph(), texdef, direction );

View File

@ -4092,7 +4092,7 @@ const ModifierFlags c_modifier_toggle_face = c_modifier_toggle | c_modifier_face
const ModifierFlags c_modifier_replace_face = c_modifier_replace | c_modifier_face;
const ButtonIdentifier c_button_texture = c_buttonMiddle;
const ModifierFlags c_modifier_apply_texture1 = c_modifierControl | c_modifierShift;
const ModifierFlags c_modifier_apply_texture1_project = c_modifierControl | c_modifierShift;
const ModifierFlags c_modifier_apply_texture2_seamless = c_modifierControl;
const ModifierFlags c_modifier_apply_texture3 = c_modifierShift;
const ModifierFlags c_modifier_copy_texture = c_modifierNone;
@ -4100,7 +4100,8 @@ const ModifierFlags c_modifier_copy_texture = c_modifierNone;
void Scene_copyClosestTexture( SelectionTest& test );
void Scene_applyClosestTexture( SelectionTest& test, bool seamless );
void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project );
void Scene_projectClosestTexture( SelectionTest& test );
class TexManipulator_
{
@ -4118,10 +4119,10 @@ void mouseDown( DeviceVector position ){
ConstructSelectionTest( scissored, SelectionBoxForPoint( &position[0], &m_epsilon[0] ) );
SelectionVolume volume( scissored );
if ( m_state == c_modifier_apply_texture1 || m_state == c_modifier_apply_texture2_seamless || m_state == c_modifier_apply_texture3 ) {
if ( m_state == c_modifier_apply_texture1_project || m_state == c_modifier_apply_texture2_seamless || m_state == c_modifier_apply_texture3 ) {
m_undo_begun = true;
GlobalUndoSystem().start();
Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless );
Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless, m_state == c_modifier_apply_texture1_project );
}
else if ( m_state == c_modifier_copy_texture ) {
Scene_copyClosestTexture( volume );
@ -4134,14 +4135,14 @@ void mouseMoved( DeviceVector position ){
ConstructSelectionTest( scissored, SelectionBoxForPoint( &device_constrained( position )[0], &m_epsilon[0] ) );
SelectionVolume volume( scissored );
Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless );
Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless, m_state == c_modifier_apply_texture1_project );
}
}
typedef MemberCaller1<TexManipulator_, DeviceVector, &TexManipulator_::mouseMoved> MouseMovedCaller;
void mouseUp( DeviceVector position ){
if( m_undo_begun ){
GlobalUndoSystem().finish( "paintTexture" );
GlobalUndoSystem().finish( ( m_state == c_modifier_apply_texture1_project ) ? "projectTexture" : "paintTexture" );
m_undo_begun = false;
}
g_mouseMovedCallback.clear();

View File

@ -549,8 +549,8 @@ static void OnBtnReset( GtkWidget *widget, gpointer data ){
static void OnBtnProject( GtkWidget *widget, gpointer data ){
if ( g_bp_globals.m_texdefTypeId != TEXDEFTYPEID_BRUSHPRIMITIVES ) {
globalErrorStream() << "function is implemented for BRUSHPRIMITIVES map format only\n";
return;
globalErrorStream() << "function doesn't work for *brushes* in map formats other than BRUSHPRIMITIVES\n";
//return;
}
getSurfaceInspector().exportData();
SurfaceInspector_ProjectTexture();
@ -1453,7 +1453,7 @@ void Face_getTexture( Face& face, CopiedString& shader, TextureProjection& proje
typedef Function4<Face&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Face_getTexture> FaceGetTexture;
/* copied from winding.cpp */
inline bool float_is_largest_absolute( double axis, double other ){
return fabs( axis ) > fabs( other );
}
@ -1502,7 +1502,8 @@ void Face_setTexture_Seamless( Face& face, const char* shader, const TextureProj
face.SetShader( shader );
DoubleLine line = plane3_intersect_plane3( g_faceTextureClipboard.m_plane, face.getPlane().plane3() );
Quaternion rotation = Quaternion( vector3_cross( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ), static_cast<float>( 1.0 + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ) ) );
Quaternion rotation = Quaternion( vector3_cross( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ),
static_cast<float>( 1.0 + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ) ) );
//Quaternion rotation = quaternion_for_unit_vectors( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() );
//rotation.w() = sqrt( vector3_length_squared( g_faceTextureClipboard.m_plane.normal() ) * vector3_length_squared( face.getPlane().plane3().normal() ) ) + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() );
//globalOutputStream() << "rotation: " << rotation.x() << " " << rotation.y() << " " << rotation.z() << " " << rotation.w() << " " << "\n";
@ -1540,6 +1541,16 @@ void Face_setTexture_Seamless( Face& face, const char* shader, const TextureProj
typedef Function4<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture_Seamless> FaceSetTextureSeamless;
void Face_setTexture_Project( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
face.SetShader( shader );
//face.SetTexdef( projection );
face.SetFlags( flags );
face.ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() );
}
typedef Function4<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture_Project> FaceSetTextureProject;
void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
face.SetShader( shader );
face.SetTexdef( projection );
@ -1555,6 +1566,12 @@ void Patch_getTexture( Patch& patch, CopiedString& shader, TextureProjection& pr
}
typedef Function4<Patch&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Patch_getTexture> PatchGetTexture;
void Patch_setTexture_Project( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
patch.SetShader( shader );
patch.ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() );
}
typedef Function4<Patch&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Patch_setTexture_Project> PatchSetTextureProject;
void Patch_setTexture( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
patch.SetShader( shader );
}
@ -1571,7 +1588,7 @@ struct Texturable
};
void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable, bool seamless ){
void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable, bool seamless, bool project ){
if ( face.isFiltered() ) {
return;
}
@ -1580,7 +1597,9 @@ void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& be
if ( intersection.valid()
&& SelectionIntersection_closer( intersection, bestIntersection ) ) {
bestIntersection = intersection;
if( seamless )
if( project )
texturable.setTexture = makeCallback3( FaceSetTextureProject(), face );
else if( seamless )
texturable.setTexture = makeCallback3( FaceSetTextureSeamless(), face );
else
texturable.setTexture = makeCallback3( FaceSetTexture(), face );
@ -1614,9 +1633,10 @@ class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker
SelectionTest& m_test;
Texturable& m_texturable;
bool m_seamless;
bool m_project;
mutable SelectionIntersection m_bestIntersection;
public:
BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable, bool seamless ) : m_test( test ), m_texturable( texturable ), m_seamless( seamless ){
BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable, bool seamless, bool project ) : m_test( test ), m_texturable( texturable ), m_seamless( seamless ), m_project( project ){
}
bool pre( const scene::Path& path, scene::Instance& instance ) const {
if ( path.top().get().visible() ) {
@ -1626,7 +1646,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
for ( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i )
{
Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable, m_seamless );
Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable, m_seamless, m_project );
}
}
else
@ -1639,7 +1659,10 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
if ( occluded ) {
Patch* patch = Node_getPatch( path.top() );
if ( patch != 0 ) {
m_texturable.setTexture = makeCallback3( PatchSetTexture(), *patch );
if( m_project )
m_texturable.setTexture = makeCallback3( PatchSetTextureProject(), *patch );
else
m_texturable.setTexture = makeCallback3( PatchSetTexture(), *patch );
m_texturable.getTexture = makeCallback3( PatchGetTexture(), *patch );
}
else
@ -1657,9 +1680,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
}
};
Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test, bool seamless = false ){
Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test, bool seamless = false, bool project = false ){
Texturable texturable;
graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless ) );
graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless, project ) );
return texturable;
}
@ -1672,8 +1695,8 @@ bool Scene_getClosestTexture( scene::Graph& graph, SelectionTest& test, CopiedSt
return false;
}
void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags, bool seamless ){
Texturable texturable = Scene_getClosestTexturable( graph, test, seamless );
void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags, bool seamless, bool project ){
Texturable texturable = Scene_getClosestTexturable( graph, test, seamless, project );
if ( texturable.setTexture != SetTextureCallback() ) {
texturable.setTexture( shader, projection, flags );
}
@ -1694,10 +1717,10 @@ void Scene_copyClosestTexture( SelectionTest& test ){
}
}
void Scene_applyClosestTexture( SelectionTest& test, bool seamless ){
void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project ){
// UndoableCommand command( "facePaintTexture" );
Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless );
Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless, project );
SceneChangeNotify();
}