//----------------------------------------------------------------------------- // 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<LLVector4a*>(ll_aligned_malloc_16(size)); mNormals = static_cast<LLVector4a*>(ll_aligned_malloc_16(size)); mBinormals = static_cast<LLVector4a*>(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) { LL_ERRS() << "Bad morph index: " << mVertexIndices[v] << LL_ENDL; } 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; }
//----------------------------------------------------------------------------- // LLPolyMesh::saveLLM() //----------------------------------------------------------------------------- BOOL LLPolyMorphData::saveLLM(LLFILE *fp) { if (!fp) return FALSE; S32 numVertices = mNumIndices; llendianswizzle(&numVertices, sizeof(S32), 1); if (fwrite(&numVertices, sizeof(S32), 1, fp) != 1) { llwarns << "Short write" << llendl; } numVertices = mNumIndices; // without the swizzle again //------------------------------------------------------------------------- // write vertices //------------------------------------------------------------------------- for(S32 v = 0; v < numVertices; v++) { llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); if (fwrite(&mVertexIndices[v], sizeof(U32), 1, fp) != 1) { llwarns << "Short write" << llendl; } llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); llendianswizzle(mCoords[v].getF32ptr(), sizeof(F32), 3); if (fwrite(mCoords[v].getF32ptr(), sizeof(F32), 3, fp) != 3) { llwarns << "Short write" << llendl; } llendianswizzle(mCoords[v].getF32ptr(), sizeof(F32), 3); llendianswizzle(mNormals[v].getF32ptr(), sizeof(F32), 3); if (fwrite(mNormals[v].getF32ptr(), sizeof(F32), 3, fp) != 3) { llwarns << "Short write" << llendl; } llendianswizzle(mNormals[v].getF32ptr(), sizeof(F32), 3); llendianswizzle(mBinormals[v].getF32ptr(), sizeof(F32), 3); if (fwrite(mBinormals[v].getF32ptr(), sizeof(F32), 3, fp) != 3) { llwarns << "Short write" << llendl; } llendianswizzle(mBinormals[v].getF32ptr(), sizeof(F32), 3); llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); if (fwrite(&mTexCoords[v].mV, sizeof(F32), 2, fp) != 2) { llwarns << "Short write" << llendl; } llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); } return TRUE; }
//----------------------------------------------------------------------------- // 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) { llwarns << "Can't read number of morph target vertices" << llendl; return FALSE; } //------------------------------------------------------------------------- // allocate vertices //------------------------------------------------------------------------- mCoords = new LLVector3[numVertices]; mNormals = new LLVector3[numVertices]; mBinormals = new LLVector3[numVertices]; 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.zeroVec(); 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) { llwarns << "Can't read morph target vertex number" << llendl; return FALSE; } if (mVertexIndices[v] > 10000) { llerrs << "Bad morph index: " << mVertexIndices[v] << llendl; } numRead = fread(&mCoords[v].mV, sizeof(F32), 3, fp); llendianswizzle(&mCoords[v].mV, sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target vertex coordinates" << llendl; return FALSE; } F32 magnitude = mCoords[v].magVec(); mTotalDistortion += magnitude; mAvgDistortion.mV[VX] += fabs(mCoords[v].mV[VX]); mAvgDistortion.mV[VY] += fabs(mCoords[v].mV[VY]); mAvgDistortion.mV[VZ] += fabs(mCoords[v].mV[VZ]); if (magnitude > mMaxDistortion) { mMaxDistortion = magnitude; } numRead = fread(&mNormals[v].mV, sizeof(F32), 3, fp); llendianswizzle(&mNormals[v].mV, sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target normal" << llendl; return FALSE; } numRead = fread(&mBinormals[v].mV, sizeof(F32), 3, fp); llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target binormal" << llendl; return FALSE; } numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp); llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); if (numRead != 2) { llwarns << "Can't read morph target uv" << llendl; return FALSE; } mNumIndices++; } mAvgDistortion = mAvgDistortion * (1.f/(F32)mNumIndices); mAvgDistortion.normVec(); return TRUE; }
//-------------------------------------------------------------------- // LLPolyMeshSharedData::loadMesh() //-------------------------------------------------------------------- BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) { //------------------------------------------------------------------------- // Open the file //------------------------------------------------------------------------- if(fileName.empty()) { LL_ERRS() << "Filename is Empty!" << LL_ENDL; return FALSE; } LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ if (!fp) { LL_ERRS() << "can't open: " << fileName << LL_ENDL; return FALSE; } //------------------------------------------------------------------------- // Read a chunk //------------------------------------------------------------------------- char header[128]; /*Flawfinder: ignore*/ if (fread(header, sizeof(char), 128, fp) != 128) { LL_WARNS() << "Short read" << LL_ENDL; } //------------------------------------------------------------------------- // Check for proper binary header //------------------------------------------------------------------------- BOOL status = FALSE; if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) /*Flawfinder: ignore*/ { LL_DEBUGS() << "Loading " << fileName << LL_ENDL; //---------------------------------------------------------------- // File Header (seek past it) //---------------------------------------------------------------- fseek(fp, 24, SEEK_SET); //---------------------------------------------------------------- // HasWeights //---------------------------------------------------------------- U8 hasWeights; size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp); if (numRead != 1) { LL_ERRS() << "can't read HasWeights flag from " << fileName << LL_ENDL; return FALSE; } if (!isLOD()) { mHasWeights = (hasWeights==0) ? FALSE : TRUE; } //---------------------------------------------------------------- // HasDetailTexCoords //---------------------------------------------------------------- U8 hasDetailTexCoords; numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp); if (numRead != 1) { LL_ERRS() << "can't read HasDetailTexCoords flag from " << fileName << LL_ENDL; return FALSE; } //---------------------------------------------------------------- // Position //---------------------------------------------------------------- LLVector3 position; numRead = fread(position.mV, sizeof(float), 3, fp); llendianswizzle(position.mV, sizeof(float), 3); if (numRead != 3) { LL_ERRS() << "can't read Position from " << fileName << LL_ENDL; return FALSE; } setPosition( position ); //---------------------------------------------------------------- // Rotation //---------------------------------------------------------------- LLVector3 rotationAngles; numRead = fread(rotationAngles.mV, sizeof(float), 3, fp); llendianswizzle(rotationAngles.mV, sizeof(float), 3); if (numRead != 3) { LL_ERRS() << "can't read RotationAngles from " << fileName << LL_ENDL; return FALSE; } U8 rotationOrder; numRead = fread(&rotationOrder, sizeof(U8), 1, fp); if (numRead != 1) { LL_ERRS() << "can't read RotationOrder from " << fileName << LL_ENDL; return FALSE; } rotationOrder = 0; setRotation( mayaQ( rotationAngles.mV[0], rotationAngles.mV[1], rotationAngles.mV[2], (LLQuaternion::Order)rotationOrder ) ); //---------------------------------------------------------------- // Scale //---------------------------------------------------------------- LLVector3 scale; numRead = fread(scale.mV, sizeof(float), 3, fp); llendianswizzle(scale.mV, sizeof(float), 3); if (numRead != 3) { LL_ERRS() << "can't read Scale from " << fileName << LL_ENDL; return FALSE; } setScale( scale ); //------------------------------------------------------------------------- // Release any existing mesh geometry //------------------------------------------------------------------------- freeMeshData(); U16 numVertices = 0; //---------------------------------------------------------------- // NumVertices //---------------------------------------------------------------- if (!isLOD()) { numRead = fread(&numVertices, sizeof(U16), 1, fp); llendianswizzle(&numVertices, sizeof(U16), 1); if (numRead != 1) { LL_ERRS() << "can't read NumVertices from " << fileName << LL_ENDL; return FALSE; } allocateVertexData( numVertices ); for (U16 i = 0; i < numVertices; ++i) { //---------------------------------------------------------------- // Coords //---------------------------------------------------------------- numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); llendianswizzle(&mBaseCoords[i], sizeof(float), 3); if (numRead != 3) { LL_ERRS() << "can't read Coordinates from " << fileName << LL_ENDL; return FALSE; } } for (U16 i = 0; i < numVertices; ++i) { //---------------------------------------------------------------- // Normals //---------------------------------------------------------------- numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); llendianswizzle(&mBaseNormals[i], sizeof(float), 3); if (numRead != 3) { LL_ERRS() << " can't read Normals from " << fileName << LL_ENDL; return FALSE; } } for (U16 i = 0; i < numVertices; ++i) { //---------------------------------------------------------------- // Binormals //---------------------------------------------------------------- numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); if (numRead != 3) { LL_ERRS() << " can't read Binormals from " << fileName << LL_ENDL; return FALSE; } } //---------------------------------------------------------------- // TexCoords //---------------------------------------------------------------- numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp); llendianswizzle(mTexCoords, sizeof(float), 2*numVertices); if (numRead != numVertices) { LL_ERRS() << "can't read TexCoords from " << fileName << LL_ENDL; return FALSE; } //---------------------------------------------------------------- // DetailTexCoords //---------------------------------------------------------------- if (mHasDetailTexCoords) { numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp); llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices); if (numRead != numVertices) { LL_ERRS() << "can't read DetailTexCoords from " << fileName << LL_ENDL; return FALSE; } } //---------------------------------------------------------------- // Weights //---------------------------------------------------------------- if (mHasWeights) { numRead = fread(mWeights, sizeof(float), numVertices, fp); llendianswizzle(mWeights, sizeof(float), numVertices); if (numRead != numVertices) { LL_ERRS() << "can't read Weights from " << fileName << LL_ENDL; return FALSE; } } } //---------------------------------------------------------------- // NumFaces //---------------------------------------------------------------- U16 numFaces; numRead = fread(&numFaces, sizeof(U16), 1, fp); llendianswizzle(&numFaces, sizeof(U16), 1); if (numRead != 1) { LL_ERRS() << "can't read NumFaces from " << fileName << LL_ENDL; return FALSE; } allocateFaceData( numFaces ); //---------------------------------------------------------------- // Faces //---------------------------------------------------------------- U32 i; U32 numTris = 0; for (i = 0; i < numFaces; i++) { S16 face[3]; numRead = fread(face, sizeof(U16), 3, fp); llendianswizzle(face, sizeof(U16), 3); if (numRead != 3) { LL_ERRS() << "can't read Face[" << i << "] from " << fileName << LL_ENDL; return FALSE; } 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]; // S32 j; // for(j = 0; j < 3; j++) // { // std::vector<S32> *face_list = mVertFaceMap.getIfThere(face[j]); // if (!face_list) // { // face_list = new std::vector<S32>; // mVertFaceMap.addData(face[j], face_list); // } // face_list->put(i); // } numTris++; } LL_DEBUGS() << "verts: " << numVertices << ", faces: " << numFaces << ", tris: " << numTris << LL_ENDL; //---------------------------------------------------------------- // NumSkinJoints //---------------------------------------------------------------- if (!isLOD()) { U16 numSkinJoints = 0; if ( mHasWeights ) { numRead = fread(&numSkinJoints, sizeof(U16), 1, fp); llendianswizzle(&numSkinJoints, sizeof(U16), 1); if (numRead != 1) { LL_ERRS() << "can't read NumSkinJoints from " << fileName << LL_ENDL; return FALSE; } allocateJointNames( numSkinJoints ); } //---------------------------------------------------------------- // SkinJoints //---------------------------------------------------------------- for (i=0; i < numSkinJoints; i++) { char jointName[64+1]; numRead = fread(jointName, sizeof(jointName)-1, 1, fp); jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination if (numRead != 1) { LL_ERRS() << "can't read Skin[" << i << "].Name from " << fileName << LL_ENDL; return FALSE; } std::string *jn = &mJointNames[i]; *jn = jointName; } //------------------------------------------------------------------------- // look for morph section //------------------------------------------------------------------------- char morphName[64+1]; morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination while(fread(&morphName, sizeof(char), 64, fp) == 64) { if (!strcmp(morphName, "End Morphs")) { // we reached the end of the morphs break; } LLPolyMorphData* morph_data = new LLPolyMorphData(std::string(morphName)); BOOL result = morph_data->loadBinary(fp, this); if (!result) { delete morph_data; continue; } mMorphData.insert(morph_data); if (!strcmp(morphName, "Breast_Female_Cleavage")) { mMorphData.insert(clone_morph_param_cleavage(morph_data, .75f, "Breast_Physics_LeftRight_Driven")); } if (!strcmp(morphName, "Breast_Female_Cleavage")) { mMorphData.insert(clone_morph_param_duplicate(morph_data, "Breast_Physics_InOut_Driven")); } if (!strcmp(morphName, "Breast_Gravity")) { mMorphData.insert(clone_morph_param_duplicate(morph_data, "Breast_Physics_UpDown_Driven")); } if (!strcmp(morphName, "Big_Belly_Torso")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Belly_Physics_Torso_UpDown_Driven")); } if (!strcmp(morphName, "Big_Belly_Legs")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Belly_Physics_Legs_UpDown_Driven")); } if (!strcmp(morphName, "skirt_belly")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Belly_Physics_Skirt_UpDown_Driven")); } if (!strcmp(morphName, "Small_Butt")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Butt_Physics_UpDown_Driven")); } if (!strcmp(morphName, "Small_Butt")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0.03f,0), "Butt_Physics_LeftRight_Driven")); } } S32 numRemaps; if (fread(&numRemaps, sizeof(S32), 1, fp) == 1) { llendianswizzle(&numRemaps, sizeof(S32), 1); for (S32 i = 0; i < numRemaps; i++) { S32 remapSrc; S32 remapDst; if (fread(&remapSrc, sizeof(S32), 1, fp) != 1) { LL_ERRS() << "can't read source vertex in vertex remap data" << LL_ENDL; break; } if (fread(&remapDst, sizeof(S32), 1, fp) != 1) { LL_ERRS() << "can't read destination vertex in vertex remap data" << LL_ENDL; break; } llendianswizzle(&remapSrc, sizeof(S32), 1); llendianswizzle(&remapDst, sizeof(S32), 1); mSharedVerts[remapSrc] = remapDst; } } } status = TRUE; } else { LL_ERRS() << "invalid mesh file header: " << fileName << LL_ENDL; status = FALSE; } if (0 == mNumJointNames) { allocateJointNames(1); } fclose( fp ); return status; }