From 5345d1e115fdf3fca7ea3e8330f1a23ad19257c8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 26 Jan 2016 08:23:40 -0500 Subject: SL-315 WIP - added a call stack extractor for windows to help with tracing joint issues (of course, could be used for other things as well). --- indra/llcommon/StackWalker.h | 223 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 indra/llcommon/StackWalker.h (limited to 'indra/llcommon/StackWalker.h') diff --git a/indra/llcommon/StackWalker.h b/indra/llcommon/StackWalker.h new file mode 100644 index 0000000000..f4ef8d557f --- /dev/null +++ b/indra/llcommon/StackWalker.h @@ -0,0 +1,223 @@ +/********************************************************************** + * + * StackWalker.h + * + * + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * + * LICENSE (http://www.opensource.org/licenses/bsd-license.php) + * + * Copyright (c) 2005-2009, Jochen Kalmbach + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of Jochen Kalmbach nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * **********************************************************************/ + +#if LL_WINDOWS + +// #pragma once is supported starting with _MCS_VER 1000, +// so we need not to check the version (because we only support _MSC_VER >= 1100)! +#pragma once + +#include + +// special defines for VC5/6 (if no actual PSDK is installed): +#if _MSC_VER < 1300 +typedef unsigned __int64 DWORD64, *PDWORD64; +#if defined(_WIN64) +typedef unsigned __int64 SIZE_T, *PSIZE_T; +#else +typedef unsigned long SIZE_T, *PSIZE_T; +#endif +#endif // _MSC_VER < 1300 + +class StackWalkerInternal; // forward +class StackWalker +{ +public: + typedef enum StackWalkOptions + { + // No addition info will be retrived + // (only the address is available) + RetrieveNone = 0, + + // Try to get the symbol-name + RetrieveSymbol = 1, + + // Try to get the line for this symbol + RetrieveLine = 2, + + // Try to retrieve the module-infos + RetrieveModuleInfo = 4, + + // Also retrieve the version for the DLL/EXE + RetrieveFileVersion = 8, + + // Contains all the abouve + RetrieveVerbose = 0xF, + + // Generate a "good" symbol-search-path + SymBuildPath = 0x10, + + // Also use the public Microsoft-Symbol-Server + SymUseSymSrv = 0x20, + + // Contains all the abouve "Sym"-options + SymAll = 0x30, + + // Contains all options (default) + OptionsAll = 0x3F + } StackWalkOptions; + + StackWalker( + bool verbose = true, + int options = OptionsAll, // 'int' is by design, to combine the enum-flags + LPCSTR szSymPath = NULL, + DWORD dwProcessId = GetCurrentProcessId(), + HANDLE hProcess = GetCurrentProcess() + ); + StackWalker(DWORD dwProcessId, HANDLE hProcess); + virtual ~StackWalker(); + + typedef BOOL (__stdcall *PReadProcessMemoryRoutine)( + HANDLE hProcess, + DWORD64 qwBaseAddress, + PVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead, + LPVOID pUserData // optional data, which was passed in "ShowCallstack" + ); + + BOOL LoadModules(); + + BOOL ShowCallstack( + HANDLE hThread = GetCurrentThread(), + const CONTEXT *context = NULL, + PReadProcessMemoryRoutine readMemoryFunction = NULL, + LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback + ); + +#if _MSC_VER >= 1300 +// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public" +// in older compilers in order to use it... starting with VC7 we can declare it as "protected" +protected: +#endif + enum { STACKWALK_MAX_NAMELEN = 1024 }; // max name length for found symbols + +protected: + // Entry for each Callstack-Entry + typedef struct CallstackEntry + { + DWORD64 offset; // if 0, we have no valid entry + CHAR name[STACKWALK_MAX_NAMELEN]; + CHAR undName[STACKWALK_MAX_NAMELEN]; + CHAR undFullName[STACKWALK_MAX_NAMELEN]; + DWORD64 offsetFromSmybol; + DWORD offsetFromLine; + DWORD lineNumber; + CHAR lineFileName[STACKWALK_MAX_NAMELEN]; + DWORD symType; + LPCSTR symTypeString; + CHAR moduleName[STACKWALK_MAX_NAMELEN]; + DWORD64 baseOfImage; + CHAR loadedImageName[STACKWALK_MAX_NAMELEN]; + } CallstackEntry; + + typedef enum CallstackEntryType {firstEntry, nextEntry, lastEntry}; + + virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName); + virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion); + virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry); + virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr); + virtual void OnOutput(LPCSTR szText); + + StackWalkerInternal *m_sw; + HANDLE m_hProcess; + DWORD m_dwProcessId; + BOOL m_modulesLoaded; + LPSTR m_szSymPath; + + bool m_verbose; + int m_options; + int m_MaxRecursionCount; + + static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead); + + friend StackWalkerInternal; +}; // class StackWalker + + +// The "ugly" assembler-implementation is needed for systems before XP +// If you have a new PSDK and you only compile for XP and later, then you can use +// the "RtlCaptureContext" +// Currently there is no define which determines the PSDK-Version... +// So we just use the compiler-version (and assumes that the PSDK is +// the one which was installed by the VS-IDE) + +// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later... +// But I currently use it in x64/IA64 environments... +//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400) + +#if defined(_M_IX86) +#ifdef CURRENT_THREAD_VIA_EXCEPTION +// TODO: The following is not a "good" implementation, +// because the callstack is only valid in the "__except" block... +#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \ + do { \ + memset(&c, 0, sizeof(CONTEXT)); \ + EXCEPTION_POINTERS *pExp = NULL; \ + __try { \ + throw 0; \ + } __except( ( (pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER)) {} \ + if (pExp != NULL) \ + memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \ + c.ContextFlags = contextFlags; \ + } while(0); +#else +// The following should be enough for walking the callstack... +#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \ + do { \ + memset(&c, 0, sizeof(CONTEXT)); \ + c.ContextFlags = contextFlags; \ + __asm call x \ + __asm x: pop eax \ + __asm mov c.Eip, eax \ + __asm mov c.Ebp, ebp \ + __asm mov c.Esp, esp \ + } while(0); +#endif + +#else + +// The following is defined for x86 (XP and higher), x64 and IA64: +#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \ + do { \ + memset(&c, 0, sizeof(CONTEXT)); \ + c.ContextFlags = contextFlags; \ + RtlCaptureContext(&c); \ +} while(0); +#endif + +#endif // LL_WINDOWS -- cgit v1.3 From e91a192301db37f99a4f5a817f3b4c47b448417a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 26 Jan 2016 11:11:52 -0500 Subject: SL-315 WIP - added callstack info to joint debugging. Made joint debugging run-time configurable via debug setting DebugAvatarJoints --- indra/llcharacter/lljoint.cpp | 27 ++++++++++++++++++++++++++- indra/llcharacter/lljoint.h | 4 ++++ indra/llcommon/StackWalker.cpp | 2 +- indra/llcommon/StackWalker.h | 2 +- indra/llcommon/llcallstack.cpp | 15 +++++++++------ indra/llcommon/llcallstack.h | 3 ++- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llviewercontrol.cpp | 8 ++++++++ indra/newview/llvoavatar.cpp | 3 +++ indra/newview/llvoavatarself.cpp | 3 --- 10 files changed, 65 insertions(+), 13 deletions(-) (limited to 'indra/llcommon/StackWalker.h') diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 8fcab454dc..a314692edc 100755 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -32,6 +32,8 @@ #include "lljoint.h" #include "llmath.h" +#include "llcallstack.h" +#include S32 LLJoint::sNumUpdates = 0; S32 LLJoint::sNumTouches = 0; @@ -313,7 +315,11 @@ const LLVector3& LLJoint::getPosition() bool do_debug_joint(const std::string& name) { - return false; + if (std::find(LLJoint::s_debugJointNames.begin(), LLJoint::s_debugJointNames.end(),name) != LLJoint::s_debugJointNames.end()) + { + return true; + } + return false; } //-------------------------------------------------------------------- @@ -325,7 +331,9 @@ void LLJoint::setPosition( const LLVector3& pos ) { if (do_debug_joint(getName())) { + LLCallStack cs; LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL; + LL_DEBUGS("Avatar") << "STACK:\n" << "====================\n" << cs << "====================" << LL_ENDL; } } mXform.setPosition(pos); @@ -427,6 +435,23 @@ void LLJoint::updatePos(const std::string& av_info) setPosition(pos); } +// init static +LLJoint::debug_joint_name_t LLJoint::s_debugJointNames = debug_joint_name_t(); + +//-------------------------------------------------------------------- +// setDebugJointNames +//-------------------------------------------------------------------- +void LLJoint::setDebugJointNames(const debug_joint_name_t& names) +{ + s_debugJointNames = names; +} +void LLJoint::setDebugJointNames(const std::string& names_string) +{ + debug_joint_name_t names; + boost::split(names, names_string, boost::is_any_of(" :,")); + setDebugJointNames(names); +} + //-------------------------------------------------------------------- // getWorldPosition() //-------------------------------------------------------------------- diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 424f172318..ab21f73122 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -130,6 +130,10 @@ public: // debug statics static S32 sNumTouches; static S32 sNumUpdates; + typedef std::set debug_joint_name_t; + static debug_joint_name_t s_debugJointNames; + static void setDebugJointNames(const debug_joint_name_t& names); + static void setDebugJointNames(const std::string& names_string); LLPosOverrideMap m_attachmentOverrides; LLVector3 m_posBeforeOverrides; diff --git a/indra/llcommon/StackWalker.cpp b/indra/llcommon/StackWalker.cpp index da52386a22..768595f5de 100644 --- a/indra/llcommon/StackWalker.cpp +++ b/indra/llcommon/StackWalker.cpp @@ -4,7 +4,7 @@ * http://stackwalker.codeplex.com/ * * - * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * $LicenseInfo:firstyear=2016&license=bsd$ * * History: * 2005-07-27 v1 - First public release on http://www.codeproject.com/ diff --git a/indra/llcommon/StackWalker.h b/indra/llcommon/StackWalker.h index f4ef8d557f..b29cdbfc81 100644 --- a/indra/llcommon/StackWalker.h +++ b/indra/llcommon/StackWalker.h @@ -4,7 +4,7 @@ * * * - * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * $LicenseInfo:firstyear=2016&license=bsd$ * * LICENSE (http://www.opensource.org/licenses/bsd-license.php) * diff --git a/indra/llcommon/llcallstack.cpp b/indra/llcommon/llcallstack.cpp index 87eb37de16..02cf4d0173 100644 --- a/indra/llcommon/llcallstack.cpp +++ b/indra/llcommon/llcallstack.cpp @@ -39,12 +39,14 @@ public: ~LLCallStackImpl() { } - void getStack(std::vector& stack) + void getStack(std::vector& stack, S32 skip_count=0) { m_stack.clear(); ShowCallstack(); - // Skip the first 2 lines because they're just bookkeeping for LLCallStack. - for (S32 i=3; i& stack) + void getStack(std::vector& stack, S32 skip_count=0) { stack.clear(); } @@ -72,14 +74,15 @@ public: LLCallStackImpl *LLCallStack::s_impl = NULL; -LLCallStack::LLCallStack() +LLCallStack::LLCallStack(S32 skip_count): + m_skipCount(skip_count) { if (!s_impl) { s_impl = new LLCallStackImpl; } LLTimer t; - s_impl->getStack(m_strings); + s_impl->getStack(m_strings, m_skipCount); } std::ostream& operator<<(std::ostream& s, const LLCallStack& call_stack) diff --git a/indra/llcommon/llcallstack.h b/indra/llcommon/llcallstack.h index 6059d4f2c5..598db3d404 100644 --- a/indra/llcommon/llcallstack.h +++ b/indra/llcommon/llcallstack.h @@ -29,10 +29,11 @@ class LLCallStackImpl; class LLCallStack { public: - LLCallStack(); + LLCallStack(S32 skip_count=0); std::vector m_strings; private: static LLCallStackImpl *s_impl; + S32 m_skipCount; }; LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCallStack& call_stack); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 32707e7653..e1f2ecff0c 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2182,6 +2182,17 @@ String Value + + DebugAvatarJoints + + Comment + List of joints to emit additional debugging info about. + Persist + 1 + Type + String + Value + DebugAvatarRezTime diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 612fd9a326..3532a872c9 100755 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -120,6 +120,13 @@ static bool handleTerrainDetailChanged(const LLSD& newvalue) } +static bool handleDebugAvatarJointsChanged(const LLSD& newvalue) +{ + std::string new_string = newvalue.asString(); + LLJoint::setDebugJointNames(new_string); + return true; +} + static bool handleDeferredDebugSettingChanged(const LLSD& newvalue) { LLNotificationsUtil::add("ChangeDeferredDebugSetting"); @@ -769,6 +776,7 @@ void settings_setup_listeners() gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged)); gSavedSettings.getControl("IncludeEnhancedSkeleton")->getCommitSignal()->connect(boost::bind(&handleDeferredDebugSettingChanged, _2)); + gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index efc07fffe5..ffe51ee0ae 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1084,6 +1084,9 @@ void LLVOAvatar::initClass() gAnimLibrary.animStateSetString(ANIM_AGENT_PELVIS_FIX,"pelvis_fix"); gAnimLibrary.animStateSetString(ANIM_AGENT_TARGET,"target"); gAnimLibrary.animStateSetString(ANIM_AGENT_WALK_ADJUST,"walk_adjust"); + + // Where should this be set initially? + LLJoint::setDebugJointNames(gSavedSettings.getString("DebugAvatarJoints")); } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 0648ee6732..aadcce95b9 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -207,9 +207,6 @@ bool update_avatar_rez_metrics() gAgentAvatarp->updateAvatarRezMetrics(false); - LLCallStack cs; - LL_INFOS() << "CallStack:\n" << cs << LL_ENDL; - return false; } -- cgit v1.3 From c92079db31f60196c2c70d6733aeaaaa40f1f485 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 28 Jan 2016 10:40:38 -0500 Subject: SL-315 - verbose option for CallStack objects, doc headers in StackWalker.{h,cpp} --- indra/llcommon/StackWalker.cpp | 5 ++++- indra/llcommon/StackWalker.h | 3 +++ indra/llcommon/llcallstack.cpp | 11 ++++++----- indra/llcommon/llcallstack.h | 3 ++- 4 files changed, 15 insertions(+), 7 deletions(-) (limited to 'indra/llcommon/StackWalker.h') diff --git a/indra/llcommon/StackWalker.cpp b/indra/llcommon/StackWalker.cpp index 768595f5de..c0d3104099 100644 --- a/indra/llcommon/StackWalker.cpp +++ b/indra/llcommon/StackWalker.cpp @@ -6,6 +6,8 @@ * * $LicenseInfo:firstyear=2016&license=bsd$ * + * Linden notes: Small modifications from the original source at https://stackwalker.codeplex.com/ + * * History: * 2005-07-27 v1 - First public release on http://www.codeproject.com/ * http://www.codeproject.com/threads/StackWalker.asp @@ -1012,8 +1014,9 @@ BOOL StackWalker::LoadModules() static StackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = NULL; static LPVOID s_readMemoryFunction_UserData = NULL; -BOOL StackWalker::ShowCallstack(HANDLE hThread, const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData) +BOOL StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData) { + m_verbose = verbose; CONTEXT c; CallstackEntry csEntry; IMAGEHLP_SYMBOL64 *pSym = NULL; diff --git a/indra/llcommon/StackWalker.h b/indra/llcommon/StackWalker.h index b29cdbfc81..4ff6e736da 100644 --- a/indra/llcommon/StackWalker.h +++ b/indra/llcommon/StackWalker.h @@ -6,6 +6,8 @@ * * $LicenseInfo:firstyear=2016&license=bsd$ * + * Linden notes: Small modifications from the original source at https://stackwalker.codeplex.com/ + * * LICENSE (http://www.opensource.org/licenses/bsd-license.php) * * Copyright (c) 2005-2009, Jochen Kalmbach @@ -113,6 +115,7 @@ public: BOOL LoadModules(); BOOL ShowCallstack( + bool verbose, HANDLE hThread = GetCurrentThread(), const CONTEXT *context = NULL, PReadProcessMemoryRoutine readMemoryFunction = NULL, diff --git a/indra/llcommon/llcallstack.cpp b/indra/llcommon/llcallstack.cpp index 02cf4d0173..e4b3cfeab5 100644 --- a/indra/llcommon/llcallstack.cpp +++ b/indra/llcommon/llcallstack.cpp @@ -39,10 +39,10 @@ public: ~LLCallStackImpl() { } - void getStack(std::vector& stack, S32 skip_count=0) + void getStack(std::vector& stack, S32 skip_count=0, bool verbose=false) { m_stack.clear(); - ShowCallstack(); + ShowCallstack(verbose); // Skip the first few lines because they're just bookkeeping for LLCallStack, // plus any additional lines requested to skip. S32 first_line = skip_count + 3; @@ -74,15 +74,16 @@ public: LLCallStackImpl *LLCallStack::s_impl = NULL; -LLCallStack::LLCallStack(S32 skip_count): - m_skipCount(skip_count) +LLCallStack::LLCallStack(S32 skip_count, bool verbose): + m_skipCount(skip_count), + m_verbose(verbose) { if (!s_impl) { s_impl = new LLCallStackImpl; } LLTimer t; - s_impl->getStack(m_strings, m_skipCount); + s_impl->getStack(m_strings, m_skipCount, m_verbose); } std::ostream& operator<<(std::ostream& s, const LLCallStack& call_stack) diff --git a/indra/llcommon/llcallstack.h b/indra/llcommon/llcallstack.h index 598db3d404..44a572838e 100644 --- a/indra/llcommon/llcallstack.h +++ b/indra/llcommon/llcallstack.h @@ -29,8 +29,9 @@ class LLCallStackImpl; class LLCallStack { public: - LLCallStack(S32 skip_count=0); + LLCallStack(S32 skip_count=0, bool verbose=false); std::vector m_strings; + bool m_verbose; private: static LLCallStackImpl *s_impl; S32 m_skipCount; -- cgit v1.3 From f1e6f5c72a1df374252698f68de51de4d4238cc4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 23 Feb 2016 09:34:40 -0500 Subject: SL-287 WIP - fixed default avatar crash caused by added spine joints. Still renders distorted. --- indra/llappearance/llavatarjointmesh.cpp | 60 ++++--- indra/llcharacter/lljoint.h | 2 +- indra/llcommon/StackWalker.h | 2 +- .../character/avatar_skeleton_spine_joints.xml | 198 +++++++++++++++++++++ indra/newview/llviewerjointmesh.cpp | 2 +- 5 files changed, 241 insertions(+), 23 deletions(-) create mode 100644 indra/newview/character/avatar_skeleton_spine_joints.xml (limited to 'indra/llcommon/StackWalker.h') diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index 747579fca2..8b052ac198 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -79,6 +79,28 @@ LLSkinJoint::~LLSkinJoint() } +LLAvatarJoint *getBaseSkeletonAncestor(LLAvatarJoint* joint) +{ + LLJoint *ancestor = joint->getParent(); + while (ancestor->getParent() && (ancestor->getSupport() != LLJoint::SUPPORT_BASE)) + { + LL_DEBUGS("Avatar") << "skipping non-base ancestor " << ancestor->getName() << LL_ENDL; + ancestor = ancestor->getParent(); + } + return (LLAvatarJoint*) ancestor; +} + +LLVector3 totalSkinOffset(LLAvatarJoint *joint) +{ + LLVector3 totalOffset; + while (joint) + { + totalOffset += joint->getSkinOffset(); + joint = (LLAvatarJoint*)joint->getParent(); + } + return totalOffset; +} + //----------------------------------------------------------------------------- // LLSkinJoint::setupSkinJoint() //----------------------------------------------------------------------------- @@ -92,18 +114,12 @@ BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) } // compute the inverse root skin matrix - mRootToJointSkinOffset.clearVec(); + mRootToJointSkinOffset = totalSkinOffset(joint); + mRootToJointSkinOffset = -mRootToJointSkinOffset; - LLVector3 rootSkinOffset; - while (joint) - { - rootSkinOffset += joint->getSkinOffset(); - joint = (LLAvatarJoint*)joint->getParent(); - } - - mRootToJointSkinOffset = -rootSkinOffset; - mRootToParentJointSkinOffset = mRootToJointSkinOffset; - mRootToParentJointSkinOffset += mJoint->getSkinOffset(); + //mRootToParentJointSkinOffset = totalSkinOffset((LLAvatarJoint*)joint->getParent()); + mRootToParentJointSkinOffset = totalSkinOffset(getBaseSkeletonAncestor(joint)); + mRootToParentJointSkinOffset = -mRootToParentJointSkinOffset; return TRUE; } @@ -315,9 +331,9 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh ) if (!mMesh->isLOD()) { setupJoint((LLAvatarJoint*)getRoot()); + LL_DEBUGS("Avatar") << getName() << " joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL; } - LL_DEBUGS() << "joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL; } //----------------------------------------------------------------------------- @@ -325,8 +341,6 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh ) //----------------------------------------------------------------------------- void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint) { - LL_DEBUGS() << "Mesh: " << getName() << LL_ENDL; - S32 joint_count = 0; U32 sj; @@ -340,22 +354,28 @@ void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint) } // we've found a skinjoint for this joint.. + LL_DEBUGS("Avatar") << "Mesh: " << getName() << " joint " << current_joint->getName() << " matches skinjoint " << sj << LL_ENDL; // is the last joint in the array our parent? - if(mMesh->mJointRenderData.size() && mMesh->mJointRenderData[mMesh->mJointRenderData.size() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix()) + + // SL-287 - need to update this so the results are the same if + // additional extended-skeleton joints lie between this joint + // and the original parent. + LLJoint *ancestor = getBaseSkeletonAncestor(current_joint); + if(mMesh->mJointRenderData.size() && mMesh->mJointRenderData[mMesh->mJointRenderData.size() - 1]->mWorldMatrix == &ancestor->getWorldMatrix()) { // ...then just add ourselves LLAvatarJoint* jointp = js.mJoint; mMesh->mJointRenderData.push_back(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); - LL_DEBUGS() << "joint " << joint_count++ << js.mJoint->getName() << LL_ENDL; + LL_DEBUGS("Avatar") << "add joint " << joint_count++ << " " << js.mJoint->getName() << LL_ENDL; } - // otherwise add our parent and ourselves + // otherwise add our ancestor and ourselves else { - mMesh->mJointRenderData.push_back(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL)); - LL_DEBUGS() << "joint " << joint_count++ << current_joint->getParent()->getName() << LL_ENDL; + mMesh->mJointRenderData.push_back(new LLJointRenderData(&ancestor->getWorldMatrix(), NULL)); + LL_DEBUGS("Avatar") << "add2 ancestor joint " << joint_count++ << " " << ancestor->getName() << LL_ENDL; mMesh->mJointRenderData.push_back(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); - LL_DEBUGS() << "joint " << joint_count++ << current_joint->getName() << LL_ENDL; + LL_DEBUGS("Avatar") << "add2 joint " << joint_count++ << " " << current_joint->getName() << LL_ENDL; } } diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index e666f177e7..61592363f5 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -42,7 +42,7 @@ const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; // BENTO JOINT COUNT LIMIT - need to set this to final skeleton size // (bones + attachments) + 2, rounded to next multiple of 4. -const U32 LL_CHARACTER_MAX_ANIMATED_JOINTS = 164; // must be divisible by 4! +const U32 LL_CHARACTER_MAX_ANIMATED_JOINTS = 180; // must be divisible by 4! const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 110; // These should be higher than the joint_num of any diff --git a/indra/llcommon/StackWalker.h b/indra/llcommon/StackWalker.h index 4ff6e736da..5a5ed96e6f 100644 --- a/indra/llcommon/StackWalker.h +++ b/indra/llcommon/StackWalker.h @@ -127,7 +127,7 @@ public: // in older compilers in order to use it... starting with VC7 we can declare it as "protected" protected: #endif - enum { STACKWALK_MAX_NAMELEN = 1024 }; // max name length for found symbols + enum { STACKWALK_MAX_NAMELEN = 2048 }; // max name length for found symbols protected: // Entry for each Callstack-Entry diff --git a/indra/newview/character/avatar_skeleton_spine_joints.xml b/indra/newview/character/avatar_skeleton_spine_joints.xml new file mode 100644 index 0000000000..4124df9055 --- /dev/null +++ b/indra/newview/character/avatar_skeleton_spine_joints.xml @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index bf7cf08c63..43a81ada49 100755 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -203,7 +203,7 @@ void LLViewerJointMesh::uploadJointMatrices() // DrawElementsBLEND and utility code //-------------------------------------------------------------------- -// compate_int is used by the qsort function to sort the index array +// compare_int is used by the qsort function to sort the index array int compare_int(const void *a, const void *b) { if (*(U32*)a < *(U32*)b) -- cgit v1.3 From 0447fe5a57c2b3e0406fd28b665ea9f47d689b2f Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 20 Apr 2016 13:18:56 -0400 Subject: SL-371 - increased the limit for StackWalker strings, avoid crashing if mesh has wrong number of mAlternateBindMatrix matrices --- indra/llcommon/StackWalker.h | 2 +- indra/llprimitive/lldaeloader.cpp | 4 +++- indra/newview/llvoavatar.cpp | 8 ++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'indra/llcommon/StackWalker.h') diff --git a/indra/llcommon/StackWalker.h b/indra/llcommon/StackWalker.h index 5a5ed96e6f..834f89c471 100644 --- a/indra/llcommon/StackWalker.h +++ b/indra/llcommon/StackWalker.h @@ -127,7 +127,7 @@ public: // in older compilers in order to use it... starting with VC7 we can declare it as "protected" protected: #endif - enum { STACKWALK_MAX_NAMELEN = 2048 }; // max name length for found symbols + enum { STACKWALK_MAX_NAMELEN = 4096 }; // max name length for found symbols protected: // Entry for each Callstack-Entry diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index df69607404..38b061dd79 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1189,7 +1189,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do S32 childCount = children.getCount(); //Process any children that are joints - //Not all children are joints, some code be ambient lights, cameras, geometry etc.. + //Not all children are joints, some could be ambient lights, cameras, geometry etc.. for (S32 i = 0; i < childCount; ++i) { domNode* pNode = daeSafeCast(children[i]); @@ -1229,6 +1229,8 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do domNode* pJoint = daeSafeCast( resolver.getElement() ); if ( pJoint ) { + // FIXME this has a lot of overlap with processJointNode(), would be nice to refactor. + //Pull out the translate id and store it in the jointTranslations map daeSIDResolver jointResolverA( pJoint, "./translate" ); domTranslate* pTranslateA = daeSafeCast( jointResolverA.getElement() ); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a82f92b01a..af10af98f2 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5299,9 +5299,13 @@ void LLVOAvatar::addAttachmentPosOverridesForObject(LLViewerObject *vo) if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData ) { const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) + const int jointCnt = pSkinData->mJointNames.size(); + if ((bindCnt > 0) && (bindCnt != jointCnt)) + { + LL_WARNS_ONCE() << "invalid mesh, bindCnt " << bindCnt << "!= jointCnt " << jointCnt << ", joint overrides will be ignored." << LL_ENDL; + } + if ((bindCnt > 0) && (bindCnt == jointCnt)) { - const int jointCnt = pSkinData->mJointNames.size(); const F32 pelvisZOffset = pSkinData->mPelvisOffset; const LLUUID& mesh_id = pSkinData->mMeshID; bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false; -- cgit v1.3