From 1d994e77020597bb09c8fcc968477cee46a79aa2 Mon Sep 17 00:00:00 2001 From: ruslantproductengine Date: Thu, 4 Apr 2019 19:18:50 +0300 Subject: SL-5570 - Align planar faces" does not work on normal or specular maps SL-10864 -Normal and Specular textures can be rotated with checked align planar faces checkbox Implement separate texture layers alignment. --- indra/newview/llface.cpp | 45 +++++- indra/newview/llface.h | 2 +- indra/newview/llpanelface.cpp | 155 ++++++++++++++++++--- indra/newview/llpanelface.h | 2 + .../skins/default/xui/en/panel_tools_texture.xml | 11 ++ 5 files changed, 193 insertions(+), 22 deletions(-) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index b2da5bb9f8..473e55ce82 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1106,7 +1106,7 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po // Returns the necessary texture transform to align this face's TE to align_to's TE bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offset, - LLVector2* res_st_scale, F32* res_st_rot) const + LLVector2* res_st_scale, F32* res_st_rot, LLRender::eTexIndex map) const { if (!align_to) { @@ -1119,6 +1119,43 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs return false; } + F32 map_rot = 0.f, map_scaleS = 0.f, map_scaleT = 0.f, map_offsS = 0.f, map_offsT = 0.f; + + switch (map) + { + case LLRender::DIFFUSE_MAP: + map_rot = orig_tep->getRotation(); + map_scaleS = orig_tep->mScaleS; + map_scaleT = orig_tep->mScaleT; + map_offsS = orig_tep->mOffsetS; + map_offsT = orig_tep->mOffsetT; + break; + case LLRender::NORMAL_MAP: + if (orig_tep->getMaterialParams()->getNormalID().isNull()) + { + return false; + } + map_rot = orig_tep->getMaterialParams()->getNormalRotation(); + map_scaleS = orig_tep->getMaterialParams()->getNormalRepeatX(); + map_scaleT = orig_tep->getMaterialParams()->getNormalRepeatY(); + map_offsS = orig_tep->getMaterialParams()->getNormalOffsetX(); + map_offsT = orig_tep->getMaterialParams()->getNormalOffsetY(); + break; + case LLRender::SPECULAR_MAP: + if (orig_tep->getMaterialParams()->getSpecularID().isNull()) + { + return false; + } + map_rot = orig_tep->getMaterialParams()->getSpecularRotation(); + map_scaleS = orig_tep->getMaterialParams()->getSpecularRepeatX(); + map_scaleT = orig_tep->getMaterialParams()->getSpecularRepeatY(); + map_offsS = orig_tep->getMaterialParams()->getSpecularOffsetX(); + map_offsT = orig_tep->getMaterialParams()->getSpecularOffsetY(); + break; + default: /*make compiler happy*/ + break; + } + LLVector3 orig_pos, this_pos; LLQuaternion orig_face_rot, this_face_rot; F32 orig_proj_scale, this_proj_scale; @@ -1126,7 +1163,7 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale); // The rotation of "this face's" texture: - LLQuaternion orig_st_rot = LLQuaternion(orig_tep->getRotation(), LLVector3::z_axis) * orig_face_rot; + LLQuaternion orig_st_rot = LLQuaternion(map_rot, LLVector3::z_axis) * orig_face_rot; LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot; F32 x_ang, y_ang, z_ang; this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang); @@ -1134,10 +1171,10 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs // Offset and scale of "this face's" texture: LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot; - LLVector3 st_scale(orig_tep->mScaleS, orig_tep->mScaleT, 1.f); + LLVector3 st_scale(map_scaleS, map_scaleT, 1.f); st_scale *= orig_proj_scale; centers_dist.scaleVec(st_scale); - LLVector2 orig_st_offset(orig_tep->mOffsetS, orig_tep->mOffsetT); + LLVector2 orig_st_offset(map_offsS, map_offsT); *res_st_offset = orig_st_offset + (LLVector2)centers_dist; res_st_offset->mV[VX] -= (S32)res_st_offset->mV[VX]; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 736d45b7ad..10c2b31b6f 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -114,7 +114,7 @@ public: LLVector2 surfaceToTexture(LLVector2 surface_coord, const LLVector4a& position, const LLVector4a& normal); void getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const; bool calcAlignedPlanarTE(const LLFace* align_to, LLVector2* st_offset, - LLVector2* st_scale, F32* st_rot) const; + LLVector2* st_scale, F32* st_rot, LLRender::eTexIndex map = LLRender::DIFFUSE_MAP) const; U32 getState() const { return mState; } void setState(U32 state) { mState |= state; } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 5e6a44c09d..5cbd1e2f99 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -82,6 +82,8 @@ const S32 ALPHAMODE_MASK = 2; // Alpha masking mode const S32 BUMPY_TEXTURE = 18; // use supplied normal map const S32 SHINY_TEXTURE = 4; // use supplied specular map +BOOST_STATIC_ASSERT(MATTYPE_DIFFUSE == LLRender::DIFFUSE_MAP && MATTYPE_NORMAL == LLRender::NORMAL_MAP && MATTYPE_SPECULAR == LLRender::SPECULAR_MAP); + // // "Use texture" label for normal/specular type comboboxes // Filled in at initialization from translated strings @@ -154,6 +156,7 @@ BOOL LLPanelFace::postBuild() childSetCommitCallback("maskcutoff",&LLPanelFace::onCommitMaterialMaskCutoff, this); childSetAction("button align",&LLPanelFace::onClickAutoFix,this); + childSetAction("button align textures", &LLPanelFace::onAlignTexture, this); LLTextureCtrl* mTextureCtrl; LLTextureCtrl* mShinyTextureCtrl; @@ -439,11 +442,28 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor { BOOL valid; F32 value; - LLSpinCtrl* ctrlTexScaleS = mPanel->getChild("TexScaleU"); - LLSpinCtrl* ctrlTexScaleT = mPanel->getChild("TexScaleV"); - LLSpinCtrl* ctrlTexOffsetS = mPanel->getChild("TexOffsetU"); - LLSpinCtrl* ctrlTexOffsetT = mPanel->getChild("TexOffsetV"); - LLSpinCtrl* ctrlTexRotation = mPanel->getChild("TexRot"); + + LLRadioGroup * radio_mat_type = mPanel->getChild("radio_material_type"); + std::string prefix; + switch (radio_mat_type->getSelectedIndex()) + { + case MATTYPE_DIFFUSE: + prefix = "Tex"; + break; + case MATTYPE_NORMAL: + prefix = "bumpy"; + break; + case MATTYPE_SPECULAR: + prefix = "shiny"; + break; + } + + LLSpinCtrl * ctrlTexScaleS = mPanel->getChild(prefix + "ScaleU"); + LLSpinCtrl * ctrlTexScaleT = mPanel->getChild(prefix + "ScaleV"); + LLSpinCtrl * ctrlTexOffsetS = mPanel->getChild(prefix + "OffsetU"); + LLSpinCtrl * ctrlTexOffsetT = mPanel->getChild(prefix + "OffsetV"); + LLSpinCtrl * ctrlTexRotation = mPanel->getChild(prefix + "Rot"); + LLComboBox* comboTexGen = mPanel->getChild("combobox texgen"); LLCheckBoxCtrl* cb_planar_align = mPanel->getChild("checkbox planar align"); bool align_planar = (cb_planar_align && cb_planar_align->get()); @@ -466,8 +486,8 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor if (align_planar) { - LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, value, te); - LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, value, te); + LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, value, te, object->getID()); } } } @@ -491,8 +511,8 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor if (align_planar) { - LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, value, te); - LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, value, te); + LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, value, te, object->getID()); } } } @@ -507,8 +527,8 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor if (align_planar) { - LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, value, te); - LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, value, te); + LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, value, te, object->getID()); } } } @@ -523,8 +543,8 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor if (align_planar) { - LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, value, te); - LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, value, te); + LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, value, te, object->getID()); } } } @@ -539,8 +559,8 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor if (align_planar) { - LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, value, te); - LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, value, te); + LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, value, te, object->getID()); } } } @@ -612,6 +632,68 @@ private: LLFace* mCenterFace; }; +struct LLPanelFaceSetAlignedConcreteTEFunctor : public LLSelectedTEFunctor +{ + LLPanelFaceSetAlignedConcreteTEFunctor(LLPanelFace* panel, LLFace* center_face, LLRender::eTexIndex map) : + mPanel(panel), + mChefFace(center_face), + mMap(map) + {} + + virtual bool apply(LLViewerObject* object, S32 te) + { + LLFace* facep = object->mDrawable->getFace(te); + if (!facep) + { + return true; + } + + if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te) + { + return true; + } + + if (mChefFace != facep) + { + LLVector2 uv_offset, uv_scale; + F32 uv_rot; + if (facep->calcAlignedPlanarTE(mChefFace, &uv_offset, &uv_scale, &uv_rot, mMap)) + { + switch (mMap) + { + case LLRender::DIFFUSE_MAP: + object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]); + object->setTEScale(te, uv_scale.mV[VX], uv_scale.mV[VY]); + object->setTERotation(te, uv_rot); + break; + case LLRender::NORMAL_MAP: + LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, uv_rot, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, uv_offset.mV[VX], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, uv_offset.mV[VY], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, uv_scale.mV[VX], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, uv_scale.mV[VY], te, object->getID()); + break; + case LLRender::SPECULAR_MAP: + LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, uv_rot, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, uv_offset.mV[VX], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, uv_offset.mV[VY], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID()); + break; + default: /*make compiler happy*/ + break; + } + } + } + + return true; + } +private: + LLPanelFace* mPanel; + LLFace* mChefFace; + LLRender::eTexIndex mMap; +}; + // Functor that tests if a face is aligned to mCenterFace struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor { @@ -697,6 +779,17 @@ void LLPanelFace::sendTextureInfo() LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); } +void LLPanelFace::alignTestureLayer() +{ + LLFace* last_face = NULL; + bool identical_face = false; + LLSelectedTE::getFace(last_face, identical_face); + + LLRadioGroup * radio_mat_type = getChild("radio_material_type"); + LLPanelFaceSetAlignedConcreteTEFunctor setfunc(this, last_face, static_cast(radio_mat_type->getSelectedIndex())); + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); +} + void LLPanelFace::getState() { updateUI(); @@ -983,6 +1076,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) bool enabled = (editable && isIdenticalPlanarTexgen()); childSetValue("checkbox planar align", align_planar && enabled); childSetEnabled("checkbox planar align", enabled); + childSetEnabled("button align textures", enabled && LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1); if (align_planar && enabled) { @@ -2129,7 +2223,18 @@ void LLPanelFace::onCommitMaterialBumpyRot(LLUICtrl* ctrl, void* userdata) } else { - LLSelectedTEMaterial::setNormalRotation(self,self->getCurrentBumpyRot() * DEG_TO_RAD); + if ((bool)self->childGetValue("checkbox planar align").asBoolean()) + { + LLFace* last_face = NULL; + bool identical_face = false; + LLSelectedTE::getFace(last_face, identical_face); + LLPanelFaceSetAlignedTEFunctor setfunc(self, last_face); + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); + } + else + { + LLSelectedTEMaterial::setNormalRotation(self, self->getCurrentBumpyRot() * DEG_TO_RAD); + } } } @@ -2146,7 +2251,18 @@ void LLPanelFace::onCommitMaterialShinyRot(LLUICtrl* ctrl, void* userdata) } else { - LLSelectedTEMaterial::setSpecularRotation(self,self->getCurrentShinyRot() * DEG_TO_RAD); + if ((bool)self->childGetValue("checkbox planar align").asBoolean()) + { + LLFace* last_face = NULL; + bool identical_face = false; + LLSelectedTE::getFace(last_face, identical_face); + LLPanelFaceSetAlignedTEFunctor setfunc(self, last_face); + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); + } + else + { + LLSelectedTEMaterial::setSpecularRotation(self, self->getCurrentShinyRot() * DEG_TO_RAD); + } } } @@ -2403,6 +2519,11 @@ void LLPanelFace::onClickAutoFix(void* userdata) LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); } +void LLPanelFace::onAlignTexture(void* userdata) +{ + LLPanelFace* self = (LLPanelFace*)userdata; + self->alignTestureLayer(); +} // TODO: I don't know who put these in or what these are for??? diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 0b40d7d41a..2d57d89a44 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -126,6 +126,7 @@ protected: void sendFullbright(); // applies and sends full bright void sendGlow(); void sendMedia(); + void alignTestureLayer(); // this function is to return TRUE if the drag should succeed. static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item); @@ -202,6 +203,7 @@ protected: static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata); static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); static void onClickAutoFix(void*); + static void onAlignTexture(void*); static F32 valueGlow(LLViewerObject* object, S32 face); diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index 67b99ca588..90f32ae452 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -770,6 +770,17 @@ tool_tip="Align textures on all selected faces with the last selected face. Requires Planar texture mapping." top_delta="16" width="260" /> +