Skip to content

Commit 64ea4f7

Browse files
committed
Add PBR material support for planar texture alignment
1 parent e81b1de commit 64ea4f7

File tree

3 files changed

+179
-12
lines changed

3 files changed

+179
-12
lines changed

indra/newview/llface.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,61 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs
10711071
return true;
10721072
}
10731073

1074+
// Overload that returns the necessary texture transform using provided transform parameters
1075+
bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offset,
1076+
LLVector2* res_st_scale, F32* res_st_rot,
1077+
F32 map_rot, F32 map_scaleS, F32 map_scaleT,
1078+
F32 map_offsS, F32 map_offsT) const
1079+
{
1080+
if (!align_to)
1081+
{
1082+
return false;
1083+
}
1084+
const LLTextureEntry* tep = getTextureEntry();
1085+
if (!tep)
1086+
{
1087+
return false;
1088+
}
1089+
const LLTextureEntry* orig_tep = align_to->getTextureEntry();
1090+
if (!orig_tep)
1091+
{
1092+
return false;
1093+
}
1094+
if ((orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) ||
1095+
(tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR))
1096+
{
1097+
return false;
1098+
}
1099+
1100+
LLVector3 orig_pos, this_pos;
1101+
LLQuaternion orig_face_rot, this_face_rot;
1102+
F32 orig_proj_scale, this_proj_scale;
1103+
align_to->getPlanarProjectedParams(&orig_face_rot, &orig_pos, &orig_proj_scale);
1104+
getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale);
1105+
1106+
// The rotation of "this face's" texture:
1107+
LLQuaternion orig_st_rot = LLQuaternion(map_rot, LLVector3::z_axis) * orig_face_rot;
1108+
LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot;
1109+
F32 x_ang, y_ang, z_ang;
1110+
this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang);
1111+
*res_st_rot = z_ang;
1112+
1113+
// Offset and scale of "this face's" texture:
1114+
LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot;
1115+
LLVector3 st_scale(map_scaleS, map_scaleT, 1.f);
1116+
st_scale *= orig_proj_scale;
1117+
centers_dist.scaleVec(st_scale);
1118+
LLVector2 orig_st_offset(map_offsS, map_offsT);
1119+
1120+
*res_st_offset = orig_st_offset + (LLVector2)centers_dist;
1121+
res_st_offset->mV[VX] -= (S32)res_st_offset->mV[VX];
1122+
res_st_offset->mV[VY] -= (S32)res_st_offset->mV[VY];
1123+
1124+
st_scale /= this_proj_scale;
1125+
*res_st_scale = (LLVector2)st_scale;
1126+
return true;
1127+
}
1128+
10741129
void LLFace::updateRebuildFlags()
10751130
{
10761131
if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME))

indra/newview/llface.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ class alignas(16) LLFace
113113
void getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const;
114114
bool calcAlignedPlanarTE(const LLFace* align_to, LLVector2* st_offset,
115115
LLVector2* st_scale, F32* st_rot, LLRender::eTexIndex map = LLRender::DIFFUSE_MAP) const;
116+
bool calcAlignedPlanarTE(const LLFace* align_to, LLVector2* st_offset,
117+
LLVector2* st_scale, F32* st_rot,
118+
F32 map_rot, F32 map_scaleS, F32 map_scaleT,
119+
F32 map_offsS, F32 map_offsT) const;
116120

117121
U32 getState() const { return mState; }
118122
void setState(U32 state) { mState |= state; }

indra/newview/llpanelface.cpp

