12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106 |
- /**
- * @file llpolymesh.cpp
- * @brief Implementation of LLPolyMesh class
- *
- * $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 "llpolymesh.h"
- #include "llavatarappearance.h"
- #include "lldir.h"
- #include "llendianswizzle.h"
- #include "llfasttimer.h"
- #include "llvolume.h"
- #include "llwearable.h"
- #include "llxmltree.h"
- #define HEADER_ASCII "Linden Mesh 1.0"
- #define HEADER_BINARY "Linden Binary Mesh 1.0"
- LLPolyMorphData* clone_morph_param_duplicate(const LLPolyMorphData* src_data,
- const std::string& name);
- LLPolyMorphData* clone_morph_param_direction(const LLPolyMorphData* src_data,
- const LLVector3& direction,
- const std::string& name);
- LLPolyMorphData* clone_morph_param_cleavage(const LLPolyMorphData* src_data,
- F32 scale,
- const std::string& name);
- //-----------------------------------------------------------------------------
- // Global table of loaded LLPolyMeshes
- //-----------------------------------------------------------------------------
- LLPolyMesh::LLPolyMeshSharedDataTable LLPolyMesh::sGlobalSharedMeshList;
- //-----------------------------------------------------------------------------
- // LLPolyMeshSharedData class
- //-----------------------------------------------------------------------------
- LLPolyMeshSharedData::LLPolyMeshSharedData()
- {
- mNumVertices = 0;
- mBaseCoords = NULL;
- mBaseNormals = NULL;
- mBaseBinormals = NULL;
- mTexCoords = NULL;
- mDetailTexCoords = NULL;
- mWeights = NULL;
- mHasWeights = false;
- mHasDetailTexCoords = false;
- mNumFaces = 0;
- mFaces = NULL;
- mNumJointNames = 0;
- mJointNames = NULL;
- mTriangleIndices = NULL;
- mNumTriangleIndices = 0;
- mReferenceData = NULL;
- mLastIndexOffset = -1;
- }
- LLPolyMeshSharedData::~LLPolyMeshSharedData()
- {
- freeMeshData();
- for_each(mMorphData.begin(), mMorphData.end(), DeletePointer());
- mMorphData.clear();
- }
- void LLPolyMeshSharedData::setupLOD(LLPolyMeshSharedData* reference_data)
- {
- mReferenceData = reference_data;
- if (reference_data)
- {
- mBaseCoords = reference_data->mBaseCoords;
- mBaseNormals = reference_data->mBaseNormals;
- mBaseBinormals = reference_data->mBaseBinormals;
- mTexCoords = reference_data->mTexCoords;
- mDetailTexCoords = reference_data->mDetailTexCoords;
- mWeights = reference_data->mWeights;
- mHasWeights = reference_data->mHasWeights;
- mHasDetailTexCoords = reference_data->mHasDetailTexCoords;
- }
- }
- void LLPolyMeshSharedData::freeMeshData()
- {
- if (!mReferenceData)
- {
- freeVertexData();
- }
- mNumFaces = 0;
- if (mFaces)
- {
- delete[] mFaces;
- mFaces = NULL;
- }
- mNumJointNames = 0;
- if (mJointNames)
- {
- delete[] mJointNames;
- mJointNames = NULL;
- }
- if (mTriangleIndices)
- {
- delete[] mTriangleIndices;
- mTriangleIndices = NULL;
- }
- }
- // compate_int is used by the qsort function to sort the index array
- S32 compare_int(const void* a, const void* b);
- #if 0 // Dead code
- void LLPolyMeshSharedData::genIndices(S32 index_offset)
- {
- if (index_offset == mLastIndexOffset)
- {
- return;
- }
- if (mTriangleIndices)
- {
- delete[] mTriangleIndices;
- }
- mTriangleIndices = new U32[mNumTriangleIndices];
- S32 cur_index = 0;
- for (S32 i = 0; i < mNumFaces; ++i)
- {
- mTriangleIndices[cur_index++] = mFaces[i][0] + index_offset;
- mTriangleIndices[cur_index++] = mFaces[i][1] + index_offset;
- mTriangleIndices[cur_index++] = mFaces[i][2] + index_offset;
- }
- mLastIndexOffset = index_offset;
- }
- #endif
- U32 LLPolyMeshSharedData::getNumKB()
- {
- U32 bytes = sizeof(LLPolyMesh);
- if (!isLOD())
- {
- bytes += mNumVertices * (sizeof(LLVector3) + // coords
- sizeof(LLVector3) + // normals
- sizeof(LLVector2)); // texCoords
- }
- if (mHasDetailTexCoords && !isLOD())
- {
- bytes += mNumVertices * sizeof(LLVector2); // detailTexCoords
- }
- if (mHasWeights && !isLOD())
- {
- bytes += mNumVertices * sizeof(float); // weights
- }
- bytes += mNumFaces * sizeof(LLPolyFace); // faces
- return bytes / 1024;
- }
- bool LLPolyMeshSharedData::allocateVertexData(U32 n_vertices)
- {
- mBaseCoords =(LLVector4a*)allocate_volume_mem(n_vertices * sizeof(LLVector4a));
- if (!mBaseCoords)
- {
- freeVertexData();
- return false;
- }
- mBaseNormals = (LLVector4a*)allocate_volume_mem(n_vertices * sizeof(LLVector4a));
- if (!mBaseNormals)
- {
- freeVertexData();
- return false;
- }
- mBaseBinormals = (LLVector4a*)allocate_volume_mem(n_vertices * sizeof(LLVector4a));
- if (!mBaseBinormals)
- {
- freeVertexData();
- return false;
- }
- S32 tex_size = (n_vertices * sizeof(LLVector2) + 0xF) & ~0xF;
- mTexCoords = (LLVector2*)allocate_volume_mem(tex_size);
- if (!mTexCoords)
- {
- freeVertexData();
- return false;
- }
- mDetailTexCoords = (LLVector2*)allocate_volume_mem(n_vertices * sizeof(LLVector2));
- if (!mDetailTexCoords)
- {
- freeVertexData();
- return false;
- }
- mWeights = (F32*)allocate_volume_mem(n_vertices * sizeof(F32));
- if (!mWeights)
- {
- freeVertexData();
- return false;
- }
- for (U32 i = 0; i < n_vertices; ++i)
- {
- mBaseCoords[i].clear();
- mBaseNormals[i].clear();
- mBaseBinormals[i].clear();
- mTexCoords[i].clear();
- mWeights[i] = 0.f;
- }
- mNumVertices = n_vertices;
- return true;
- }
- void LLPolyMeshSharedData::freeVertexData()
- {
- mNumVertices = 0;
- if (mBaseCoords)
- {
- free_volume_mem(mBaseCoords);
- mBaseCoords = NULL;
- }
- if (mBaseNormals)
- {
- free_volume_mem(mBaseNormals);
- mBaseNormals = NULL;
- }
- if (mBaseBinormals)
- {
- free_volume_mem(mBaseBinormals);
- mBaseBinormals = NULL;
- }
- if (mTexCoords)
- {
- free_volume_mem(mTexCoords);
- mTexCoords = NULL;
- }
- if (mDetailTexCoords)
- {
- free_volume_mem(mDetailTexCoords);
- mDetailTexCoords = NULL;
- }
- if (mWeights)
- {
- free_volume_mem(mWeights);
- mWeights = NULL;
- }
- }
- bool LLPolyMeshSharedData::allocateFaceData(U32 n_faces)
- {
- mFaces = new LLPolyFace[n_faces];
- if (!mFaces)
- {
- return false;
- }
- mNumFaces = n_faces;
- mNumTriangleIndices = mNumFaces * 3;
- return true;
- }
- bool LLPolyMeshSharedData::allocateJointNames(U32 numJointNames)
- {
- mJointNames = new std::string[numJointNames];
- if (!mJointNames)
- {
- return false;
- }
- mNumJointNames = numJointNames;
- return true;
- }
- bool LLPolyMeshSharedData::loadMesh(const std::string& filename)
- {
- //-------------------------------------------------------------------------
- // Open the file
- //-------------------------------------------------------------------------
- if (filename.empty())
- {
- llwarns << "Filename is Empty !" << llendl;
- llassert(false);
- return false;
- }
- LLFILE* fp = LLFile::open(filename, "rb");
- if (!fp)
- {
- llwarns << "Cannot open: " << filename << llendl;
- llassert(false);
- return false;
- }
- //-------------------------------------------------------------------------
- // Read a chunk
- //-------------------------------------------------------------------------
- char header[128];
- if (fread(header, 1, 128, fp) != 128)
- {
- llwarns << "Short read" << llendl;
- }
- //-------------------------------------------------------------------------
- // Check for proper binary header
- //-------------------------------------------------------------------------
- bool status = false;
- if (strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0)
- {
- LL_DEBUGS("PolyMesh") << "Loading " << filename << LL_ENDL;
- //---------------------------------------------------------------------
- // File Header (seek past it)
- //---------------------------------------------------------------------
- fseek(fp, 24, SEEK_SET);
- //---------------------------------------------------------------------
- // HasWeights
- //---------------------------------------------------------------------
- U8 has_weights;
- size_t num_read = fread(&has_weights, sizeof(U8), 1, fp);
- if (num_read != 1)
- {
- llwarns << "Cannot read HasWeights flag from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- if (!isLOD())
- {
- mHasWeights = has_weights != 0;
- }
- //---------------------------------------------------------------------
- // HasDetailTexCoords
- //---------------------------------------------------------------------
- U8 has_detail_tcoords;
- num_read = fread(&has_detail_tcoords, sizeof(U8), 1, fp);
- if (num_read != 1)
- {
- llwarns << "Cannot read HasDetailTexCoords flag from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- //---------------------------------------------------------------------
- // Position
- //---------------------------------------------------------------------
- LLVector3 position;
- num_read = fread(position.mV, sizeof(float), 3, fp);
- llendianswizzle(position.mV, sizeof(float), 3);
- if (num_read != 3)
- {
- llwarns << "Cannot read Position from " << filename << llendl;
- llassert(false);
- goto abortion;
- }
- setPosition(position);
- //---------------------------------------------------------------------
- // Rotation
- //---------------------------------------------------------------------
- LLVector3 rot_angles;
- num_read = fread(rot_angles.mV, sizeof(float), 3, fp);
- llendianswizzle(rot_angles.mV, sizeof(float), 3);
- if (num_read != 3)
- {
- llwarns << "Cannot read RotationAngles from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- U8 rot_order;
- num_read = fread(&rot_order, sizeof(U8), 1, fp);
- if (num_read != 1)
- {
- llwarns << "Cannot read RotationOrder from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- rot_order = 0;
- setRotation(mayaQ(rot_angles.mV[0], rot_angles.mV[1], rot_angles.mV[2],
- (LLQuaternion::Order)rot_order));
- //---------------------------------------------------------------------
- // Scale
- //---------------------------------------------------------------------
- LLVector3 scale;
- num_read = fread(scale.mV, sizeof(float), 3, fp);
- llendianswizzle(scale.mV, sizeof(float), 3);
- if (num_read != 3)
- {
- llwarns << "Cannot read Scale from " << filename << llendl;
- llassert(false);
- goto abortion;
- }
- setScale(scale);
- //---------------------------------------------------------------------
- // Release any existing mesh geometry
- //---------------------------------------------------------------------
- freeMeshData();
- //---------------------------------------------------------------------
- // NumVertices
- //---------------------------------------------------------------------
- U16 n_vertices = 0;
- if (!isLOD())
- {
- num_read = fread(&n_vertices, sizeof(U16), 1, fp);
- llendianswizzle(&n_vertices, sizeof(U16), 1);
- if (num_read != 1)
- {
- llwarns << "Cannot read NumVertices from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- if (!allocateVertexData(n_vertices))
- {
- llwarns << "Can't allocate vertex data: out of memory ?"
- << llendl;
- llassert(false);
- goto abortion;
- }
- // Coords
- for (U16 i = 0; i < n_vertices; ++i)
- {
- num_read = fread(&mBaseCoords[i], sizeof(float), 3, fp);
- llendianswizzle(&mBaseCoords[i], sizeof(float), 3);
- if (num_read != 3)
- {
- llwarns << "Cannot read Coordinates from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- }
- // Normals
- for (U16 i = 0; i < n_vertices; ++i)
- {
- num_read = fread(&mBaseNormals[i], sizeof(float), 3, fp);
- llendianswizzle(&mBaseNormals[i], sizeof(float), 3);
- if (num_read != 3)
- {
- llwarns << "Cannot read Normals from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- }
- // Binormals
- for (U16 i = 0; i < n_vertices; ++i)
- {
- num_read = fread(&mBaseBinormals[i], sizeof(float), 3, fp);
- llendianswizzle(&mBaseBinormals[i], sizeof(float), 3);
- if (num_read != 3)
- {
- llwarns << "Cannot read Binormals from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- }
- // TexCoords
- num_read = fread(mTexCoords, 2 * sizeof(float), n_vertices, fp);
- llendianswizzle(mTexCoords, sizeof(float), 2 * n_vertices);
- if (num_read != n_vertices)
- {
- llwarns << "Cannot read TexCoords from " << filename << llendl;
- llassert(false);
- goto abortion;
- }
- // DetailTexCoords
- if (mHasDetailTexCoords)
- {
- num_read = fread(mDetailTexCoords, 2 * sizeof(float),
- n_vertices, fp);
- llendianswizzle(mDetailTexCoords, sizeof(float),
- 2 * n_vertices);
- if (num_read != n_vertices)
- {
- llwarns << "Cannot read DetailTexCoords from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- }
- // Weights
- if (mHasWeights)
- {
- num_read = fread(mWeights, sizeof(float), n_vertices, fp);
- llendianswizzle(mWeights, sizeof(float), n_vertices);
- if (num_read != n_vertices)
- {
- llwarns << "Cannot read Weights from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- }
- }
- //---------------------------------------------------------------------
- // NumFaces
- //---------------------------------------------------------------------
- U16 n_faces;
- num_read = fread(&n_faces, sizeof(U16), 1, fp);
- llendianswizzle(&n_faces, sizeof(U16), 1);
- if (num_read != 1)
- {
- llwarns << "Cannot read NumFaces from " << filename << llendl;
- llassert(false);
- goto abortion;
- }
- allocateFaceData(n_faces);
- //---------------------------------------------------------------------
- // Faces
- //---------------------------------------------------------------------
- U32 i;
- U32 n_tris = 0;
- for (i = 0; i < n_faces; ++i)
- {
- S16 face[3];
- num_read = fread(face, sizeof(U16), 3, fp);
- llendianswizzle(face, sizeof(U16), 3);
- if (num_read != 3)
- {
- llwarns << "Cannot read Face[" << i << "] from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- if (mReferenceData)
- {
- llassert(face[0] < mReferenceData->mNumVertices);
- llassert(face[1] < mReferenceData->mNumVertices);
- llassert(face[2] < mReferenceData->mNumVertices);
- }
- if (isLOD())
- {
- // store largest index in case of LODs
- for (S32 j = 0; j < 3; ++j)
- {
- if (face[j] > mNumVertices - 1)
- {
- mNumVertices = face[j] + 1;
- }
- }
- }
- mFaces[i][0] = face[0];
- mFaces[i][1] = face[1];
- mFaces[i][2] = face[2];
- ++n_tris;
- }
- LL_DEBUGS("PolyMesh") << "verts: " << n_vertices << ", faces: "
- << n_faces << ", tris: " << n_tris << LL_ENDL;
- //---------------------------------------------------------------------
- // NumSkinJoints
- //---------------------------------------------------------------------
- if (!isLOD())
- {
- U16 n_skin_joints = 0;
- if (mHasWeights)
- {
- num_read = fread(&n_skin_joints, sizeof(U16), 1, fp);
- llendianswizzle(&n_skin_joints, sizeof(U16), 1);
- if (num_read != 1)
- {
- llwarns << "Cannot read NumSkinJoints from " << filename
- << llendl;
- llassert(false);
- goto abortion;
- }
- allocateJointNames(n_skin_joints);
- }
- //----------------------------------------------------------------
- // SkinJoints
- //----------------------------------------------------------------
- char joint_name[65];
- for (i = 0; i < n_skin_joints; ++i)
- {
- num_read = fread(joint_name, 64, 1, fp);
- joint_name[64] = '\0'; // ensure nul-termination
- if (num_read != 1)
- {
- llwarns << "Cannot read Skin[" << i << "].Name from "
- << filename << llendl;
- llassert(false);
- goto abortion;
- }
- std::string* jn = &mJointNames[i];
- *jn = joint_name;
- }
- //-----------------------------------------------------------------
- // Look for morph section
- //-----------------------------------------------------------------
- char morph_name[65];
- morph_name[64] = '\0'; // Ensure nul-termination
- while (fread(morph_name, 1, 64, fp) == 64)
- {
- if (!strcmp(morph_name, "End Morphs"))
- {
- // We reached the end of the morphs
- break;
- }
- LLPolyMorphData* morph_data = new LLPolyMorphData(morph_name);
- if (!morph_data || !morph_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to allocate new morph data for "
- << morph_name << llendl;
- llassert(false);
- goto abortion;
- }
- if (!morph_data->loadBinary(fp, this))
- {
- delete morph_data;
- continue;
- }
- mMorphData.insert(morph_data);
- LLPolyMorphData* cloned_data;
- if (!strcmp(morph_name, "Breast_Female_Cleavage"))
- {
- cloned_data =
- clone_morph_param_cleavage(morph_data, 0.75f,
- "Breast_Physics_LeftRight_Driven");
- if (!cloned_data || !cloned_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to clone morph data" << llendl;
- llassert(false);
- goto abortion;
- }
- mMorphData.insert(cloned_data);
- cloned_data =
- clone_morph_param_duplicate(morph_data,
- "Breast_Physics_InOut_Driven");
- if (!cloned_data || !cloned_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to clone morph data" << llendl;
- llassert(false);
- goto abortion;
- }
- mMorphData.insert(cloned_data);
- }
- if (!strcmp(morph_name, "Breast_Gravity"))
- {
- cloned_data =
- clone_morph_param_duplicate(morph_data,
- "Breast_Physics_UpDown_Driven");
- if (!cloned_data || !cloned_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to clone morph data" << llendl;
- llassert(false);
- goto abortion;
- }
- mMorphData.insert(cloned_data);
- }
- if (!strcmp(morph_name, "Big_Belly_Torso"))
- {
- cloned_data =
- clone_morph_param_direction(morph_data,
- LLVector3(0, 0, 0.05f),
- "Belly_Physics_Torso_UpDown_Driven");
- if (!cloned_data || !cloned_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to clone morph data" << llendl;
- llassert(false);
- goto abortion;
- }
- mMorphData.insert(cloned_data);
- }
- if (!strcmp(morph_name, "Big_Belly_Legs"))
- {
- cloned_data =
- clone_morph_param_direction(morph_data,
- LLVector3(0, 0, 0.05f),
- "Belly_Physics_Legs_UpDown_Driven");
- if (!cloned_data || !cloned_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to clone morph data" << llendl;
- llassert(false);
- goto abortion;
- }
- mMorphData.insert(cloned_data);
- }
- if (!strcmp(morph_name, "skirt_belly"))
- {
- cloned_data =
- clone_morph_param_direction(morph_data,
- LLVector3(0, 0, 0.05f),
- "Belly_Physics_Skirt_UpDown_Driven");
- if (!cloned_data || !cloned_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to clone morph data" << llendl;
- llassert(false);
- goto abortion;
- }
- mMorphData.insert(cloned_data);
- }
- if (!strcmp(morph_name, "Small_Butt"))
- {
- cloned_data =
- clone_morph_param_direction(morph_data,
- LLVector3(0, 0, 0.05f),
- "Butt_Physics_UpDown_Driven");
- if (!cloned_data || !cloned_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to clone morph data" << llendl;
- llassert(false);
- goto abortion;
- }
- mMorphData.insert(cloned_data);
- cloned_data =
- clone_morph_param_direction(morph_data,
- LLVector3(0, 0.03f, 0),
- "Butt_Physics_LeftRight_Driven");
- if (!cloned_data || !cloned_data->isSuccesfullyAllocated())
- {
- llwarns << "Failure to clone morph data" << llendl;
- llassert(false);
- goto abortion;
- }
- mMorphData.insert(cloned_data);
- }
- }
- S32 n_remaps;
- if (fread(&n_remaps, sizeof(S32), 1, fp) == 1)
- {
- llendianswizzle(&n_remaps, sizeof(S32), 1);
- for (S32 i = 0; i < n_remaps; ++i)
- {
- S32 remap_src;
- S32 remap_dst;
- if (fread(&remap_src, sizeof(S32), 1, fp) != 1)
- {
- llwarns << "Cannot read source vertex in vertex remap data"
- << llendl;
- llassert(false);
- goto abortion;
- }
- if (fread(&remap_dst, sizeof(S32), 1, fp) != 1)
- {
- llwarns << "Cannot read destination vertex in vertex remap data"
- << llendl;
- llassert(false);
- goto abortion;
- }
- llendianswizzle(&remap_src, sizeof(S32), 1);
- llendianswizzle(&remap_dst, sizeof(S32), 1);
- mSharedVerts[remap_src] = remap_dst;
- }
- }
- }
- status = true;
- }
- else
- {
- llwarns << "Invalid mesh file header: " << filename << llendl;
- }
- if (mNumJointNames == 0)
- {
- allocateJointNames(1);
- }
- abortion:
- LLFile::close(fp);
- return status;
- }
- const S32* LLPolyMeshSharedData::getSharedVert(S32 vert)
- {
- if (mSharedVerts.count(vert) > 0)
- {
- return &mSharedVerts[vert];
- }
- return NULL;
- }
- const LLVector2 &LLPolyMeshSharedData::getUVs(U32 index)
- {
- // TODO: convert all index variables to S32
- llassert((S32)index < mNumVertices);
- return mTexCoords[index];
- }
- //-----------------------------------------------------------------------------
- // LLPolyMesh class
- //-----------------------------------------------------------------------------
- LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData* shared_data,
- LLPolyMesh* reference_mesh)
- {
- llassert(shared_data);
- mSharedData = shared_data;
- mReferenceMesh = reference_mesh;
- mAvatarp = NULL;
- mVertexData = NULL;
- mCurVertexCount = 0;
- mFaceIndexCount = 0;
- mFaceIndexOffset = 0;
- mFaceVertexCount = 0;
- mFaceVertexOffset = 0;
- if (shared_data->isLOD() && reference_mesh)
- {
- mCoords = reference_mesh->mCoords;
- mNormals = reference_mesh->mNormals;
- mScaledNormals = reference_mesh->mScaledNormals;
- mBinormals = reference_mesh->mBinormals;
- mScaledBinormals = reference_mesh->mScaledBinormals;
- mTexCoords = reference_mesh->mTexCoords;
- mClothingWeights = reference_mesh->mClothingWeights;
- }
- else
- {
- // Allocate memory without initializing every vector
- // NOTE: This makes assumptions about the size of LLVector[234]
- S32 nverts = mSharedData->mNumVertices;
- // make sure it's an even number of verts for alignment
- nverts += nverts % 2;
- S32 nfloats = nverts * (4 + //coords
- 4 + //normals
- 4 + //weights
- 2 + //coords
- 4 + //scaled normals
- 4 + //binormals
- 4); //scaled binormals
- // use 16 byte aligned vertex data to make LLPolyMesh SSE friendly
- mVertexData = (F32*)allocate_volume_mem(nfloats * 4);
- if (!mVertexData)
- {
- llwarns << "Failure to allocate vertex data buffer !" << llendl;
- mCoords = mNormals = mClothingWeights = mScaledNormals =
- mBinormals = mScaledBinormals = NULL;
- mTexCoords = NULL;
- return;
- }
- S32 offset = 0;
- mCoords = (LLVector4a*)(mVertexData + offset); offset += 4 * nverts;
- mNormals = (LLVector4a*)(mVertexData + offset); offset += 4 * nverts;
- mClothingWeights = (LLVector4a*)(mVertexData + offset); offset += 4 * nverts;
- mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2 * nverts;
- mScaledNormals = (LLVector4a*)(mVertexData + offset); offset += 4 * nverts;
- mBinormals = (LLVector4a*)(mVertexData + offset); offset += 4 * nverts;
- mScaledBinormals = (LLVector4a*)(mVertexData + offset); offset += 4 * nverts;
- initializeForMorph();
- }
- }
- LLPolyMesh::~LLPolyMesh()
- {
- delete_and_clear(mJointRenderData);
- if (mVertexData)
- {
- free_volume_mem(mVertexData);
- mVertexData = NULL;
- }
- }
- LLPolyMesh* LLPolyMesh::getMesh(const std::string& name,
- LLPolyMesh* reference_mesh)
- {
- //-------------------------------------------------------------------------
- // Search for an existing mesh by this name
- //-------------------------------------------------------------------------
- LLPolyMeshSharedData* meshSharedData = get_ptr_in_map(sGlobalSharedMeshList,
- name);
- if (meshSharedData)
- {
- LL_DEBUGS("PolyMesh") << "Polymesh " << name
- << " found in global mesh table." << LL_ENDL;
- LLPolyMesh* poly_mesh = new LLPolyMesh(meshSharedData, reference_mesh);
- return poly_mesh;
- }
- //-------------------------------------------------------------------------
- // If not found, create a new one, add it to the list
- //-------------------------------------------------------------------------
- std::string full_path = gDirUtil.getFullPath(LL_PATH_CHARACTER, name);
- LLPolyMeshSharedData* mesh_data = new LLPolyMeshSharedData();
- if (reference_mesh)
- {
- mesh_data->setupLOD(reference_mesh->getSharedData());
- }
- if (!mesh_data->loadMesh(full_path))
- {
- delete mesh_data;
- return NULL;
- }
- LLPolyMesh* poly_mesh = new LLPolyMesh(mesh_data, reference_mesh);
- LL_DEBUGS("PolyMesh") << "Polymesh " << name
- << " added to global mesh table." << LL_ENDL;
- sGlobalSharedMeshList[name] = poly_mesh->mSharedData;
- return poly_mesh;
- }
- void LLPolyMesh::freeAllMeshes()
- {
- // Delete each item in the global lists
- for_each(sGlobalSharedMeshList.begin(), sGlobalSharedMeshList.end(),
- DeletePairedPointer());
- sGlobalSharedMeshList.clear();
- }
- void LLPolyMesh::dumpDiagInfo()
- {
- // keep track of totals
- U32 total_verts = 0;
- U32 total_faces = 0;
- U32 total_kb = 0;
- std::string buf;
- llinfos << "-----------------------------------------------------"
- << llendl;
- llinfos << " Global PolyMesh Table (DEBUG only)" << llendl;
- llinfos << " Verts Faces Mem(KB) Name" << llendl;
- llinfos << "-----------------------------------------------------"
- << llendl;
- // print each loaded mesh, and it's memory usage
- for (LLPolyMeshSharedDataTable::iterator iter = sGlobalSharedMeshList.begin();
- iter != sGlobalSharedMeshList.end(); ++iter)
- {
- const std::string& mesh_name = iter->first;
- LLPolyMeshSharedData* mesh = iter->second;
- S32 num_verts = mesh->mNumVertices;
- S32 num_faces = mesh->mNumFaces;
- U32 num_kb = mesh->getNumKB();
- buf = llformat("%8d %8d %8d %s", num_verts, num_faces, num_kb,
- mesh_name.c_str());
- llinfos << buf << llendl;
- total_verts += num_verts;
- total_faces += num_faces;
- total_kb += num_kb;
- }
- llinfos << "-----------------------------------------------------"
- << llendl;
- buf = llformat("%8d %8d %8d TOTAL", total_verts, total_faces, total_kb);
- llinfos << buf << llendl;
- llinfos << "-----------------------------------------------------"
- << llendl;
- }
- void LLPolyMesh::initializeForMorph()
- {
- S32 num_vertices = mSharedData->mNumVertices;
- LLVector4a::memcpyNonAliased16((F32*)mCoords,
- (F32*)mSharedData->mBaseCoords,
- sizeof(LLVector4a) * num_vertices);
- LLVector4a::memcpyNonAliased16((F32*)mNormals,
- (F32*)mSharedData->mBaseNormals,
- sizeof(LLVector4a) * num_vertices);
- LLVector4a::memcpyNonAliased16((F32*)mScaledNormals,
- (F32*)mSharedData->mBaseNormals,
- sizeof(LLVector4a) * num_vertices);
- LLVector4a::memcpyNonAliased16((F32*)mBinormals,
- (F32*)mSharedData->mBaseNormals,
- sizeof(LLVector4a) * num_vertices);
- LLVector4a::memcpyNonAliased16((F32*)mScaledBinormals,
- (F32*)mSharedData->mBaseNormals,
- sizeof(LLVector4a) * num_vertices);
- LLVector4a::memcpyNonAliased16((F32*)mTexCoords,
- (F32*)mSharedData->mTexCoords,
- sizeof(LLVector2) *
- (num_vertices + num_vertices % 2));
- for (S32 i = 0; i < num_vertices; ++i)
- {
- mClothingWeights[i].clear();
- }
- }
- LLPolyMorphData* LLPolyMesh::getMorphData(const std::string& morph_name)
- {
- if (mSharedData)
- {
- for (LLPolyMeshSharedData::morphdata_list_t::iterator
- iter = mSharedData->mMorphData.begin(),
- end = mSharedData->mMorphData.end();
- iter != end; ++iter)
- {
- LLPolyMorphData* morph_data = *iter;
- if (morph_data->getName() == morph_name)
- {
- return morph_data;
- }
- }
- }
- return NULL;
- }
- #if 0
- // Erasing but not deleting seems bad, but fortunately we do not actually use
- // this...
- void LLPolyMesh::removeMorphData(LLPolyMorphData* morph_target)
- {
- if (mSharedData)
- {
- mSharedData->mMorphData.erase(morph_target);
- }
- }
- void LLPolyMesh::deleteAllMorphData()
- {
- if (mSharedData)
- {
- for_each(mSharedData->mMorphData.begin(),
- mSharedData->mMorphData.end(), DeletePointer());
- mSharedData->mMorphData.clear();
- }
- }
- #endif
|