void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { const LLVector3& pos_agent = getPositionAgent(); LLVector4a scale; LLVector4a p; p.load3(pos_agent.mV); scale.splat(mScale.mV[0]+mViewerPartGroupp->getBoxSide()*0.5f); newMin.setSub(p, scale); newMax.setAdd(p,scale); llassert(newMin.isFinite3()); llassert(newMax.isFinite3()); llassert(p.isFinite3()); mDrawable->setPositionGroup(p); }
LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) { LLCamera ret = camera; LLXformMatrix* mat = mDrawable->getXform(); const LLVector4a& center = mat->getWorldMatrix().getRow<3>(); LLQuaternion2 invRot; invRot.setConjugate( LLQuaternion2(mat->getRotation()) ); LLVector4a delta; delta.load3(ret.getOrigin().mV); delta.sub(center); LLVector4a lookAt; lookAt.load3(ret.getAtAxis().mV); LLVector4a up_axis; up_axis.load3(ret.getUpAxis().mV); LLVector4a left_axis; left_axis.load3(ret.getLeftAxis().mV); delta.setRotated(invRot, delta); lookAt.setRotated(invRot, lookAt); up_axis.setRotated(invRot, up_axis); left_axis.setRotated(invRot, left_axis); if (!delta.isFinite3()) { delta.clear(); } ret.setOrigin(LLVector3(delta.getF32ptr())); ret.setAxes(LLVector3(lookAt.getF32ptr()), LLVector3(left_axis.getF32ptr()), LLVector3(up_axis.getF32ptr())); return ret; }
void LLPolyMorphTarget::apply( ESex avatar_sex ) { if (!mMorphData || mNumMorphMasksPending > 0) { return; } LL_RECORD_BLOCK_TIME(FTM_APPLY_MORPH_TARGET); mLastSex = avatar_sex; // Check for NaN condition (NaN is detected if a variable doesn't equal itself. if (mCurWeight != mCurWeight) { mCurWeight = 0.0; } if (mLastWeight != mLastWeight) { mLastWeight = mCurWeight+.001; } // perform differential update of morph F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight); // store last weight mLastWeight += delta_weight; if (delta_weight != 0.f) { llassert(!mMesh->isLOD()); LLVector4a *coords = mMesh->getWritableCoords(); LLVector4a *scaled_normals = mMesh->getScaledNormals(); LLVector4a *normals = mMesh->getWritableNormals(); LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); LLVector4a *binormals = mMesh->getWritableBinormals(); LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); LLVector2 *tex_coords = mMesh->getWritableTexCoords(); F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++) { S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph]; F32 maskWeight = 1.f; if (maskWeightArray) { maskWeight = maskWeightArray[vert_index_morph]; } LLVector4a pos = mMorphData->mCoords[vert_index_morph]; pos.mul(delta_weight*maskWeight); coords[vert_index_mesh].add(pos); if (getInfo()->mIsClothingMorph && clothing_weights) { LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; clothing_offset.mul(delta_weight * maskWeight); LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; clothing_weight->add(clothing_offset); clothing_weight->getF32ptr()[VW] = maskWeight; } // calculate new normals based on half angles LLVector4a norm = mMorphData->mNormals[vert_index_morph]; norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); scaled_normals[vert_index_mesh].add(norm); norm = scaled_normals[vert_index_mesh]; // guard against degenerate input data before we create NaNs below! // norm.normalize3fast(); normals[vert_index_mesh] = norm; // calculate new binormals LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; // guard against degenerate input data before we create NaNs below! // if (!binorm.isFinite3() || (binorm.dot3(binorm).getF32() <= F_APPROXIMATELY_ZERO)) { binorm.set(1,0,0,1); } binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); scaled_binormals[vert_index_mesh].add(binorm); LLVector4a tangent; tangent.setCross3(scaled_binormals[vert_index_mesh], norm); LLVector4a& normalized_binormal = binormals[vert_index_mesh]; normalized_binormal.setCross3(norm, tangent); normalized_binormal.normalize3fast(); tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; } // now apply volume changes for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ ) { LLPolyVolumeMorph* volume_morph = &(*iter); LLVector3 scale_delta = volume_morph->mScale * delta_weight; LLVector3 pos_delta = volume_morph->mPos * delta_weight; volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta); volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta); } } if (mNext) { mNext->apply(avatar_sex); } }