From 74c8b028d42a8c5b080bb861e427f38cedd4ad7c Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 15 Dec 2023 18:26:14 +0100 Subject: SL-20743 Use LLMutex in LLImageBase for internal data thread-safety --- indra/llappearance/llpolymorph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 965b999bd4..223b2b7f1c 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -659,7 +659,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) //----------------------------------------------------------------------------- // applyMask() //----------------------------------------------------------------------------- -void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) +void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) { LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; @@ -780,7 +780,7 @@ LLPolyVertexMask::~LLPolyVertexMask() //----------------------------------------------------------------------------- // generateMask() //----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) +void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) { // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) // BOOL debugImg = FALSE; -- cgit v1.2.3 From 70f8dc7a4f4be217fea5439e474fc75e567c23c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Sat, 10 Feb 2024 22:37:52 +0100 Subject: miscellaneous: BOOL (int) to real bool --- indra/llappearance/llpolymorph.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 223b2b7f1c..c2f0289432 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -114,7 +114,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 1) { LL_WARNS() << "Can't read number of morph target vertices" << LL_ENDL; - return FALSE; + return false; } //------------------------------------------------------------------------- @@ -151,14 +151,14 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 1) { LL_WARNS() << "Can't read morph target vertex number" << LL_ENDL; - return FALSE; + return false; } if (mVertexIndices[v] > 10000) { // Bad install? These are usually .llm files from 'character' fodler LL_WARNS() << "Bad morph index " << v << ": " << mVertexIndices[v] << LL_ENDL; - return FALSE; + return false; } @@ -167,7 +167,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 3) { LL_WARNS() << "Can't read morph target vertex coordinates" << LL_ENDL; - return FALSE; + return false; } F32 magnitude = mCoords[v].getLength3().getF32(); @@ -187,7 +187,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 3) { LL_WARNS() << "Can't read morph target normal" << LL_ENDL; - return FALSE; + return false; } numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); @@ -195,7 +195,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 3) { LL_WARNS() << "Can't read morph target binormal" << LL_ENDL; - return FALSE; + return false; } @@ -204,7 +204,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 2) { LL_WARNS() << "Can't read morph target uv" << LL_ENDL; - return FALSE; + return false; } mNumIndices++; @@ -213,7 +213,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) mAvgDistortion.mul(1.f/(F32)mNumIndices); mAvgDistortion.normalize3fast(); - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -265,14 +265,14 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; + return false; // Get mixed-case name static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); if( !node->getFastAttributeString( name_string, mMorphName ) ) { LL_WARNS() << "Avatar file: is missing name attribute" << LL_ENDL; - return FALSE; // Continue, ignoring this tag + return false; // Continue, ignoring this tag } static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph"); @@ -284,7 +284,7 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) { LL_WARNS() << "Failed to getChildByName(\"param_morph\")" << LL_ENDL; - return FALSE; + return false; } for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); @@ -310,7 +310,7 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) } } - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -357,7 +357,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { llassert(mInfo == NULL); if (info->mID < 0) - return FALSE; + return false; mInfo = info; mID = info->mID; setWeight(getDefaultWeight()); @@ -394,9 +394,9 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) if (!mMorphData) { LL_WARNS() << "No morph target named " << morph_param_name << " found in mesh." << LL_ENDL; - return FALSE; // Continue, ignoring this tag + return false; // Continue, ignoring this tag } - return TRUE; + return true; } /*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const @@ -416,9 +416,9 @@ BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node) if (!setInfo(info)) { delete info; - return FALSE; + return false; } - return TRUE; + return true; } #endif -- cgit v1.2.3 From 4419bb870986c6900fc096338622d27b999cd771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Sun, 11 Feb 2024 01:23:28 +0100 Subject: more misc: BOOL (int) to real bool --- indra/llappearance/llpolymorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index c2f0289432..697beb239e 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -260,7 +260,7 @@ LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() { } -BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) +bool LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) { llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); -- cgit v1.2.3 From 1839def9dc6064a865f6cd05d1509358a53ac9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Sun, 11 Feb 2024 16:50:22 +0100 Subject: even more misc: BOOL (int) to real bool --- indra/llappearance/llpolymorph.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 697beb239e..73811a550c 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -104,7 +104,7 @@ LLPolyMorphData::~LLPolyMorphData() //----------------------------------------------------------------------------- // loadBinary() //----------------------------------------------------------------------------- -BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) +bool LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) { S32 numVertices; S32 numRead; @@ -353,7 +353,7 @@ LLPolyMorphTarget::~LLPolyMorphTarget() //----------------------------------------------------------------------------- // setInfo() //----------------------------------------------------------------------------- -BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) +bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { llassert(mInfo == NULL); if (info->mID < 0) @@ -408,7 +408,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) //----------------------------------------------------------------------------- // parseData() //----------------------------------------------------------------------------- -BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node) +bool LLPolyMorphTarget::parseData(LLXmlTreeNode* node) { LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo; -- cgit v1.2.3 From 9e854b697a06abed2a0917fb6120445f176764f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Fri, 16 Feb 2024 19:29:51 +0100 Subject: misc: BOOL to bool --- indra/llappearance/llpolymorph.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 73811a550c..4b94ed48b1 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -256,7 +256,7 @@ void LLPolyMorphData::freeData() // LLPolyMorphTargetInfo() //----------------------------------------------------------------------------- LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() - : mIsClothingMorph(FALSE) + : mIsClothingMorph(false) { } @@ -659,7 +659,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) //----------------------------------------------------------------------------- // applyMask() //----------------------------------------------------------------------------- -void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) +void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert) { LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; @@ -749,7 +749,7 @@ void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight) LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data) : mWeights(new F32[morph_data->mNumIndices]), mMorphData(morph_data), - mWeightsGenerated(FALSE) + mWeightsGenerated(false) { llassert(mMorphData != NULL); llassert(mMorphData->mNumIndices > 0); @@ -780,10 +780,10 @@ LLPolyVertexMask::~LLPolyVertexMask() //----------------------------------------------------------------------------- // generateMask() //----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) +void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights) { // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) -// BOOL debugImg = FALSE; +// bool debugImg = false; // if (debugImg) // { // if (invert) @@ -827,7 +827,7 @@ void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 he clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; } } - mWeightsGenerated = TRUE; + mWeightsGenerated = true; } //----------------------------------------------------------------------------- -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/llappearance/llpolymorph.cpp | 1688 ++++++++++++++++++------------------ 1 file changed, 844 insertions(+), 844 deletions(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 8665ac2433..d8109d79c2 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -1,844 +1,844 @@ -/** - * @file llpolymorph.cpp - * @brief Implementation of LLPolyMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- - -#include "llpolymorph.h" -#include "llavatarappearance.h" -#include "llavatarjoint.h" -#include "llwearable.h" -#include "llxmltree.h" -#include "llendianswizzle.h" -#include "llpolymesh.h" -#include "llfasttimer.h" - -//#include "../tools/imdebug/imdebug.h" - -const F32 NORMAL_SOFTEN_FACTOR = 0.65f; - -//----------------------------------------------------------------------------- -// LLPolyMorphData() -//----------------------------------------------------------------------------- -LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) - : mName(morph_name) -{ - mNumIndices = 0; - mCurrentIndex = 0; - mTotalDistortion = 0.f; - mAvgDistortion.clear(); - mMaxDistortion = 0.f; - mVertexIndices = NULL; - mCoords = NULL; - mNormals = NULL; - mBinormals = NULL; - mTexCoords = NULL; - - mMesh = NULL; -} - -LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : - mName(rhs.mName), - mNumIndices(rhs.mNumIndices), - mTotalDistortion(rhs.mTotalDistortion), - mAvgDistortion(rhs.mAvgDistortion), - mMaxDistortion(rhs.mMaxDistortion), - mVertexIndices(NULL), - mCoords(NULL), - mNormals(NULL), - mBinormals(NULL), - mTexCoords(NULL) -{ - const S32 numVertices = mNumIndices; - - U32 size = sizeof(LLVector4a)*numVertices; - - mCoords = static_cast( ll_aligned_malloc_16(size) ); - mNormals = static_cast( ll_aligned_malloc_16(size) ); - mBinormals = static_cast( ll_aligned_malloc_16(size) ); - mTexCoords = new LLVector2[numVertices]; - mVertexIndices = new U32[numVertices]; - - for (S32 v=0; v < numVertices; v++) - { - mCoords[v] = rhs.mCoords[v]; - mNormals[v] = rhs.mNormals[v]; - mBinormals[v] = rhs.mBinormals[v]; - mTexCoords[v] = rhs.mTexCoords[v]; - mVertexIndices[v] = rhs.mVertexIndices[v]; - } -} - -//----------------------------------------------------------------------------- -// ~LLPolyMorphData() -//----------------------------------------------------------------------------- -LLPolyMorphData::~LLPolyMorphData() -{ - freeData(); -} - -//----------------------------------------------------------------------------- -// loadBinary() -//----------------------------------------------------------------------------- -bool LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) -{ - S32 numVertices; - S32 numRead; - - numRead = fread(&numVertices, sizeof(S32), 1, fp); - llendianswizzle(&numVertices, sizeof(S32), 1); - if (numRead != 1) - { - LL_WARNS() << "Can't read number of morph target vertices" << LL_ENDL; - return false; - } - - //------------------------------------------------------------------------- - // free any existing data - //------------------------------------------------------------------------- - freeData(); - - //------------------------------------------------------------------------- - // allocate vertices - //------------------------------------------------------------------------- - - U32 size = sizeof(LLVector4a)*numVertices; - - mCoords = static_cast(ll_aligned_malloc_16(size)); - mNormals = static_cast(ll_aligned_malloc_16(size)); - mBinormals = static_cast(ll_aligned_malloc_16(size)); - - mTexCoords = new LLVector2[numVertices]; - // Actually, we are allocating more space than we need for the skiplist - mVertexIndices = new U32[numVertices]; - mNumIndices = 0; - mTotalDistortion = 0.f; - mMaxDistortion = 0.f; - mAvgDistortion.clear(); - mMesh = mesh; - - //------------------------------------------------------------------------- - // read vertices - //------------------------------------------------------------------------- - for(S32 v = 0; v < numVertices; v++) - { - numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp); - llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); - if (numRead != 1) - { - LL_WARNS() << "Can't read morph target vertex number" << LL_ENDL; - return false; - } - - if (mVertexIndices[v] > 10000) - { - // Bad install? These are usually .llm files from 'character' fodler - LL_WARNS() << "Bad morph index " << v << ": " << mVertexIndices[v] << LL_ENDL; - return false; - } - - - numRead = fread(&mCoords[v], sizeof(F32), 3, fp); - llendianswizzle(&mCoords[v], sizeof(F32), 3); - if (numRead != 3) - { - LL_WARNS() << "Can't read morph target vertex coordinates" << LL_ENDL; - return false; - } - - F32 magnitude = mCoords[v].getLength3().getF32(); - - mTotalDistortion += magnitude; - LLVector4a t; - t.setAbs(mCoords[v]); - mAvgDistortion.add(t); - - if (magnitude > mMaxDistortion) - { - mMaxDistortion = magnitude; - } - - numRead = fread(&mNormals[v], sizeof(F32), 3, fp); - llendianswizzle(&mNormals[v], sizeof(F32), 3); - if (numRead != 3) - { - LL_WARNS() << "Can't read morph target normal" << LL_ENDL; - return false; - } - - numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); - llendianswizzle(&mBinormals[v], sizeof(F32), 3); - if (numRead != 3) - { - LL_WARNS() << "Can't read morph target binormal" << LL_ENDL; - return false; - } - - - numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp); - llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); - if (numRead != 2) - { - LL_WARNS() << "Can't read morph target uv" << LL_ENDL; - return false; - } - - mNumIndices++; - } - - mAvgDistortion.mul(1.f/(F32)mNumIndices); - mAvgDistortion.normalize3fast(); - - return true; -} - -//----------------------------------------------------------------------------- -// freeData() -//----------------------------------------------------------------------------- -void LLPolyMorphData::freeData() -{ - if (mCoords != NULL) - { - ll_aligned_free_16(mCoords); - mCoords = NULL; - } - - if (mNormals != NULL) - { - ll_aligned_free_16(mNormals); - mNormals = NULL; - } - - if (mBinormals != NULL) - { - ll_aligned_free_16(mBinormals); - mBinormals = NULL; - } - - if (mTexCoords != NULL) - { - delete [] mTexCoords; - mTexCoords = NULL; - } - - if (mVertexIndices != NULL) - { - delete [] mVertexIndices; - mVertexIndices = NULL; - } -} - -//----------------------------------------------------------------------------- -// LLPolyMorphTargetInfo() -//----------------------------------------------------------------------------- -LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() - : mIsClothingMorph(false) -{ -} - -bool LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return false; - - // Get mixed-case name - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if( !node->getFastAttributeString( name_string, mMorphName ) ) - { - LL_WARNS() << "Avatar file: is missing name attribute" << LL_ENDL; - return false; // Continue, ignoring this tag - } - - static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph"); - node->getFastAttributeBOOL(clothing_morph_string, mIsClothingMorph); - - LLXmlTreeNode *paramNode = node->getChildByName("param_morph"); - - if (NULL == paramNode) - { - LL_WARNS() << "Failed to getChildByName(\"param_morph\")" - << LL_ENDL; - return false; - } - - for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); - child_node; - child_node = paramNode->getNextChild()) - { - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (child_node->hasName("volume_morph")) - { - std::string volume_name; - if (child_node->getFastAttributeString(name_string, volume_name)) - { - LLVector3 scale; - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - child_node->getFastAttributeVector3(scale_string, scale); - - LLVector3 pos; - static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); - child_node->getFastAttributeVector3(pos_string, pos); - - mVolumeInfoList.push_back(LLPolyVolumeMorphInfo(volume_name,scale,pos)); - } - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// LLPolyMorphTarget() -//----------------------------------------------------------------------------- -LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh) - : LLViewerVisualParam(), - mMorphData(NULL), - mMesh(poly_mesh), - mVertMask(NULL), - mLastSex(SEX_FEMALE), - mNumMorphMasksPending(0), - mVolumeMorphs() -{ -} - -//----------------------------------------------------------------------------- -// LLPolyMorphTarget() -//----------------------------------------------------------------------------- -LLPolyMorphTarget::LLPolyMorphTarget(const LLPolyMorphTarget& pOther) - : LLViewerVisualParam(pOther), - mMorphData(pOther.mMorphData), - mMesh(pOther.mMesh), - mVertMask(pOther.mVertMask == NULL ? NULL : new LLPolyVertexMask(*pOther.mVertMask)), - mLastSex(pOther.mLastSex), - mNumMorphMasksPending(pOther.mNumMorphMasksPending), - mVolumeMorphs(pOther.mVolumeMorphs) -{ -} - -//----------------------------------------------------------------------------- -// ~LLPolyMorphTarget() -//----------------------------------------------------------------------------- -LLPolyMorphTarget::~LLPolyMorphTarget() -{ - delete mVertMask; - mVertMask = NULL; -} - -//----------------------------------------------------------------------------- -// setInfo() -//----------------------------------------------------------------------------- -bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return false; - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight()); - - LLAvatarAppearance* avatarp = mMesh->getAvatar(); - for (LLPolyVolumeMorphInfo& volume_info : getInfo()->mVolumeInfoList) - { - for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++) - { - if (avatarp->mCollisionVolumes[i].getName() == volume_info.mName) - { - mVolumeMorphs.push_back( - LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i], - volume_info.mScale, - volume_info.mPos)); - break; - } - } - } - - std::string morph_param_name = getInfo()->mMorphName; - - mMorphData = mMesh->getMorphData(morph_param_name); - if (!mMorphData) - { - const std::string driven_tag = "_Driven"; - U32 pos = morph_param_name.find(driven_tag); - if (pos > 0) - { - morph_param_name = morph_param_name.substr(0,pos); - mMorphData = mMesh->getMorphData(morph_param_name); - } - } - if (!mMorphData) - { - LL_WARNS() << "No morph target named " << morph_param_name << " found in mesh." << LL_ENDL; - return false; // Continue, ignoring this tag - } - return true; -} - -/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const -{ - return new LLPolyMorphTarget(*this); -} - -#if 0 // obsolete -//----------------------------------------------------------------------------- -// parseData() -//----------------------------------------------------------------------------- -bool LLPolyMorphTarget::parseData(LLXmlTreeNode* node) -{ - LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo; - - info->parseXml(node); - if (!setInfo(info)) - { - delete info; - return false; - } - return true; -} -#endif - -//----------------------------------------------------------------------------- -// getVertexDistortion() -//----------------------------------------------------------------------------- -LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) -{ - if (!mMorphData || mMesh != mesh) return LLVector4a::getZero(); - - for(U32 index = 0; index < mMorphData->mNumIndices; index++) - { - if (mMorphData->mVertexIndices[index] == (U32)requested_index) - { - return mMorphData->mCoords[index]; - } - } - - return LLVector4a::getZero(); -} - -//----------------------------------------------------------------------------- -// getFirstDistortion() -//----------------------------------------------------------------------------- -const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) -{ - if (!mMorphData) return &LLVector4a::getZero(); - - LLVector4a* resultVec; - mMorphData->mCurrentIndex = 0; - if (mMorphData->mNumIndices) - { - resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; - if (index != NULL) - { - *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; - } - if (poly_mesh != NULL) - { - *poly_mesh = mMesh; - } - - return resultVec; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// getNextDistortion() -//----------------------------------------------------------------------------- -const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) -{ - if (!mMorphData) return &LLVector4a::getZero(); - - LLVector4a* resultVec; - mMorphData->mCurrentIndex++; - if (mMorphData->mCurrentIndex < mMorphData->mNumIndices) - { - resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; - if (index != NULL) - { - *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; - } - if (poly_mesh != NULL) - { - *poly_mesh = mMesh; - } - return resultVec; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// getTotalDistortion() -//----------------------------------------------------------------------------- -F32 LLPolyMorphTarget::getTotalDistortion() -{ - if (mMorphData) - { - return mMorphData->mTotalDistortion; - } - else - { - return 0.f; - } -} - -//----------------------------------------------------------------------------- -// getAvgDistortion() -//----------------------------------------------------------------------------- -const LLVector4a& LLPolyMorphTarget::getAvgDistortion() -{ - if (mMorphData) - { - return mMorphData->mAvgDistortion; - } - else - { - return LLVector4a::getZero(); - } -} - -//----------------------------------------------------------------------------- -// getMaxDistortion() -//----------------------------------------------------------------------------- -F32 LLPolyMorphTarget::getMaxDistortion() -{ - if (mMorphData) - { - return mMorphData->mMaxDistortion; - } - else - { - return 0.f; - } -} - -//----------------------------------------------------------------------------- -// apply() -//----------------------------------------------------------------------------- -void LLPolyMorphTarget::apply( ESex avatar_sex ) -{ - if (!mMorphData || mNumMorphMasksPending > 0) - { - return; - } - - LL_PROFILE_ZONE_SCOPED; - - mLastSex = avatar_sex; - - // Check for NaN condition (NaN is detected if a variable doesn't equal itself. - if (mCurWeight != mCurWeight) - { - mCurWeight = 0.0; - } - if (mLastWeight != mLastWeight) - { - mLastWeight = mCurWeight+.001; - } - - // perform differential update of morph - F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight); - // store last weight - mLastWeight += delta_weight; - - if (delta_weight != 0.f) - { - llassert(!mMesh->isLOD()); - LLVector4a *coords = mMesh->getWritableCoords(); - - LLVector4a *scaled_normals = mMesh->getScaledNormals(); - LLVector4a *normals = mMesh->getWritableNormals(); - - LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); - LLVector4a *binormals = mMesh->getWritableBinormals(); - - LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); - LLVector2 *tex_coords = mMesh->getWritableTexCoords(); - - F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; - - for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++) - { - S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph]; - - F32 maskWeight = 1.f; - if (maskWeightArray) - { - maskWeight = maskWeightArray[vert_index_morph]; - } - - - LLVector4a pos = mMorphData->mCoords[vert_index_morph]; - pos.mul(delta_weight*maskWeight); - coords[vert_index_mesh].add(pos); - - if (getInfo()->mIsClothingMorph && clothing_weights) - { - LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; - clothing_offset.mul(delta_weight * maskWeight); - LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; - clothing_weight->add(clothing_offset); - clothing_weight->getF32ptr()[VW] = maskWeight; - } - - // calculate new normals based on half angles - LLVector4a norm = mMorphData->mNormals[vert_index_morph]; - norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); - scaled_normals[vert_index_mesh].add(norm); - norm = scaled_normals[vert_index_mesh]; - - // guard against degenerate input data before we create NaNs below! - // - norm.normalize3fast(); - normals[vert_index_mesh] = norm; - - // calculate new binormals - LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; - - // guard against degenerate input data before we create NaNs below! - // - if (!binorm.isFinite3() || (binorm.dot3(binorm).getF32() <= F_APPROXIMATELY_ZERO)) - { - binorm.set(1,0,0,1); - } - - binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); - scaled_binormals[vert_index_mesh].add(binorm); - LLVector4a tangent; - tangent.setCross3(scaled_binormals[vert_index_mesh], norm); - LLVector4a& normalized_binormal = binormals[vert_index_mesh]; - - normalized_binormal.setCross3(norm, tangent); - normalized_binormal.normalize3fast(); - - tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; - } - - // now apply volume changes - for(LLPolyVolumeMorph& volume_morph : mVolumeMorphs) - { - LLVector3 scale_delta = volume_morph.mScale * delta_weight; - LLVector3 pos_delta = volume_morph.mPos * delta_weight; - - volume_morph.mVolume->setScale(volume_morph.mVolume->getScale() + scale_delta); - // SL-315 - volume_morph.mVolume->setPosition(volume_morph.mVolume->getPosition() + pos_delta); - } - } - - if (mNext) - { - mNext->apply(avatar_sex); - } -} - -//----------------------------------------------------------------------------- -// applyMask() -//----------------------------------------------------------------------------- -void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert) -{ - LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; - - if (!mVertMask) - { - mVertMask = new LLPolyVertexMask(mMorphData); - mNumMorphMasksPending--; - } - else - { - // remove effect of previous mask - F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; - - if (maskWeights) - { - LLVector4a *coords = mMesh->getWritableCoords(); - LLVector4a *scaled_normals = mMesh->getScaledNormals(); - LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); - LLVector2 *tex_coords = mMesh->getWritableTexCoords(); - - LLVector4Logical clothing_mask; - clothing_mask.clear(); - clothing_mask.setElement<0>(); - clothing_mask.setElement<1>(); - clothing_mask.setElement<2>(); - - - for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) - { - F32 lastMaskWeight = mLastWeight * maskWeights[vert]; - S32 out_vert = mMorphData->mVertexIndices[vert]; - - // remove effect of existing masked morph - LLVector4a t; - t = mMorphData->mCoords[vert]; - t.mul(lastMaskWeight); - coords[out_vert].sub(t); - - t = mMorphData->mNormals[vert]; - t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); - scaled_normals[out_vert].sub(t); - - t = mMorphData->mBinormals[vert]; - t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); - scaled_binormals[out_vert].sub(t); - - tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; - - if (clothing_weights) - { - LLVector4a clothing_offset = mMorphData->mCoords[vert]; - clothing_offset.mul(lastMaskWeight); - LLVector4a* clothing_weight = &clothing_weights[out_vert]; - LLVector4a t; - t.setSub(*clothing_weight, clothing_offset); - clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight); - } - } - } - } - - // set last weight to 0, since we've removed the effect of this morph - mLastWeight = 0.f; - - mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights); - - apply(mLastSex); -} - -void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight) -{ - // now apply volume changes - for(LLPolyVolumeMorph& volume_morph : mVolumeMorphs) - { - LLVector3 scale_delta = volume_morph.mScale * delta_weight; - LLVector3 pos_delta = volume_morph.mPos * delta_weight; - - volume_morph.mVolume->setScale(volume_morph.mVolume->getScale() + scale_delta); - // SL-315 - volume_morph.mVolume->setPosition(volume_morph.mVolume->getPosition() + pos_delta); - } -} - -//----------------------------------------------------------------------------- -// LLPolyVertexMask() -//----------------------------------------------------------------------------- -LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data) - : mWeights(new F32[morph_data->mNumIndices]), - mMorphData(morph_data), - mWeightsGenerated(false) -{ - llassert(mMorphData != NULL); - llassert(mMorphData->mNumIndices > 0); -} - -//----------------------------------------------------------------------------- -// LLPolyVertexMask() -//----------------------------------------------------------------------------- -LLPolyVertexMask::LLPolyVertexMask(const LLPolyVertexMask& pOther) - : mWeights(new F32[pOther.mMorphData->mNumIndices]), - mMorphData(pOther.mMorphData), - mWeightsGenerated(pOther.mWeightsGenerated) -{ - llassert(mMorphData != NULL); - llassert(mMorphData->mNumIndices > 0); - memcpy(mWeights, pOther.mWeights, sizeof(F32) * mMorphData->mNumIndices); -} - -//----------------------------------------------------------------------------- -// ~LLPolyVertexMask() -//----------------------------------------------------------------------------- -LLPolyVertexMask::~LLPolyVertexMask() -{ - delete [] mWeights; - mWeights = NULL; -} - -//----------------------------------------------------------------------------- -// generateMask() -//----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights) -{ -// RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) -// bool debugImg = false; -// if (debugImg) -// { -// if (invert) -// { -// imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData); -// } -// else -// { -// imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData); -// } -// } - for (U32 index = 0; index < mMorphData->mNumIndices; index++) - { - S32 vertIndex = mMorphData->mVertexIndices[index]; - const S32 *sharedVertIndex = mMorphData->mMesh->getSharedVert(vertIndex); - LLVector2 uvCoords; - - if (sharedVertIndex) - { - uvCoords = mMorphData->mMesh->getUVs(*sharedVertIndex); - } - else - { - uvCoords = mMorphData->mMesh->getUVs(vertIndex); - } - U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1); - U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1); - - mWeights[index] = maskTextureData ? ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f : 0.0f; - - if (invert) - { - mWeights[index] = 1.f - mWeights[index]; - } - - // now apply step function - // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f; - - if (clothing_weights) - { - clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; - } - } - mWeightsGenerated = true; -} - -//----------------------------------------------------------------------------- -// getMaskForMorphIndex() -//----------------------------------------------------------------------------- -F32* LLPolyVertexMask::getMorphMaskWeights() -{ - if (!mWeightsGenerated) - { - return NULL; - } - - return mWeights; -} +/** + * @file llpolymorph.cpp + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- + +#include "llpolymorph.h" +#include "llavatarappearance.h" +#include "llavatarjoint.h" +#include "llwearable.h" +#include "llxmltree.h" +#include "llendianswizzle.h" +#include "llpolymesh.h" +#include "llfasttimer.h" + +//#include "../tools/imdebug/imdebug.h" + +const F32 NORMAL_SOFTEN_FACTOR = 0.65f; + +//----------------------------------------------------------------------------- +// LLPolyMorphData() +//----------------------------------------------------------------------------- +LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) + : mName(morph_name) +{ + mNumIndices = 0; + mCurrentIndex = 0; + mTotalDistortion = 0.f; + mAvgDistortion.clear(); + mMaxDistortion = 0.f; + mVertexIndices = NULL; + mCoords = NULL; + mNormals = NULL; + mBinormals = NULL; + mTexCoords = NULL; + + mMesh = NULL; +} + +LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : + mName(rhs.mName), + mNumIndices(rhs.mNumIndices), + mTotalDistortion(rhs.mTotalDistortion), + mAvgDistortion(rhs.mAvgDistortion), + mMaxDistortion(rhs.mMaxDistortion), + mVertexIndices(NULL), + mCoords(NULL), + mNormals(NULL), + mBinormals(NULL), + mTexCoords(NULL) +{ + const S32 numVertices = mNumIndices; + + U32 size = sizeof(LLVector4a)*numVertices; + + mCoords = static_cast( ll_aligned_malloc_16(size) ); + mNormals = static_cast( ll_aligned_malloc_16(size) ); + mBinormals = static_cast( ll_aligned_malloc_16(size) ); + mTexCoords = new LLVector2[numVertices]; + mVertexIndices = new U32[numVertices]; + + for (S32 v=0; v < numVertices; v++) + { + mCoords[v] = rhs.mCoords[v]; + mNormals[v] = rhs.mNormals[v]; + mBinormals[v] = rhs.mBinormals[v]; + mTexCoords[v] = rhs.mTexCoords[v]; + mVertexIndices[v] = rhs.mVertexIndices[v]; + } +} + +//----------------------------------------------------------------------------- +// ~LLPolyMorphData() +//----------------------------------------------------------------------------- +LLPolyMorphData::~LLPolyMorphData() +{ + freeData(); +} + +//----------------------------------------------------------------------------- +// loadBinary() +//----------------------------------------------------------------------------- +bool LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) +{ + S32 numVertices; + S32 numRead; + + numRead = fread(&numVertices, sizeof(S32), 1, fp); + llendianswizzle(&numVertices, sizeof(S32), 1); + if (numRead != 1) + { + LL_WARNS() << "Can't read number of morph target vertices" << LL_ENDL; + return false; + } + + //------------------------------------------------------------------------- + // free any existing data + //------------------------------------------------------------------------- + freeData(); + + //------------------------------------------------------------------------- + // allocate vertices + //------------------------------------------------------------------------- + + U32 size = sizeof(LLVector4a)*numVertices; + + mCoords = static_cast(ll_aligned_malloc_16(size)); + mNormals = static_cast(ll_aligned_malloc_16(size)); + mBinormals = static_cast(ll_aligned_malloc_16(size)); + + mTexCoords = new LLVector2[numVertices]; + // Actually, we are allocating more space than we need for the skiplist + mVertexIndices = new U32[numVertices]; + mNumIndices = 0; + mTotalDistortion = 0.f; + mMaxDistortion = 0.f; + mAvgDistortion.clear(); + mMesh = mesh; + + //------------------------------------------------------------------------- + // read vertices + //------------------------------------------------------------------------- + for(S32 v = 0; v < numVertices; v++) + { + numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp); + llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); + if (numRead != 1) + { + LL_WARNS() << "Can't read morph target vertex number" << LL_ENDL; + return false; + } + + if (mVertexIndices[v] > 10000) + { + // Bad install? These are usually .llm files from 'character' fodler + LL_WARNS() << "Bad morph index " << v << ": " << mVertexIndices[v] << LL_ENDL; + return false; + } + + + numRead = fread(&mCoords[v], sizeof(F32), 3, fp); + llendianswizzle(&mCoords[v], sizeof(F32), 3); + if (numRead != 3) + { + LL_WARNS() << "Can't read morph target vertex coordinates" << LL_ENDL; + return false; + } + + F32 magnitude = mCoords[v].getLength3().getF32(); + + mTotalDistortion += magnitude; + LLVector4a t; + t.setAbs(mCoords[v]); + mAvgDistortion.add(t); + + if (magnitude > mMaxDistortion) + { + mMaxDistortion = magnitude; + } + + numRead = fread(&mNormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mNormals[v], sizeof(F32), 3); + if (numRead != 3) + { + LL_WARNS() << "Can't read morph target normal" << LL_ENDL; + return false; + } + + numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mBinormals[v], sizeof(F32), 3); + if (numRead != 3) + { + LL_WARNS() << "Can't read morph target binormal" << LL_ENDL; + return false; + } + + + numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp); + llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); + if (numRead != 2) + { + LL_WARNS() << "Can't read morph target uv" << LL_ENDL; + return false; + } + + mNumIndices++; + } + + mAvgDistortion.mul(1.f/(F32)mNumIndices); + mAvgDistortion.normalize3fast(); + + return true; +} + +//----------------------------------------------------------------------------- +// freeData() +//----------------------------------------------------------------------------- +void LLPolyMorphData::freeData() +{ + if (mCoords != NULL) + { + ll_aligned_free_16(mCoords); + mCoords = NULL; + } + + if (mNormals != NULL) + { + ll_aligned_free_16(mNormals); + mNormals = NULL; + } + + if (mBinormals != NULL) + { + ll_aligned_free_16(mBinormals); + mBinormals = NULL; + } + + if (mTexCoords != NULL) + { + delete [] mTexCoords; + mTexCoords = NULL; + } + + if (mVertexIndices != NULL) + { + delete [] mVertexIndices; + mVertexIndices = NULL; + } +} + +//----------------------------------------------------------------------------- +// LLPolyMorphTargetInfo() +//----------------------------------------------------------------------------- +LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() + : mIsClothingMorph(false) +{ +} + +bool LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return false; + + // Get mixed-case name + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if( !node->getFastAttributeString( name_string, mMorphName ) ) + { + LL_WARNS() << "Avatar file: is missing name attribute" << LL_ENDL; + return false; // Continue, ignoring this tag + } + + static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph"); + node->getFastAttributeBOOL(clothing_morph_string, mIsClothingMorph); + + LLXmlTreeNode *paramNode = node->getChildByName("param_morph"); + + if (NULL == paramNode) + { + LL_WARNS() << "Failed to getChildByName(\"param_morph\")" + << LL_ENDL; + return false; + } + + for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); + child_node; + child_node = paramNode->getNextChild()) + { + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (child_node->hasName("volume_morph")) + { + std::string volume_name; + if (child_node->getFastAttributeString(name_string, volume_name)) + { + LLVector3 scale; + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + child_node->getFastAttributeVector3(scale_string, scale); + + LLVector3 pos; + static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); + child_node->getFastAttributeVector3(pos_string, pos); + + mVolumeInfoList.push_back(LLPolyVolumeMorphInfo(volume_name,scale,pos)); + } + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget() +//----------------------------------------------------------------------------- +LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh) + : LLViewerVisualParam(), + mMorphData(NULL), + mMesh(poly_mesh), + mVertMask(NULL), + mLastSex(SEX_FEMALE), + mNumMorphMasksPending(0), + mVolumeMorphs() +{ +} + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget() +//----------------------------------------------------------------------------- +LLPolyMorphTarget::LLPolyMorphTarget(const LLPolyMorphTarget& pOther) + : LLViewerVisualParam(pOther), + mMorphData(pOther.mMorphData), + mMesh(pOther.mMesh), + mVertMask(pOther.mVertMask == NULL ? NULL : new LLPolyVertexMask(*pOther.mVertMask)), + mLastSex(pOther.mLastSex), + mNumMorphMasksPending(pOther.mNumMorphMasksPending), + mVolumeMorphs(pOther.mVolumeMorphs) +{ +} + +//----------------------------------------------------------------------------- +// ~LLPolyMorphTarget() +//----------------------------------------------------------------------------- +LLPolyMorphTarget::~LLPolyMorphTarget() +{ + delete mVertMask; + mVertMask = NULL; +} + +//----------------------------------------------------------------------------- +// setInfo() +//----------------------------------------------------------------------------- +bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return false; + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight()); + + LLAvatarAppearance* avatarp = mMesh->getAvatar(); + for (LLPolyVolumeMorphInfo& volume_info : getInfo()->mVolumeInfoList) + { + for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++) + { + if (avatarp->mCollisionVolumes[i].getName() == volume_info.mName) + { + mVolumeMorphs.push_back( + LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i], + volume_info.mScale, + volume_info.mPos)); + break; + } + } + } + + std::string morph_param_name = getInfo()->mMorphName; + + mMorphData = mMesh->getMorphData(morph_param_name); + if (!mMorphData) + { + const std::string driven_tag = "_Driven"; + U32 pos = morph_param_name.find(driven_tag); + if (pos > 0) + { + morph_param_name = morph_param_name.substr(0,pos); + mMorphData = mMesh->getMorphData(morph_param_name); + } + } + if (!mMorphData) + { + LL_WARNS() << "No morph target named " << morph_param_name << " found in mesh." << LL_ENDL; + return false; // Continue, ignoring this tag + } + return true; +} + +/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const +{ + return new LLPolyMorphTarget(*this); +} + +#if 0 // obsolete +//----------------------------------------------------------------------------- +// parseData() +//----------------------------------------------------------------------------- +bool LLPolyMorphTarget::parseData(LLXmlTreeNode* node) +{ + LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo; + + info->parseXml(node); + if (!setInfo(info)) + { + delete info; + return false; + } + return true; +} +#endif + +//----------------------------------------------------------------------------- +// getVertexDistortion() +//----------------------------------------------------------------------------- +LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) +{ + if (!mMorphData || mMesh != mesh) return LLVector4a::getZero(); + + for(U32 index = 0; index < mMorphData->mNumIndices; index++) + { + if (mMorphData->mVertexIndices[index] == (U32)requested_index) + { + return mMorphData->mCoords[index]; + } + } + + return LLVector4a::getZero(); +} + +//----------------------------------------------------------------------------- +// getFirstDistortion() +//----------------------------------------------------------------------------- +const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + if (!mMorphData) return &LLVector4a::getZero(); + + LLVector4a* resultVec; + mMorphData->mCurrentIndex = 0; + if (mMorphData->mNumIndices) + { + resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; + if (index != NULL) + { + *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; + } + if (poly_mesh != NULL) + { + *poly_mesh = mMesh; + } + + return resultVec; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getNextDistortion() +//----------------------------------------------------------------------------- +const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + if (!mMorphData) return &LLVector4a::getZero(); + + LLVector4a* resultVec; + mMorphData->mCurrentIndex++; + if (mMorphData->mCurrentIndex < mMorphData->mNumIndices) + { + resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; + if (index != NULL) + { + *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; + } + if (poly_mesh != NULL) + { + *poly_mesh = mMesh; + } + return resultVec; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getTotalDistortion() +//----------------------------------------------------------------------------- +F32 LLPolyMorphTarget::getTotalDistortion() +{ + if (mMorphData) + { + return mMorphData->mTotalDistortion; + } + else + { + return 0.f; + } +} + +//----------------------------------------------------------------------------- +// getAvgDistortion() +//----------------------------------------------------------------------------- +const LLVector4a& LLPolyMorphTarget::getAvgDistortion() +{ + if (mMorphData) + { + return mMorphData->mAvgDistortion; + } + else + { + return LLVector4a::getZero(); + } +} + +//----------------------------------------------------------------------------- +// getMaxDistortion() +//----------------------------------------------------------------------------- +F32 LLPolyMorphTarget::getMaxDistortion() +{ + if (mMorphData) + { + return mMorphData->mMaxDistortion; + } + else + { + return 0.f; + } +} + +//----------------------------------------------------------------------------- +// apply() +//----------------------------------------------------------------------------- +void LLPolyMorphTarget::apply( ESex avatar_sex ) +{ + if (!mMorphData || mNumMorphMasksPending > 0) + { + return; + } + + LL_PROFILE_ZONE_SCOPED; + + mLastSex = avatar_sex; + + // Check for NaN condition (NaN is detected if a variable doesn't equal itself. + if (mCurWeight != mCurWeight) + { + mCurWeight = 0.0; + } + if (mLastWeight != mLastWeight) + { + mLastWeight = mCurWeight+.001; + } + + // perform differential update of morph + F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight); + // store last weight + mLastWeight += delta_weight; + + if (delta_weight != 0.f) + { + llassert(!mMesh->isLOD()); + LLVector4a *coords = mMesh->getWritableCoords(); + + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *normals = mMesh->getWritableNormals(); + + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *binormals = mMesh->getWritableBinormals(); + + LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); + LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + + F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; + + for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++) + { + S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph]; + + F32 maskWeight = 1.f; + if (maskWeightArray) + { + maskWeight = maskWeightArray[vert_index_morph]; + } + + + LLVector4a pos = mMorphData->mCoords[vert_index_morph]; + pos.mul(delta_weight*maskWeight); + coords[vert_index_mesh].add(pos); + + if (getInfo()->mIsClothingMorph && clothing_weights) + { + LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; + clothing_offset.mul(delta_weight * maskWeight); + LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; + clothing_weight->add(clothing_offset); + clothing_weight->getF32ptr()[VW] = maskWeight; + } + + // calculate new normals based on half angles + LLVector4a norm = mMorphData->mNormals[vert_index_morph]; + norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[vert_index_mesh].add(norm); + norm = scaled_normals[vert_index_mesh]; + + // guard against degenerate input data before we create NaNs below! + // + norm.normalize3fast(); + normals[vert_index_mesh] = norm; + + // calculate new binormals + LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; + + // guard against degenerate input data before we create NaNs below! + // + if (!binorm.isFinite3() || (binorm.dot3(binorm).getF32() <= F_APPROXIMATELY_ZERO)) + { + binorm.set(1,0,0,1); + } + + binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[vert_index_mesh].add(binorm); + LLVector4a tangent; + tangent.setCross3(scaled_binormals[vert_index_mesh], norm); + LLVector4a& normalized_binormal = binormals[vert_index_mesh]; + + normalized_binormal.setCross3(norm, tangent); + normalized_binormal.normalize3fast(); + + tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; + } + + // now apply volume changes + for(LLPolyVolumeMorph& volume_morph : mVolumeMorphs) + { + LLVector3 scale_delta = volume_morph.mScale * delta_weight; + LLVector3 pos_delta = volume_morph.mPos * delta_weight; + + volume_morph.mVolume->setScale(volume_morph.mVolume->getScale() + scale_delta); + // SL-315 + volume_morph.mVolume->setPosition(volume_morph.mVolume->getPosition() + pos_delta); + } + } + + if (mNext) + { + mNext->apply(avatar_sex); + } +} + +//----------------------------------------------------------------------------- +// applyMask() +//----------------------------------------------------------------------------- +void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert) +{ + LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; + + if (!mVertMask) + { + mVertMask = new LLPolyVertexMask(mMorphData); + mNumMorphMasksPending--; + } + else + { + // remove effect of previous mask + F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; + + if (maskWeights) + { + LLVector4a *coords = mMesh->getWritableCoords(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + + LLVector4Logical clothing_mask; + clothing_mask.clear(); + clothing_mask.setElement<0>(); + clothing_mask.setElement<1>(); + clothing_mask.setElement<2>(); + + + for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) + { + F32 lastMaskWeight = mLastWeight * maskWeights[vert]; + S32 out_vert = mMorphData->mVertexIndices[vert]; + + // remove effect of existing masked morph + LLVector4a t; + t = mMorphData->mCoords[vert]; + t.mul(lastMaskWeight); + coords[out_vert].sub(t); + + t = mMorphData->mNormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[out_vert].sub(t); + + t = mMorphData->mBinormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[out_vert].sub(t); + + tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; + + if (clothing_weights) + { + LLVector4a clothing_offset = mMorphData->mCoords[vert]; + clothing_offset.mul(lastMaskWeight); + LLVector4a* clothing_weight = &clothing_weights[out_vert]; + LLVector4a t; + t.setSub(*clothing_weight, clothing_offset); + clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight); + } + } + } + } + + // set last weight to 0, since we've removed the effect of this morph + mLastWeight = 0.f; + + mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights); + + apply(mLastSex); +} + +void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight) +{ + // now apply volume changes + for(LLPolyVolumeMorph& volume_morph : mVolumeMorphs) + { + LLVector3 scale_delta = volume_morph.mScale * delta_weight; + LLVector3 pos_delta = volume_morph.mPos * delta_weight; + + volume_morph.mVolume->setScale(volume_morph.mVolume->getScale() + scale_delta); + // SL-315 + volume_morph.mVolume->setPosition(volume_morph.mVolume->getPosition() + pos_delta); + } +} + +//----------------------------------------------------------------------------- +// LLPolyVertexMask() +//----------------------------------------------------------------------------- +LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data) + : mWeights(new F32[morph_data->mNumIndices]), + mMorphData(morph_data), + mWeightsGenerated(false) +{ + llassert(mMorphData != NULL); + llassert(mMorphData->mNumIndices > 0); +} + +//----------------------------------------------------------------------------- +// LLPolyVertexMask() +//----------------------------------------------------------------------------- +LLPolyVertexMask::LLPolyVertexMask(const LLPolyVertexMask& pOther) + : mWeights(new F32[pOther.mMorphData->mNumIndices]), + mMorphData(pOther.mMorphData), + mWeightsGenerated(pOther.mWeightsGenerated) +{ + llassert(mMorphData != NULL); + llassert(mMorphData->mNumIndices > 0); + memcpy(mWeights, pOther.mWeights, sizeof(F32) * mMorphData->mNumIndices); +} + +//----------------------------------------------------------------------------- +// ~LLPolyVertexMask() +//----------------------------------------------------------------------------- +LLPolyVertexMask::~LLPolyVertexMask() +{ + delete [] mWeights; + mWeights = NULL; +} + +//----------------------------------------------------------------------------- +// generateMask() +//----------------------------------------------------------------------------- +void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights) +{ +// RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) +// bool debugImg = false; +// if (debugImg) +// { +// if (invert) +// { +// imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData); +// } +// else +// { +// imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData); +// } +// } + for (U32 index = 0; index < mMorphData->mNumIndices; index++) + { + S32 vertIndex = mMorphData->mVertexIndices[index]; + const S32 *sharedVertIndex = mMorphData->mMesh->getSharedVert(vertIndex); + LLVector2 uvCoords; + + if (sharedVertIndex) + { + uvCoords = mMorphData->mMesh->getUVs(*sharedVertIndex); + } + else + { + uvCoords = mMorphData->mMesh->getUVs(vertIndex); + } + U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1); + U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1); + + mWeights[index] = maskTextureData ? ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f : 0.0f; + + if (invert) + { + mWeights[index] = 1.f - mWeights[index]; + } + + // now apply step function + // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f; + + if (clothing_weights) + { + clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; + } + } + mWeightsGenerated = true; +} + +//----------------------------------------------------------------------------- +// getMaskForMorphIndex() +//----------------------------------------------------------------------------- +F32* LLPolyVertexMask::getMorphMaskWeights() +{ + if (!mWeightsGenerated) + { + return NULL; + } + + return mWeights; +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/llappearance/llpolymorph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index d8109d79c2..068be84441 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -107,7 +107,7 @@ LLPolyMorphData::~LLPolyMorphData() bool LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) { S32 numVertices; - S32 numRead; + size_t numRead; numRead = fread(&numVertices, sizeof(S32), 1, fp); llendianswizzle(&numVertices, sizeof(S32), 1); @@ -384,7 +384,7 @@ bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) if (!mMorphData) { const std::string driven_tag = "_Driven"; - U32 pos = morph_param_name.find(driven_tag); + auto pos = morph_param_name.find(driven_tag); if (pos > 0) { morph_param_name = morph_param_name.substr(0,pos); -- cgit v1.2.3 From 9e45c1e506e0cdf8ade6136da9bbf867c93d16e6 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 9 Jun 2024 16:17:03 +0200 Subject: Fix issues resulting from b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 --- indra/llappearance/llpolymorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 068be84441..7deb943a9b 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -385,7 +385,7 @@ bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { const std::string driven_tag = "_Driven"; auto pos = morph_param_name.find(driven_tag); - if (pos > 0) + if (pos != std::string::npos) { morph_param_name = morph_param_name.substr(0,pos); mMorphData = mMesh->getMorphData(morph_param_name); -- cgit v1.2.3 From 8703d5b0f91d303a33624edb26ebed16c1c6d941 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 9 Jun 2024 16:21:28 +0200 Subject: Found string should not be directly at the start --- indra/llappearance/llpolymorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 7deb943a9b..7ae760d312 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -385,7 +385,7 @@ bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { const std::string driven_tag = "_Driven"; auto pos = morph_param_name.find(driven_tag); - if (pos != std::string::npos) + if (pos != std::string::npos && pos > 0) { morph_param_name = morph_param_name.substr(0,pos); mMorphData = mMesh->getMorphData(morph_param_name); -- cgit v1.2.3 From 9fdca96f8bd2211a99fe88e57b70cbecefa20b6d Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 8 Jul 2024 20:27:14 +0200 Subject: Re-enable compiler warnings C4244 and C4396 except for lltracerecording.h and llunittype.h for now --- indra/llappearance/llpolymorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance/llpolymorph.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 7ae760d312..8df8a9726f 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -557,7 +557,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) } if (mLastWeight != mLastWeight) { - mLastWeight = mCurWeight+.001; + mLastWeight = mCurWeight+.001f; } // perform differential update of morph -- cgit v1.2.3