bool less_than_max_mag(const LLVector4a& vec) { LLVector4a MAX_MAG; MAX_MAG.splat(1024.f*1024.f); LLVector4a val; val.setAbs(vec); S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; return lt == 0x7; }
//----------------------------------------------------------------------------- // 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; }
void LLSpatialBridge::updateSpatialExtents() { LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0); { LLFastTimer ftm(FTM_CULL_REBOUND); root->rebound(); } LLVector4a offset; LLVector4a size = root->mBounds[1]; //VECTORIZE THIS LLMatrix4a mat; mat.loadu(mDrawable->getXform()->getWorldMatrix()); LLVector4a t; t.splat(0.f); LLVector4a center; mat.affineTransform(t, center); mat.rotate(root->mBounds[0], offset); center.add(offset); LLVector4a v[4]; //get 4 corners of bounding box mat.rotate(size,v[0]); LLVector4a scale; scale.set(-1.f, -1.f, 1.f); scale.mul(size); mat.rotate(scale, v[1]); scale.set(1.f, -1.f, -1.f); scale.mul(size); mat.rotate(scale, v[2]); scale.set(-1.f, 1.f, -1.f); scale.mul(size); mat.rotate(scale, v[3]); LLVector4a& newMin = mExtents[0]; LLVector4a& newMax = mExtents[1]; newMin = newMax = center; for (U32 i = 0; i < 4; i++) { LLVector4a delta; delta.setAbs(v[i]); LLVector4a min; min.setSub(center, delta); LLVector4a max; max.setAdd(center, delta); newMin.setMin(newMin, min); newMax.setMax(newMax, max); } LLVector4a diagonal; diagonal.setSub(newMax, newMin); mRadius = diagonal.getLength3().getF32() * 0.5f; mPositionGroup.setAdd(newMin,newMax); mPositionGroup.mul(0.5f); updateBinRadius(); }
//----------------------------------------------------------------------------- // setMorphFromMesh() //----------------------------------------------------------------------------- BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) { if (!morph) return FALSE; LLVector4a *morph_coords = morph->getWritableCoords(); LLVector4a *morph_normals = morph->getWritableNormals(); LLVector4a *morph_binormals = morph->getWritableBinormals(); LLVector2 *morph_tex_coords = morph->getWritableTexCoords(); // We now have the morph loaded as a mesh. We have to subtract the // base mesh to get the delta morph. LLPolyMesh delta(mMesh, NULL); U32 nverts = delta.getNumVertices(); LLVector4a *delta_coords = delta.getWritableCoords(); LLVector4a *delta_normals = delta.getWritableNormals(); LLVector4a *delta_binormals = delta.getWritableBinormals(); LLVector2 *delta_tex_coords = delta.getWritableTexCoords(); U32 num_significant = 0; U32 vert_index; for( vert_index = 0; vert_index < nverts; vert_index++) { delta_coords[vert_index].setSub( morph_coords[vert_index], delta_coords[vert_index]); delta_normals[vert_index].setSub( morph_normals[vert_index], delta_normals[vert_index]); delta_binormals[vert_index].setSub( morph_binormals[vert_index], delta_binormals[vert_index]); delta_tex_coords[vert_index] = morph_tex_coords[vert_index] - delta_tex_coords[vert_index]; // For the normals and binormals, we really want the deltas // to be perpendicular to the mesh (bi)normals in the plane // that contains both the mesh and morph (bi)normals, such // that the morph (bi)normals form the hypotenuses of right // triangles. Right now, we just compute the difference vector. if (delta_coords[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA || delta_normals[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA || delta_binormals[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA || delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA) { num_significant++; } } //------------------------------------------------------------------------- // compute new morph //------------------------------------------------------------------------- // If the morph matches the base mesh, we store one vertex to prevent // zero length vectors. U32 nindices = num_significant; if (num_significant == 0) nindices = 1; LLVector4a* new_coords = new LLVector4a[nindices]; LLVector4a* new_normals = new LLVector4a[nindices]; LLVector4a* new_binormals = new LLVector4a[nindices]; LLVector2* new_tex_coords = new LLVector2[nindices]; U32* new_vertex_indices = new U32[nindices]; // We'll set the distortion directly mTotalDistortion = 0.f; mMaxDistortion = 0.f; mAvgDistortion.clear(); U32 morph_index = 0; for( vert_index = 0; vert_index < nverts; vert_index++) { if (delta_coords[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA || delta_normals[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA || delta_binormals[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA || delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA || num_significant == 0) { new_vertex_indices[morph_index] = vert_index; new_coords[morph_index] = delta_coords[vert_index]; new_normals[morph_index] = delta_normals[vert_index]; new_binormals[morph_index] = delta_binormals[vert_index]; new_tex_coords[morph_index] = delta_tex_coords[vert_index]; F32 magnitude = new_coords[morph_index].getLength3().getF32(); mTotalDistortion += magnitude; LLVector4a t; t.setAbs(new_coords[morph_index]); mAvgDistortion.add(t); if (magnitude > mMaxDistortion) { mMaxDistortion = magnitude; } morph_index++; num_significant = 1; } } mAvgDistortion.mul(1.f/(F32)nindices); mAvgDistortion.normalize3(); //------------------------------------------------------------------------- // compute the change in the morph //------------------------------------------------------------------------- // Because meshes are set by continually updating morph weights // there is no easy way to reapply the morphs, so we just compute // the change in this morph and apply that appropriately weighted. for( morph_index = 0; morph_index < mNumIndices; morph_index++) { vert_index = mVertexIndices[morph_index]; delta_coords[vert_index].sub( mCoords[morph_index]); delta_normals[vert_index].sub( mNormals[morph_index]); delta_binormals[vert_index].sub(mBinormals[morph_index]); delta_tex_coords[vert_index] -= mTexCoords[morph_index]; } //------------------------------------------------------------------------- // Update all avatars //------------------------------------------------------------------------- std::vector< LLCharacter* >::iterator avatar_it; for(avatar_it = LLCharacter::sInstances.begin(); avatar_it != LLCharacter::sInstances.end(); ++avatar_it) { LLVOAvatar* avatarp = (LLVOAvatar*)*avatar_it; LLPolyMorphTarget* param = (LLPolyMorphTarget*) avatarp->getVisualParam(mName.c_str()); if (!param) { continue; } F32 weight = param->getLastWeight(); if (weight == 0.0f) { continue; } LLPolyMesh* mesh = avatarp->getMesh(mMesh); if (!mesh) { continue; } // If we have a vertex mask, just remove it. It will be recreated. /*if (param->undoMask(TRUE)) { continue; }*/ LLVector4a *mesh_coords = mesh->getWritableCoords(); LLVector4a *mesh_normals = mesh->getWritableNormals(); LLVector4a *mesh_binormals = mesh->getWritableBinormals(); LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); LLVector4a *mesh_scaled_normals = mesh->getScaledNormals(); LLVector4a *mesh_scaled_binormals = mesh->getScaledBinormals(); for( vert_index = 0; vert_index < nverts; vert_index++) { delta_coords[vert_index].mul(weight); mesh_coords[vert_index].add(delta_coords[vert_index]); mesh_tex_coords[vert_index] += delta_tex_coords[vert_index] * weight; delta_normals[vert_index].mul(weight * NORMAL_SOFTEN_FACTOR); mesh_scaled_normals[vert_index].add(delta_normals[vert_index]); LLVector4a normalized_normal = mesh_scaled_normals[vert_index]; normalized_normal.normalize3(); mesh_normals[vert_index] = normalized_normal; delta_binormals[vert_index].mul(weight * NORMAL_SOFTEN_FACTOR); mesh_scaled_binormals[vert_index].add(delta_binormals[vert_index]); LLVector4a tangent; tangent.setCross3(mesh_scaled_binormals[vert_index], normalized_normal); LLVector4a normalized_binormal; normalized_binormal.setCross3(normalized_normal, tangent); normalized_binormal.normalize3(); mesh_binormals[vert_index] = normalized_binormal; } avatarp->dirtyMesh(); } //------------------------------------------------------------------------- // reallocate vertices //------------------------------------------------------------------------- delete [] mVertexIndices; delete [] mCoords; delete [] mNormals; delete [] mBinormals; delete [] mTexCoords; mVertexIndices = new_vertex_indices; mCoords = new_coords; mNormals = new_normals; mBinormals = new_binormals; mTexCoords = new_tex_coords; mNumIndices = nindices; return TRUE; }
BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); //get bounding box if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION #if MESH_ENABLED | LLDrawable::REBUILD_RIGGED #endif //MESH_ENABLED )) { //VECTORIZE THIS LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); LLMatrix4a mat_normal; mat_normal.loadu(mat_normal_in); //if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) //{ //vertex buffer no longer valid // mVertexBuffer = NULL; // mLastVertexBuffer = NULL; //} //VECTORIZE THIS LLVector4a min,max; if (f >= volume.getNumVolumeFaces()) { llwarns << "Generating bounding box for invalid face index!" << llendl; f = 0; } const LLVolumeFace &face = volume.getVolumeFace(f); min = face.mExtents[0]; max = face.mExtents[1]; llassert(less_than_max_mag(min)); llassert(less_than_max_mag(max)); //min, max are in volume space, convert to drawable render space LLVector4a center; LLVector4a t; t.setAdd(min, max); t.mul(0.5f); mat_vert.affineTransform(t, center); LLVector4a size; size.setSub(max, min); size.mul(0.5f); llassert(less_than_max_mag(min)); llassert(less_than_max_mag(max)); if (!global_volume) { //VECTORIZE THIS LLVector4a scale; scale.load3(mDrawablep->getVObj()->getScale().mV); size.mul(scale); } mat_normal.mMatrix[0].normalize3fast(); mat_normal.mMatrix[1].normalize3fast(); mat_normal.mMatrix[2].normalize3fast(); LLVector4a v[4]; //get 4 corners of bounding box mat_normal.rotate(size,v[0]); //VECTORIZE THIS LLVector4a scale; scale.set(-1.f, -1.f, 1.f); scale.mul(size); mat_normal.rotate(scale, v[1]); scale.set(1.f, -1.f, -1.f); scale.mul(size); mat_normal.rotate(scale, v[2]); scale.set(-1.f, 1.f, -1.f); scale.mul(size); mat_normal.rotate(scale, v[3]); LLVector4a& newMin = mExtents[0]; LLVector4a& newMax = mExtents[1]; newMin = newMax = center; llassert(less_than_max_mag(center)); for (U32 i = 0; i < 4; i++) { LLVector4a delta; delta.setAbs(v[i]); LLVector4a min; min.setSub(center, delta); LLVector4a max; max.setAdd(center, delta); newMin.setMin(newMin,min); newMax.setMax(newMax,max); llassert(less_than_max_mag(newMin)); llassert(less_than_max_mag(newMax)); } if (!mDrawablep->isActive()) { LLVector4a offset; offset.load3(mDrawablep->getRegion()->getOriginAgent().mV); newMin.add(offset); newMax.add(offset); llassert(less_than_max_mag(newMin)); llassert(less_than_max_mag(newMax)); } t.setAdd(newMin, newMax); t.mul(0.5f); llassert(less_than_max_mag(t)); //VECTORIZE THIS mCenterLocal.set(t.getF32ptr()); llassert(less_than_max_mag(newMin)); llassert(less_than_max_mag(newMax)); t.setSub(newMax,newMin); mBoundingSphereRadius = t.getLength3().getF32()*0.5f; updateCenterAgent(); } return TRUE; }