aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llface.cpp66
-rw-r--r--linden/indra/newview/llface.h3
-rw-r--r--linden/indra/newview/llpanelface.cpp161
-rw-r--r--linden/indra/newview/llpanelface.h1
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/floater_tools.xml4
5 files changed, 233 insertions, 2 deletions
diff --git a/linden/indra/newview/llface.cpp b/linden/indra/newview/llface.cpp
index dab1dac..aa8cd15 100644
--- a/linden/indra/newview/llface.cpp
+++ b/linden/indra/newview/llface.cpp
@@ -801,6 +801,72 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position,
801 return tc; 801 return tc;
802} 802}
803 803
804// Returns scale compared to default texgen, and face orientation as calculated
805// by planarProjection(). This is needed to match planar texgen parameters.
806void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const
807{
808 const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
809 LLVector3 normal = vf.mVertices[0].mNormal;
810 LLVector3 binormal = vf.mVertices[0].mBinormal;
811 LLVector2 projected_binormal;
812 planarProjection(projected_binormal, normal, vf.mCenter, binormal);
813 projected_binormal -= LLVector2(0.5f, 0.5f); // this normally happens in xform()
814 *scale = projected_binormal.length();
815 // rotate binormal to match what planarProjection() thinks it is,
816 // then find face's rotation from normal and rotated binormal:
817 projected_binormal.normalize();
818 F32 ang = acos(projected_binormal.mV[VY]);
819 ang = (projected_binormal.mV[VX] < 0.f) ? -ang : ang;
820 binormal.rotVec(ang, normal);
821 LLQuaternion local_rot( binormal % normal, binormal, normal );
822 *face_rot = local_rot * mXform->getWorldRotation();
823 *face_pos = mXform->getWorldPosition();
824}
825
826// Returns the necessary texture transform to align this face's TE to align_to's TE
827bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offset,
828 LLVector2* res_st_scale, F32* res_st_rot) const
829{
830 if (!align_to)
831 {
832 return false;
833 }
834 const LLTextureEntry *orig_tep = align_to->getTextureEntry();
835 if ((orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) ||
836 (getTextureEntry()->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR))
837 {
838 return false;
839 }
840
841 LLVector3 orig_pos, this_pos;
842 LLQuaternion orig_face_rot, this_face_rot;
843 F32 orig_proj_scale, this_proj_scale;
844 align_to->getPlanarProjectedParams(&orig_face_rot, &orig_pos, &orig_proj_scale);
845 getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale);
846
847 // The rotation of "this face's" texture:
848 LLQuaternion orig_st_rot = LLQuaternion(orig_tep->getRotation(), LLVector3::z_axis) * orig_face_rot;
849 LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot;
850 F32 x_ang, y_ang, z_ang;
851 this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang);
852 *res_st_rot = z_ang;
853
854 // Offset and scale of "this face's" texture:
855 LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot;
856 LLVector3 st_scale(orig_tep->mScaleS, orig_tep->mScaleT, 1.f);
857 st_scale *= orig_proj_scale;
858 centers_dist.scaleVec(st_scale);
859 LLVector2 orig_st_offset(orig_tep->mOffsetS, orig_tep->mOffsetT);
860
861 *res_st_offset = orig_st_offset + (LLVector2)centers_dist;
862 res_st_offset->mV[VX] -= (S32)res_st_offset->mV[VX];
863 res_st_offset->mV[VY] -= (S32)res_st_offset->mV[VY];
864
865 st_scale /= this_proj_scale;
866 *res_st_scale = (LLVector2)st_scale;
867 return true;
868}
869
804void LLFace::updateRebuildFlags() 870void LLFace::updateRebuildFlags()
805{ 871{
806 if (!mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) 872 if (!mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
diff --git a/linden/indra/newview/llface.h b/linden/indra/newview/llface.h
index 5e422b4..4893e82 100644
--- a/linden/indra/newview/llface.h
+++ b/linden/indra/newview/llface.h
@@ -93,6 +93,9 @@ public:
93 BOOL hasGeometry() const { return mGeomCount > 0; } 93 BOOL hasGeometry() const { return mGeomCount > 0; }
94 LLVector3 getPositionAgent() const; 94 LLVector3 getPositionAgent() const;
95 LLVector2 surfaceToTexture(LLVector2 surface_coord, LLVector3 position, LLVector3 normal); 95 LLVector2 surfaceToTexture(LLVector2 surface_coord, LLVector3 position, LLVector3 normal);
96 void getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const;
97 bool calcAlignedPlanarTE(const LLFace* align_to, LLVector2* st_offset,
98 LLVector2* st_scale, F32* st_rot) const;
96 99
97 U32 getState() const { return mState; } 100 U32 getState() const { return mState; }
98 void setState(U32 state) { mState |= state; } 101 void setState(U32 state) { mState |= state; }
diff --git a/linden/indra/newview/llpanelface.cpp b/linden/indra/newview/llpanelface.cpp
index 6ae2ffe..bd9edec 100644
--- a/linden/indra/newview/llpanelface.cpp
+++ b/linden/indra/newview/llpanelface.cpp
@@ -48,7 +48,9 @@
48#include "llcheckboxctrl.h" 48#include "llcheckboxctrl.h"
49#include "llcolorswatch.h" 49#include "llcolorswatch.h"
50#include "llcombobox.h" 50#include "llcombobox.h"
51#include "lldrawable.h"
51#include "lldrawpoolbump.h" 52#include "lldrawpoolbump.h"
53#include "llface.h"
52#include "lllineeditor.h" 54#include "lllineeditor.h"
53#include "llresmgr.h" 55#include "llresmgr.h"
54#include "llselectmgr.h" 56#include "llselectmgr.h"
@@ -173,6 +175,7 @@ BOOL LLPanelFace::postBuild()
173 175
174 childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this); 176 childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this);
175 childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this); 177 childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this);
178 childSetCommitCallback("checkbox planar align",&LLPanelFace::onCommitPlanarAlign, this);
176 childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this); 179 childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this);
177 childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this); 180 childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this);
178 childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this); 181 childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this);
@@ -364,6 +367,93 @@ private:
364 LLPanelFace* mPanel; 367 LLPanelFace* mPanel;
365}; 368};
366 369
370// Functor that aligns a face to mCenterFace
371struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor
372{
373 LLPanelFaceSetAlignedTEFunctor(LLPanelFace* panel, LLFace* center_face) :
374 mPanel(panel),
375 mCenterFace(center_face) {}
376
377 virtual bool apply(LLViewerObject* object, S32 te)
378 {
379 LLFace* facep = object->mDrawable->getFace(te);
380 if (!facep)
381 {
382 return true;
383 }
384
385 bool set_aligned = true;
386 if (facep == mCenterFace)
387 {
388 set_aligned = false;
389 }
390 if (set_aligned)
391 {
392 LLVector2 uv_offset, uv_scale;
393 F32 uv_rot;
394 set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot);
395 if (set_aligned)
396 {
397 object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]);
398 object->setTEScale(te, uv_scale.mV[VX], uv_scale.mV[VY]);
399 object->setTERotation(te, uv_rot);
400 }
401 }
402 if (!set_aligned)
403 {
404 LLPanelFaceSetTEFunctor setfunc(mPanel);
405 setfunc.apply(object, te);
406 }
407 return true;
408 }
409private:
410 LLPanelFace* mPanel;
411 LLFace* mCenterFace;
412};
413
414// Functor that tests if a face is aligned to mCenterFace
415struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor
416{
417 LLPanelFaceGetIsAlignedTEFunctor(LLFace* center_face) :
418 mCenterFace(center_face) {}
419
420 virtual bool apply(LLViewerObject* object, S32 te)
421 {
422 LLFace* facep = object->mDrawable->getFace(te);
423 if (!facep)
424 {
425 return false;
426 }
427 if (facep == mCenterFace)
428 {
429 return true;
430 }
431
432 LLVector2 aligned_st_offset, aligned_st_scale;
433 F32 aligned_st_rot;
434 if ( facep->calcAlignedPlanarTE(mCenterFace, &aligned_st_offset, &aligned_st_scale, &aligned_st_rot) )
435 {
436 const LLTextureEntry* tep = facep->getTextureEntry();
437 LLVector2 st_offset, st_scale;
438 tep->getOffset(&st_offset.mV[VX], &st_offset.mV[VY]);
439 tep->getScale(&st_scale.mV[VX], &st_scale.mV[VY]);
440 F32 st_rot = tep->getRotation();
441 // needs a fuzzy comparison, because of fp errors
442 if (is_approx_equal_fraction(st_offset.mV[VX], aligned_st_offset.mV[VX], 14) &&
443 is_approx_equal_fraction(st_offset.mV[VY], aligned_st_offset.mV[VY], 14) &&
444 is_approx_equal_fraction(st_scale.mV[VX], aligned_st_scale.mV[VX], 14) &&
445 is_approx_equal_fraction(st_scale.mV[VY], aligned_st_scale.mV[VY], 14) &&
446 is_approx_equal_fraction(st_rot, aligned_st_rot, 10))
447 {
448 return true;
449 }
450 }
451 return false;
452 }
453private:
454 LLFace* mCenterFace;
455};
456
367struct LLPanelFaceSendFunctor : public LLSelectedObjectFunctor 457struct LLPanelFaceSendFunctor : public LLSelectedObjectFunctor
368{ 458{
369 virtual bool apply(LLViewerObject* object) 459 virtual bool apply(LLViewerObject* object)
@@ -375,8 +465,26 @@ struct LLPanelFaceSendFunctor : public LLSelectedObjectFunctor
375 465
376void LLPanelFace::sendTextureInfo() 466void LLPanelFace::sendTextureInfo()
377{ 467{
378 LLPanelFaceSetTEFunctor setfunc(this); 468 if ((bool)childGetValue("checkbox planar align").asBoolean())
379 LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); 469 {
470 struct f1 : public LLSelectedTEGetFunctor<LLFace *>
471 {
472 LLFace* get(LLViewerObject* object, S32 te)
473 {
474 return (object->mDrawable) ? object->mDrawable->getFace(te): NULL;
475 }
476 } get_last_face_func;
477 LLFace* last_face;
478 LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_last_face_func, last_face);
479
480 LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face);
481 LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
482 }
483 else
484 {
485 LLPanelFaceSetTEFunctor setfunc(this);
486 LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
487 }
380 488
381 LLPanelFaceSendFunctor sendfunc; 489 LLPanelFaceSendFunctor sendfunc;
382 LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); 490 LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
@@ -483,6 +591,43 @@ void LLPanelFace::getState()
483 } 591 }
484 } 592 }
485 593
594 // planar align
595 bool align_planar = false;
596 bool identical_planar_aligned = false;
597 {
598 LLCheckBoxCtrl* cb_planar_align = getChild<LLCheckBoxCtrl>("checkbox planar align");
599 align_planar = (cb_planar_align && cb_planar_align->get());
600 struct f1 : public LLSelectedTEGetFunctor<bool>
601 {
602 bool get(LLViewerObject* object, S32 face)
603 {
604 return (object->getTE(face)->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR);
605 }
606 } func;
607
608 bool is_planar;
609 bool texgens_identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, is_planar );
610 bool enabled = (editable && texgens_identical && is_planar);
611 childSetValue("checkbox planar align", align_planar && enabled);
612 childSetEnabled("checkbox planar align", enabled);
613
614 if (align_planar && enabled)
615 {
616 struct f2 : public LLSelectedTEGetFunctor<LLFace *>
617 {
618 LLFace* get(LLViewerObject* object, S32 te)
619 {
620 return (object->mDrawable) ? object->mDrawable->getFace(te): NULL;
621 }
622 } get_te_face_func;
623 LLFace* last_face;
624 LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_te_face_func, last_face);
625 LLPanelFaceGetIsAlignedTEFunctor get_is_aligend_func(last_face);
626 // this will determine if the texture param controls are tentative:
627 identical_planar_aligned = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&get_is_aligend_func);
628 }
629 }
630
486 // Texture scale 631 // Texture scale
487 { 632 {
488 childSetEnabled("tex scale",editable); 633 childSetEnabled("tex scale",editable);
@@ -496,6 +641,7 @@ void LLPanelFace::getState()
496 } 641 }
497 } func; 642 } func;
498 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, scale_s ); 643 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, scale_s );
644 identical = align_planar ? identical_planar_aligned : identical;
499 childSetValue("TexScaleU",editable ? llabs(scale_s) : 0); 645 childSetValue("TexScaleU",editable ? llabs(scale_s) : 0);
500 childSetTentative("TexScaleU",LLSD((BOOL)(!identical))); 646 childSetTentative("TexScaleU",LLSD((BOOL)(!identical)));
501 childSetEnabled("TexScaleU",editable); 647 childSetEnabled("TexScaleU",editable);
@@ -514,6 +660,7 @@ void LLPanelFace::getState()
514 } 660 }
515 } func; 661 } func;
516 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, scale_t ); 662 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, scale_t );
663 identical = align_planar ? identical_planar_aligned : identical;
517 664
518 childSetValue("TexScaleV",llabs(editable ? llabs(scale_t) : 0)); 665 childSetValue("TexScaleV",llabs(editable ? llabs(scale_t) : 0));
519 childSetTentative("TexScaleV",LLSD((BOOL)(!identical))); 666 childSetTentative("TexScaleV",LLSD((BOOL)(!identical)));
@@ -535,6 +682,7 @@ void LLPanelFace::getState()
535 } 682 }
536 } func; 683 } func;
537 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, offset_s ); 684 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, offset_s );
685 identical = align_planar ? identical_planar_aligned : identical;
538 childSetValue("TexOffsetU", editable ? offset_s : 0); 686 childSetValue("TexOffsetU", editable ? offset_s : 0);
539 childSetTentative("TexOffsetU",!identical); 687 childSetTentative("TexOffsetU",!identical);
540 childSetEnabled("TexOffsetU",editable); 688 childSetEnabled("TexOffsetU",editable);
@@ -550,6 +698,7 @@ void LLPanelFace::getState()
550 } 698 }
551 } func; 699 } func;
552 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, offset_t ); 700 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, offset_t );
701 identical = align_planar ? identical_planar_aligned : identical;
553 childSetValue("TexOffsetV", editable ? offset_t : 0); 702 childSetValue("TexOffsetV", editable ? offset_t : 0);
554 childSetTentative("TexOffsetV",!identical); 703 childSetTentative("TexOffsetV",!identical);
555 childSetEnabled("TexOffsetV",editable); 704 childSetEnabled("TexOffsetV",editable);
@@ -567,6 +716,7 @@ void LLPanelFace::getState()
567 } 716 }
568 } func; 717 } func;
569 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, rotation ); 718 identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, rotation );
719 identical = align_planar ? identical_planar_aligned : identical;
570 childSetValue("TexRot", editable ? rotation * RAD_TO_DEG : 0); 720 childSetValue("TexRot", editable ? rotation * RAD_TO_DEG : 0);
571 childSetTentative("TexRot",!identical); 721 childSetTentative("TexRot",!identical);
572 childSetEnabled("TexRot",editable); 722 childSetEnabled("TexRot",editable);
@@ -999,6 +1149,13 @@ void LLPanelFace::onClickAutoFix(void* userdata)
999} 1149}
1000 1150
1001// static 1151// static
1152void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata)
1153{
1154 LLPanelFace* self = (LLPanelFace*) userdata;
1155 self->getState();
1156}
1157
1158// static
1002void LLPanelFace::onClickTextureConstants(void *) 1159void LLPanelFace::onClickTextureConstants(void *)
1003{ 1160{
1004 LLNotifications::instance().add("ClickTextureConstants"); 1161 LLNotifications::instance().add("ClickTextureConstants");
diff --git a/linden/indra/newview/llpanelface.h b/linden/indra/newview/llpanelface.h
index 33c84c8..8e4d4db 100644
--- a/linden/indra/newview/llpanelface.h
+++ b/linden/indra/newview/llpanelface.h
@@ -86,6 +86,7 @@ protected:
86 static void onCommitShiny( LLUICtrl* ctrl, void* userdata); 86 static void onCommitShiny( LLUICtrl* ctrl, void* userdata);
87 static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); 87 static void onCommitFullbright( LLUICtrl* ctrl, void* userdata);
88 static void onCommitGlow( LLUICtrl* ctrl, void *userdata); 88 static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
89 static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata);
89 90
90 static void onClickApply(void*); 91 static void onClickApply(void*);
91 static void onClickAutoFix(void*); 92 static void onClickAutoFix(void*);
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml b/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml
index ce08d4c..78eacf4 100644
--- a/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml
@@ -1157,6 +1157,10 @@
1157 weave 1157 weave
1158 </combo_item> 1158 </combo_item>
1159 </combo_box> 1159 </combo_box>
1160 <check_box bottom="-148" follows="left|top" font="SansSerifSmall" height="16"
1161 initial_value="false" enabled="false" label="Align across planar faces"
1162 left="8" mouse_opaque="true" name="checkbox planar align" width="160"
1163 tool_tip="When checked, aligns textures on all selected faces to the last selected face. Requires Planar texture mapping." />
1160 <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" 1164 <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
1161 bottom="-158" drop_shadow_visible="true" follows="left|top" 1165 bottom="-158" drop_shadow_visible="true" follows="left|top"
1162 font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10" 1166 font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10"