Lines changed: 120 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -806,9 +806,11 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor
806806
// Functor that aligns a face to mCenterFace
807807
struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor
808808
{
809-
LLPanelFaceSetAlignedTEFunctor(LLPanelFace* panel, LLFace* center_face) :
809+
LLPanelFaceSetAlignedTEFunctor(LLPanelFace* panel, LLFace* center_face, bool use_pbr, LLGLTFMaterial::TextureInfo pbr_channel) :
810810
mPanel(panel),
811-
mCenterFace(center_face) {}
811+
mCenterFace(center_face),
812+
mUsePBR(use_pbr),
813+
mPBRChannel(pbr_channel) {}
812814

813815
virtual bool apply(LLViewerObject* object, S32 te)
814816
{
@@ -832,7 +834,45 @@ struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor
832834
{
833835
LLVector2 uv_offset, uv_scale;
834836
F32 uv_rot;
835-
set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot);
837+
838+
// For PBR materials, use transform values from the material override
839+
if (mUsePBR && mCenterFace)
840+
{
841+
LLViewerObject* center_obj = mCenterFace->getViewerObject();
842+
S32 center_te = mCenterFace->getTEOffset();
843+
const LLTextureEntry* center_tep = center_obj->getTE(center_te);
844+
const LLGLTFMaterial* center_mat = center_tep ? center_tep->getGLTFMaterialOverride() : nullptr;
845+
846+
if (center_mat)
847+
{
848+
// Determine which channel to use based on selection
849+
U32 channel_idx = (mPBRChannel == LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT) ?
850+
LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR : mPBRChannel;
851+
852+
// Get PBR transform values
853+
F32 pbr_rot = center_mat->mTextureTransform[channel_idx].mRotation;
854+
F32 pbr_scale_u = center_mat->mTextureTransform[channel_idx].mScale.mV[VX];
855+
F32 pbr_scale_v = center_mat->mTextureTransform[channel_idx].mScale.mV[VY];
856+
F32 pbr_offset_u = center_mat->mTextureTransform[channel_idx].mOffset.mV[VX];
857+
F32 pbr_offset_v = center_mat->mTextureTransform[channel_idx].mOffset.mV[VY];
858+
859+
// Calculate alignment using PBR transform parameters
860+
set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot,
861+
pbr_rot, pbr_scale_u, pbr_scale_v,
862+
pbr_offset_u, pbr_offset_v);
863+
}
864+
else
865+
{
866+
// No PBR material, fall back to standard calculation
867+
set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot);
868+
}
869+
}
870+
else
871+
{
872+
// For Blinn-Phong materials, use standard calculation
873+
set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot);
874+
}
875+
836876
if (set_aligned)
837877
{
838878
object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]);
@@ -851,18 +891,61 @@ struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor
851891
LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
852892
LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
853893
LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
894+
895+
// Also handle PBR materials if selected
896+
if (mUsePBR)
897+
{
898+
LLGLTFMaterial new_override;
899+
const LLTextureEntry* tep = object->getTE(te);
900+
if (tep->getGLTFMaterialOverride())
901+
{
902+
new_override = *tep->getGLTFMaterialOverride();
903+
}
904+
905+
// If channel is COUNT (4), it means "Complete material" is selected - align ALL channels
906+
if (mPBRChannel == LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT)
907+
{
908+
// Align all 4 PBR texture channels
909+
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
910+
{
911+
new_override.mTextureTransform[i].mScale.mV[VX] = uv_scale.mV[VX];
912+
new_override.mTextureTransform[i].mScale.mV[VY] = uv_scale.mV[VY];
913+
new_override.mTextureTransform[i].mRotation = uv_rot;
914+
new_override.mTextureTransform[i].mOffset.mV[VX] = uv_offset.mV[VX];
915+
new_override.mTextureTransform[i].mOffset.mV[VY] = uv_offset.mV[VY];
916+
}
917+
}
918+
else
919+
{
920+
// Align only the selected channel
921+
new_override.mTextureTransform[mPBRChannel].mScale.mV[VX] = uv_scale.mV[VX];
922+
new_override.mTextureTransform[mPBRChannel].mScale.mV[VY] = uv_scale.mV[VY];
923+
new_override.mTextureTransform[mPBRChannel].mRotation = uv_rot;
924+
new_override.mTextureTransform[mPBRChannel].mOffset.mV[VX] = uv_offset.mV[VX];
925+
new_override.mTextureTransform[mPBRChannel].mOffset.mV[VY] = uv_offset.mV[VY];
926+
}
927+
928+
LLGLTFMaterialList::queueModify(object, te, &new_override);
929+
}
854930
}
855931
}
856932
if (!set_aligned)
857933
{
858-
LLPanelFaceSetTEFunctor setfunc(mPanel);
859-
setfunc.apply(object, te);
934+
// For center face or non-alignable faces, apply current panel settings
935+
// But DON'T overwrite PBR center face with Blinn-Phong values
936+
if (!(mUsePBR && facep == mCenterFace))
937+
{
938+
LLPanelFaceSetTEFunctor setfunc(mPanel);
939+
setfunc.apply(object, te);
940+
}
860941
}
861942
return true;
862943
}
863944
private:
864945
LLPanelFace* mPanel;
865946
LLFace* mCenterFace;
947+
bool mUsePBR;
948+
LLGLTFMaterial::TextureInfo mPBRChannel;
866949
};
867950

