diff options
| author | andreykproductengine <akleshchev@productengine.com> | 2016-11-15 20:16:01 +0200 | 
|---|---|---|
| committer | andreykproductengine <akleshchev@productengine.com> | 2016-11-15 20:16:01 +0200 | 
| commit | 4ae6f32ee16b21aed2235e96b99e18eebfdd82c6 (patch) | |
| tree | 212e54201405225784a3e23c5ee847f0e688ac24 | |
| parent | 2e52d12ef1ecc53f1affdf7b6d2150e9256eee65 (diff) | |
MAINT-6901 Fixes upload assigning different scale to parts of the model
| -rw-r--r-- | indra/llprimitive/lldaeloader.cpp | 13 | ||||
| -rw-r--r-- | indra/llprimitive/llmodel.cpp | 159 | ||||
| -rw-r--r-- | indra/llprimitive/llmodel.h | 1 | 
3 files changed, 165 insertions, 8 deletions
| diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 031befe63a..de02c5c188 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -999,6 +999,11 @@ bool LLDAELoader::OpenFile(const std::string& filename)  	std::sort(mModelList.begin(), mModelList.end(), ModelSort()); +	if (!mNoNormalize) +	{ +		LLModel::normalizeModels(mModelList); +	} +  	model_list::iterator model_iter = mModelList.begin();  	while (model_iter != mModelList.end())  	{ @@ -2408,8 +2413,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo  	//  	ret->sortVolumeFacesByMaterialName(); -	bool normalized = false; -      int submodelID = 0;  	// remove all faces that definitely won't fit into one model and submodel limit @@ -2424,12 +2427,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo  	{  		// Insure we do this once with the whole gang and not per-model  		// -		if (!normalized && !mNoNormalize) -		{			 -			normalized = true; -			ret->normalizeVolumeFaces(); -		} -  		ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder);  		if (!mNoOptimize) diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index e494c55250..3270722ccb 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -174,6 +174,165 @@ void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remain  	}  } +// Shrink group of models to fit +// on a 1x1x1 cube centered at the origin. +void LLModel::normalizeModels(std::vector<LLPointer<LLModel>> model_list) +{ +    std::vector<LLPointer<LLModel > >::iterator iter = model_list.begin(); + +    LLVector4a min, max; +    while (iter != model_list.end() && (*iter)->mVolumeFaces.empty()) +    { +        iter++; +    } +    if (iter == model_list.end()) +    { +        // no models with faces +        return; +    } + +    min = (*iter)->mVolumeFaces[0].mExtents[0]; +    max = (*iter)->mVolumeFaces[0].mExtents[1]; + +    // Treat models as a group - each model out of 1x1x1 cube +    // needs scaling and will affect whole group scale +    while (iter != model_list.end()) +    { +        LLPointer<LLModel> model = *iter++; + +        if (model.get() && model->mVolumeFaces.empty()) +        { +            // For all of the volume faces +            // in the model, loop over +            // them and see what the extents +            // of the volume along each axis. + +            for (U32 i = 0; i < model->mVolumeFaces.size(); ++i) +            { +                LLVolumeFace& face = model->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 < 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); +     +    iter = model_list.begin(); +    // apply fixed scale and trans to all models as a single group +    while (iter != model_list.end()) +    { +        LLPointer<LLModel> model = *iter++; + +        if (model->mVolumeFaces.empty()) +        { +            continue; +        } + +        for (U32 i = 0; i < model->mVolumeFaces.size(); ++i) +        { +            LLVolumeFace& face = model->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 < 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); +        model->mNormalizedScale.set(normalized_scale.getF32ptr()); +        model->mNormalizedTranslation.set(trans.getF32ptr()); +        model->mNormalizedTranslation *= -1.f; +    } +} +  // Shrink the model to fit  // on a 1x1x1 cube centered at the origin.  // The positions and extents diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index ae602c09df..8fe025a352 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -172,6 +172,7 @@ public:  	void addFace(const LLVolumeFace& face);  	void sortVolumeFacesByMaterialName(); +	static void normalizeModels(std::vector<LLPointer<LLModel>> model_list);  	void normalizeVolumeFaces();  	void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);  	void optimizeVolumeFaces(); | 
