transformation t_scale( const vector& v ) { transformation t; t.m = scale(v); t.inv = inv_scale(v); return t; }
// Shrink the model to fit // on a 1x1x1 cube centered at the origin. // The positions and extents // multiplied by mNormalizedScale // and offset by mNormalizedTranslation // to be the "original" extents and position. // Also, the positions will fit // within the unit cube. void LLModel::normalizeVolumeFaces() { // ensure we don't have too many faces if (mVolumeFaces.size() > LL_SCULPT_MESH_MAX_FACES) mVolumeFaces.resize(LL_SCULPT_MESH_MAX_FACES); if (!mVolumeFaces.empty()) { LLVector4a min, max; // For all of the volume faces // in the model, loop over // them and see what the extents // of the volume along each axis. min = mVolumeFaces[0].mExtents[0]; max = mVolumeFaces[0].mExtents[1]; for (U32 i = 1; i < mVolumeFaces.size(); ++i) { LLVolumeFace& face = mVolumeFaces[i]; update_min_max(min, max, face.mExtents[0]); update_min_max(min, max, face.mExtents[1]); if (face.mTexCoords) { LLVector2& min_tc = face.mTexCoordExtents[0]; LLVector2& max_tc = face.mTexCoordExtents[1]; min_tc = face.mTexCoords[0]; max_tc = face.mTexCoords[0]; for (U32 j = 1; j < (U32)face.mNumVertices; ++j) { update_min_max(min_tc, max_tc, face.mTexCoords[j]); } } else { face.mTexCoordExtents[0].set(0,0); face.mTexCoordExtents[1].set(1,1); } } // Now that we have the extents of the model // we can compute the offset needed to center // the model at the origin. // Compute center of the model // and make it negative to get translation // needed to center at origin. LLVector4a trans; trans.setAdd(min, max); trans.mul(-0.5f); // Compute the total size along all // axes of the model. LLVector4a size; size.setSub(max, min); // Prevent division by zero. F32 x = size[0]; F32 y = size[1]; F32 z = size[2]; F32 w = size[3]; if (fabs(x)<F_APPROXIMATELY_ZERO) { x = 1.0; } if (fabs(y)<F_APPROXIMATELY_ZERO) { y = 1.0; } if (fabs(z)<F_APPROXIMATELY_ZERO) { z = 1.0; } size.set(x,y,z,w); // Compute scale as reciprocal of size LLVector4a scale; scale.splat(1.f); scale.div(size); LLVector4a inv_scale(1.f); inv_scale.div(scale); for (U32 i = 0; i < mVolumeFaces.size(); ++i) { LLVolumeFace& face = mVolumeFaces[i]; // We shrink the extents so // that they fall within // the unit cube. face.mExtents[0].add(trans); face.mExtents[0].mul(scale); face.mExtents[1].add(trans); face.mExtents[1].mul(scale); // For all the positions, we scale // the positions to fit within the unit cube. LLVector4a* pos = (LLVector4a*) face.mPositions; LLVector4a* norm = (LLVector4a*) face.mNormals; for (U32 j = 0; j < (U32)face.mNumVertices; ++j) { pos[j].add(trans); pos[j].mul(scale); if (norm && !norm[j].equals3(LLVector4a::getZero())) { norm[j].mul(inv_scale); norm[j].normalize3(); } } } // mNormalizedScale is the scale at which // we would need to multiply the model // by to get the original size of the // model instead of the normalized size. LLVector4a normalized_scale; normalized_scale.splat(1.f); normalized_scale.div(scale); mNormalizedScale.set(normalized_scale.getF32ptr()); mNormalizedTranslation.set(trans.getF32ptr()); mNormalizedTranslation *= -1.f; } }