868951
struct LLPanelFaceSetAlignedConcreteTEFunctor : public LLSelectedTEFunctor
@@ -998,12 +1081,23 @@ struct LLPanelFaceSendFunctor : public LLSelectedObjectFunctor
9981081

9991082
void LLPanelFace::sendTextureInfo()
10001083
{
1001-
if (mPlanarAlign->getValue().asBoolean())
1084+
bool planar_align = mPlanarAlign->getValue().asBoolean();
1085+
bool pbr_selected = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR;
1086+
1087+
if (planar_align)
10021088
{
10031089
LLFace* last_face = NULL;
1004-
bool identical_face =false;
1090+
bool identical_face = false;
10051091
LLSelectedTE::getFace(last_face, identical_face);
1006-
LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face);
1092+
1093+
// Get PBR texture info if PBR is selected
1094+
LLGLTFMaterial::TextureInfo pbr_channel = LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
1095+
if (pbr_selected)
1096+
{
1097+
pbr_channel = getPBRTextureInfo();
1098+
}
1099+
1100+
LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face, pbr_selected, pbr_channel);
10071101
LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
10081102
}
10091103
else
@@ -1022,8 +1116,22 @@ void LLPanelFace::alignTextureLayer()
10221116
bool identical_face = false;
10231117
LLSelectedTE::getFace(last_face, identical_face);
10241118

1025-
LLPanelFaceSetAlignedConcreteTEFunctor setfunc(this, last_face, static_cast<LLRender::eTexIndex>(mRadioMaterialType->getSelectedIndex()));
1026-
LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
1119+
bool pbr_selected = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR;
1120+
1121+
if (pbr_selected)
1122+
{
1123+
// Use unified functor with PBR support
1124+
LLGLTFMaterial::TextureInfo texture_info = getPBRTextureInfo();
1125+
LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face, true, texture_info);
1126+
LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
1127+
}
1128+
else
1129+
{
1130+
// Use existing concrete functor for Blinn-Phong specific alignment
1131+
S32 material_type = mRadioMaterialType->getSelectedIndex();
1132+
LLPanelFaceSetAlignedConcreteTEFunctor setfunc(this, last_face, static_cast<LLRender::eTexIndex>(material_type));
1133+
LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
1134+
}
10271135
}
10281136

10291137
void LLPanelFace::getState()
@@ -3616,7 +3724,7 @@ void LLPanelFace::onCommitMaterialBumpyRot()
36163724
LLFace* last_face = NULL;
36173725
bool identical_face = false;
36183726
LLSelectedTE::getFace(last_face, identical_face);
3619-
LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face);
3727+
LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face, false, LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT);
36203728
LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
36213729
}
36223730
else
@@ -3640,7 +3748,7 @@ void LLPanelFace::onCommitMaterialShinyRot()
36403748
LLFace* last_face = NULL;
36413749
bool identical_face = false;
36423750
LLSelectedTE::getFace(last_face, identical_face);
3643-
LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face);
3751+
LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face, false, LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT);
36443752
LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
36453753
}
36463754
else

0 commit comments

Comments
 (0)