/** * @file llvoavatar.cpp * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject * * $LicenseInfo:firstyear=2001&license=viewergpl$ * * Copyright (c) 2001-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llvoavatardefines.h" const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512; const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512; const S32 LLVOAvatarDefines::IMPOSTOR_PERIOD = 2; using namespace LLVOAvatarDefines; /********************************************************************************* * Edit this function to add/remove/change textures and mesh definitions for avatars. */ void LLVOAvatarDictionary::initData() { // Textures mTextureMap[TEX_HEAD_BODYPAINT] = new TextureDictionaryEntry("head bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN); mTextureMap[TEX_UPPER_SHIRT] = new TextureDictionaryEntry("shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", WT_SHIRT); mTextureMap[TEX_LOWER_PANTS] = new TextureDictionaryEntry("pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", WT_PANTS); mTextureMap[TEX_EYES_IRIS] = new TextureDictionaryEntry("iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", WT_EYES); mTextureMap[TEX_HAIR] = new TextureDictionaryEntry("hair", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", WT_HAIR); mTextureMap[TEX_UPPER_BODYPAINT] = new TextureDictionaryEntry("upper bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN); mTextureMap[TEX_LOWER_BODYPAINT] = new TextureDictionaryEntry("lower bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN); mTextureMap[TEX_LOWER_SHOES] = new TextureDictionaryEntry("shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", WT_SHOES); mTextureMap[TEX_LOWER_SOCKS] = new TextureDictionaryEntry("socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", WT_SOCKS); mTextureMap[TEX_UPPER_JACKET] = new TextureDictionaryEntry("upper jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", WT_JACKET); mTextureMap[TEX_LOWER_JACKET] = new TextureDictionaryEntry("lower jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", WT_JACKET); mTextureMap[TEX_UPPER_GLOVES] = new TextureDictionaryEntry("gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", WT_GLOVES); mTextureMap[TEX_UPPER_UNDERSHIRT] = new TextureDictionaryEntry("undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERSHIRT); mTextureMap[TEX_LOWER_UNDERPANTS] = new TextureDictionaryEntry("underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERPANTS); mTextureMap[TEX_SKIRT] = new TextureDictionaryEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", WT_SKIRT); mTextureMap[TEX_LOWER_ALPHA] = new TextureDictionaryEntry("lower_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA); mTextureMap[TEX_UPPER_ALPHA] = new TextureDictionaryEntry("upper_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA); mTextureMap[TEX_HEAD_ALPHA] = new TextureDictionaryEntry("head_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA); mTextureMap[TEX_EYES_ALPHA] = new TextureDictionaryEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA); mTextureMap[TEX_HAIR_ALPHA] = new TextureDictionaryEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA); mTextureMap[TEX_HEAD_TATTOO] = new TextureDictionaryEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO); mTextureMap[TEX_UPPER_TATTOO] = new TextureDictionaryEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO); mTextureMap[TEX_LOWER_TATTOO] = new TextureDictionaryEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO); mTextureMap[TEX_HEAD_BAKED] = new TextureDictionaryEntry("head-baked", FALSE, BAKED_HEAD); mTextureMap[TEX_UPPER_BAKED] = new TextureDictionaryEntry("upper-baked", FALSE, BAKED_UPPER); mTextureMap[TEX_LOWER_BAKED] = new TextureDictionaryEntry("lower-baked", FALSE, BAKED_LOWER); mTextureMap[TEX_EYES_BAKED] = new TextureDictionaryEntry("eyes-baked", FALSE, BAKED_EYES); mTextureMap[TEX_HAIR_BAKED] = new TextureDictionaryEntry("hair-baked", FALSE, BAKED_HAIR); mTextureMap[TEX_SKIRT_BAKED] = new TextureDictionaryEntry("skirt-baked", FALSE, BAKED_SKIRT); // Baked textures mBakedTextureMap[BAKED_HEAD] = new BakedDictionaryEntry(TEX_HEAD_BAKED, "head", 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA); mBakedTextureMap[BAKED_UPPER] = new BakedDictionaryEntry(TEX_UPPER_BAKED, "upper_body", 7, TEX_UPPER_SHIRT, TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA); mBakedTextureMap[BAKED_LOWER] = new BakedDictionaryEntry(TEX_LOWER_BAKED, "lower_body", 8, TEX_LOWER_PANTS, TEX_LOWER_BODYPAINT, TEX_LOWER_SHOES, TEX_LOWER_SOCKS, TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA); mBakedTextureMap[BAKED_EYES] = new BakedDictionaryEntry(TEX_EYES_BAKED, "eyes", 2, TEX_EYES_IRIS, TEX_EYES_ALPHA); mBakedTextureMap[BAKED_SKIRT] = new BakedDictionaryEntry(TEX_SKIRT_BAKED, "skirt", 1, TEX_SKIRT); mBakedTextureMap[BAKED_HAIR] = new BakedDictionaryEntry(TEX_HAIR_BAKED, "hair", 2, TEX_HAIR, TEX_HAIR_ALPHA); // Meshes mMeshMap[MESH_ID_HAIR] = new MeshDictionaryEntry(BAKED_HAIR, "hairMesh", 6, LLViewerJoint::PN_4); mMeshMap[MESH_ID_HEAD] = new MeshDictionaryEntry(BAKED_HEAD, "headMesh", 5, LLViewerJoint::PN_5); mMeshMap[MESH_ID_EYELASH] = new MeshDictionaryEntry(BAKED_HEAD, "eyelashMesh", 1, LLViewerJoint::PN_0); // no baked mesh associated currently mMeshMap[MESH_ID_UPPER_BODY] = new MeshDictionaryEntry(BAKED_UPPER, "upperBodyMesh", 5, LLViewerJoint::PN_1); mMeshMap[MESH_ID_LOWER_BODY] = new MeshDictionaryEntry(BAKED_LOWER, "lowerBodyMesh", 5, LLViewerJoint::PN_2); mMeshMap[MESH_ID_EYEBALL_LEFT] = new MeshDictionaryEntry(BAKED_EYES, "eyeBallLeftMesh", 2, LLViewerJoint::PN_3); mMeshMap[MESH_ID_EYEBALL_RIGHT] = new MeshDictionaryEntry(BAKED_EYES, "eyeBallRightMesh", 2, LLViewerJoint::PN_3); mMeshMap[MESH_ID_SKIRT] = new MeshDictionaryEntry(BAKED_SKIRT, "skirtMesh", 5, LLViewerJoint::PN_5); // Wearables mWearableMap[BAKED_HEAD] = new WearableDictionaryEntry("18ded8d6-bcfc-e415-8539-944c0f5ea7a6", 5, WT_SHAPE, WT_SKIN, WT_HAIR, WT_TATTOO, WT_ALPHA); mWearableMap[BAKED_UPPER] = new WearableDictionaryEntry("338c29e3-3024-4dbb-998d-7c04cf4fa88f", 8, WT_SHAPE, WT_SKIN, WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT, WT_TATTOO, WT_ALPHA); mWearableMap[BAKED_LOWER] = new WearableDictionaryEntry("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f", 9, WT_SHAPE, WT_SKIN, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_UNDERPANTS, WT_TATTOO, WT_ALPHA); mWearableMap[BAKED_EYES] = new WearableDictionaryEntry("b2cf28af-b840-1071-3c6a-78085d8128b5", 2, WT_EYES, WT_ALPHA); mWearableMap[BAKED_SKIRT] = new WearableDictionaryEntry("ea800387-ea1a-14e0-56cb-24f2022f969a", 1, WT_SKIRT); mWearableMap[BAKED_HAIR] = new WearableDictionaryEntry("0af1ef7c-ad24-11dd-8790-001f5bf833e8", 2, WT_HAIR, WT_ALPHA); } /* * *********************************************************************************/ LLVOAvatarDictionary::LLVOAvatarDictionary() { initData(); createAssociations(); } // Baked textures are composites of textures; for each such composited texture, // map it to the baked texture. void LLVOAvatarDictionary::createAssociations() { for (baked_map_t::const_iterator iter = mBakedTextureMap.begin(); iter != mBakedTextureMap.end(); iter++) { const EBakedTextureIndex baked_index = (iter->first); const BakedDictionaryEntry *dict = (iter->second); // For each texture that this baked texture index affects, associate those textures // with this baked texture index. for (texture_vec_t::const_iterator local_texture_iter = dict->mLocalTextures.begin(); local_texture_iter != dict->mLocalTextures.end(); local_texture_iter++) { const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter; mTextureMap[local_texture_index]->mIsUsedByBakedTexture = true; mTextureMap[local_texture_index]->mBakedTextureIndex = baked_index; } } } LLVOAvatarDictionary::TextureDictionaryEntry::TextureDictionaryEntry(const std::string &name, bool is_local_texture, EBakedTextureIndex baked_texture_index, const std::string &default_image_name, EWearableType wearable_type) : mName(name), mIsLocalTexture(is_local_texture), mIsBakedTexture(!is_local_texture), mIsUsedByBakedTexture(baked_texture_index != BAKED_NUM_INDICES), mBakedTextureIndex(baked_texture_index), mDefaultImageName(default_image_name), mWearableType(wearable_type) { } LLVOAvatarDictionary::MeshDictionaryEntry::MeshDictionaryEntry(EBakedTextureIndex baked_index, const std::string &name, U8 level, LLViewerJoint::PickName pick) : mBakedID(baked_index), mName(name), mLOD(level), mPickName(pick) { } LLVOAvatarDictionary::BakedDictionaryEntry::BakedDictionaryEntry(ETextureIndex tex_index, const std::string &name, U32 num_local_textures, ... ) : mName(name), mTextureIndex(tex_index) { va_list argp; va_start(argp, num_local_textures); for (U8 i=0; i < num_local_textures; i++) { ETextureIndex t = (ETextureIndex)va_arg(argp,int); mLocalTextures.push_back(t); } } LLVOAvatarDictionary::WearableDictionaryEntry::WearableDictionaryEntry(const std::string &hash_name, U32 num_wearables, ... ) : mHashID(LLUUID(hash_name)) { va_list argp; va_start(argp, num_wearables); for (U8 i=0; i < num_wearables; i++) { EWearableType t = (EWearableType)va_arg(argp,int); mWearablesVec.push_back(t); } } //virtual LLVOAvatarDictionary::~LLVOAvatarDictionary() { for (mesh_map_t::iterator iter = mMeshMap.begin(); iter != mMeshMap.end(); iter++) delete (iter->second); for (baked_map_t::iterator iter = mBakedTextureMap.begin(); iter != mBakedTextureMap.end(); iter++) delete (iter->second); for (texture_map_t::iterator iter = mTextureMap.begin(); iter != mTextureMap.end(); iter++) delete (iter->second); } const LLVOAvatarDictionary::MeshDictionaryEntry *LLVOAvatarDictionary::getMesh(EMeshIndex index) const { mesh_map_t::const_iterator mesh_iter = mMeshMap.find(index); if (mesh_iter == mMeshMap.end()) return NULL; return mesh_iter->second; } const LLVOAvatarDictionary::BakedDictionaryEntry *LLVOAvatarDictionary::getBakedTexture(EBakedTextureIndex index) const { baked_map_t::const_iterator baked_iter = mBakedTextureMap.find(index); if (baked_iter == mBakedTextureMap.end()) return NULL; return baked_iter->second; } const LLVOAvatarDictionary::TextureDictionaryEntry *LLVOAvatarDictionary::getTexture(ETextureIndex index) const { texture_map_t::const_iterator texture_iter = mTextureMap.find(index); if (texture_iter == mTextureMap.end()) return NULL; return texture_iter->second; } const LLVOAvatarDictionary::WearableDictionaryEntry *LLVOAvatarDictionary::getWearable(EBakedTextureIndex index) const { wearable_map_t::const_iterator wearable_iter = mWearableMap.find(index); if (wearable_iter == mWearableMap.end()) return NULL; return wearable_iter->second; } ETextureIndex LLVOAvatarDefines::getTextureIndex(EBakedTextureIndex index) { return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; }