Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions indra/llprimitive/llmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,93 @@ void LLModel::remapVolumeFaces()
}
}

void LLModel::remapSkinWeightsAndJoints()
{
if (mSkinWeights.empty())
{
return;
}

mPosition.clear();

// Make a list of positions
std::set<LLVector3> positions;
for (S32 i = 0; i < getNumVolumeFaces(); ++i)
{
for (S32 j = 0; j < mVolumeFaces[i].mNumVertices; ++j)
{
positions.emplace(mVolumeFaces[i].mPositions[j].getF32ptr());
}
}

// Build new list of weights and record used joints
weight_map replacement_weights;
std::vector<S32> joint_index_use_count;
size_t joint_count = mSkinInfo.mJointNames.size();
joint_index_use_count.resize(joint_count, 0);
for (const LLVector3& pos : positions)
{
mPosition.push_back(pos);
auto found = mSkinWeights.find(pos);
if (found != mSkinWeights.end())
{
replacement_weights[pos] = found->second;

for (auto& weight : found->second)
{
if (joint_count > weight.mJointIdx)
{
joint_index_use_count[weight.mJointIdx]++;
}
}
}
}

// go over joint data and remap joints
// prepare joint map
std::vector<std::string> replacement_joint_names;
std::vector<S32> replacement_joint_nums;
LLMeshSkinInfo::matrix_list_t replacement_inv_bind;
LLMeshSkinInfo::matrix_list_t replacement_alt_bind;
std::vector<S32> index_map;
index_map.resize(joint_count);
S32 replacement_index = 0;

for (S32 i = 0; i < joint_count; i++)
{
if (joint_index_use_count[i] > 0)
{
replacement_joint_names.push_back(mSkinInfo.mJointNames[i]);
replacement_joint_nums.push_back(mSkinInfo.mJointNums[i]);
replacement_inv_bind.push_back(mSkinInfo.mInvBindMatrix[i]);
replacement_alt_bind.push_back(mSkinInfo.mAlternateBindMatrix[i]);
index_map[i] = replacement_index++;
}
}

// Apply new data
mSkinInfo.mJointNames.clear();
mSkinInfo.mJointNames = replacement_joint_names;
mSkinInfo.mJointNums.clear();
mSkinInfo.mJointNums = replacement_joint_nums;
mSkinInfo.mInvBindMatrix.clear();
mSkinInfo.mInvBindMatrix = replacement_inv_bind;
mSkinInfo.mAlternateBindMatrix.clear();
mSkinInfo.mAlternateBindMatrix = replacement_alt_bind;

// remap weights
for (auto& weights : replacement_weights)
{
for (auto& weight : weights.second)
{
weight.mJointIdx = index_map[weight.mJointIdx];
}
}

mSkinWeights.clear();
mSkinWeights = replacement_weights;
}

void LLModel::optimizeVolumeFaces()
{
for (S32 i = 0; i < getNumVolumeFaces(); ++i)
Expand Down
1 change: 1 addition & 0 deletions indra/llprimitive/llmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ class LLModel : public LLVolume
void normalizeVolumeFacesAndWeights();
void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
void remapVolumeFaces();
void remapSkinWeightsAndJoints();
void optimizeVolumeFaces();
void offsetMesh( const LLVector3& pivotPoint );
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const;
Expand Down
105 changes: 97 additions & 8 deletions indra/newview/gltf/llgltfloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ LLGLTFLoader::LLGLTFLoader(std::string filename,
maxJointsPerMesh ),
//mPreprocessGLTF(preprocess),
mMeshesLoaded(false),
mMaterialsLoaded(false)
mMaterialsLoaded(false),
mGeneratedModelLimit(modelLimit)
{
}

Expand Down Expand Up @@ -135,6 +136,97 @@ bool LLGLTFLoader::OpenFile(const std::string &filename)
return (mMeshesLoaded);
}

void LLGLTFLoader::addModelToScene(
LLModel* pModel,
U32 submodel_limit,
const LLMatrix4& transformation,
const LLVolumeParams& volume_params)
{
U32 volume_faces = pModel->getNumVolumeFaces();

// Side-steps all manner of issues when splitting models
// and matching lower LOD materials to base models
//
pModel->sortVolumeFacesByMaterialName();

int submodelID = 0;

// remove all faces that definitely won't fit into one model and submodel limit
U32 face_limit = (submodel_limit + 1) * LL_SCULPT_MESH_MAX_FACES;
if (face_limit < volume_faces)
{
pModel->setNumVolumeFaces(face_limit);
}

LLVolume::face_list_t remainder;
std::vector<LLModel*> ready_models;
LLModel* current_model = pModel;
do
{
current_model->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder);

volume_faces = static_cast<U32>(remainder.size());

// Don't add to scene yet because weights and materials aren't ready.
// Just save it
ready_models.push_back(current_model);

// If we have left-over volume faces, create another model
// to absorb them.
if (volume_faces)
{
LLModel* next = new LLModel(volume_params, 0.f);
next->ClearFacesAndMaterials();
next->mSubmodelID = ++submodelID;
next->mLabel = pModel->mLabel + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod];
next->getVolumeFaces() = remainder;
next->mNormalizedScale = current_model->mNormalizedScale;
next->mNormalizedTranslation = current_model->mNormalizedTranslation;
next->mSkinWeights = current_model->mSkinWeights;
next->mPosition = current_model->mPosition;

const LLMeshSkinInfo& current_skin_info = current_model->mSkinInfo;
LLMeshSkinInfo& next_skin_info = next->mSkinInfo;
next_skin_info.mJointNames = current_skin_info.mJointNames;
next_skin_info.mJointNums = current_skin_info.mJointNums;
next_skin_info.mBindShapeMatrix = current_skin_info.mBindShapeMatrix;
next_skin_info.mInvBindMatrix = current_skin_info.mInvBindMatrix;
next_skin_info.mAlternateBindMatrix = current_skin_info.mAlternateBindMatrix;
next_skin_info.mPelvisOffset = current_skin_info.mPelvisOffset;


if (current_model->mMaterialList.size() > LL_SCULPT_MESH_MAX_FACES)
{
next->mMaterialList.assign(current_model->mMaterialList.begin() + LL_SCULPT_MESH_MAX_FACES, current_model->mMaterialList.end());
current_model->mMaterialList.resize(LL_SCULPT_MESH_MAX_FACES);
}

current_model = next;
}

remainder.clear();

} while (volume_faces);

for (auto model : ready_models)
{
// remove unused/redundant vertices
current_model->remapVolumeFaces();
// remove unused/redundant weights and joints
current_model->remapSkinWeightsAndJoints();

mModelList.push_back(model);

std::map<std::string, LLImportMaterial> materials;
for (U32 i = 0; i < (U32)model->mMaterialList.size(); ++i)
{
materials[model->mMaterialList[i]] = LLImportMaterial();
}
mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));
stretch_extents(model, transformation);
}
}

bool LLGLTFLoader::parseMeshes()
{
if (!mGltfLoaded) return false;
Expand All @@ -160,6 +252,7 @@ bool LLGLTFLoader::parseMeshes()

// Track how many times each mesh name has been used
std::map<std::string, S32> mesh_name_counts;
U32 submodel_limit = mGLTFAsset.mNodes.size() > 0 ? mGeneratedModelLimit / (U32)mGLTFAsset.mNodes.size() : 0;

// Process each node
for (auto& node : mGLTFAsset.mNodes)
Expand Down Expand Up @@ -188,8 +281,6 @@ bool LLGLTFLoader::parseMeshes()
(LLModel::NO_ERRORS == pModel->getStatus()) &&
validate_model(pModel))
{
mModelList.push_back(pModel);

mTransform.setIdentity();
transformation = mTransform;

Expand Down Expand Up @@ -234,8 +325,7 @@ bool LLGLTFLoader::parseMeshes()
mWarningsArray.append(args);
}

mScene[transformation].push_back(LLModelInstance(pModel, pModel->mLabel, transformation, mats));
stretch_extents(pModel, transformation);
addModelToScene(pModel, submodel_limit, transformation, volume_params);
}
else
{
Expand Down Expand Up @@ -347,8 +437,7 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
}
}

auto prims = mesh.mPrimitives;
for (auto prim : prims)
for (const LL::GLTF::Primitive& prim : mesh.mPrimitives)
{
// Unfortunately, SLM does not support 32 bit indices. Filter out anything that goes beyond 16 bit.
if (prim.getVertexCount() < USHRT_MAX)
Expand Down Expand Up @@ -471,7 +560,7 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
{
vert.weights = glm::vec4(prim.mWeights[i]);

auto accessorIdx = prim.mAttributes["JOINTS_0"];
auto accessorIdx = prim.mAttributes.at("JOINTS_0");
LL::GLTF::Accessor::ComponentType componentType = LL::GLTF::Accessor::ComponentType::UNSIGNED_BYTE;
if (accessorIdx >= 0)
{
Expand Down
6 changes: 6 additions & 0 deletions indra/newview/gltf/llgltfloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class LLGLTFLoader : public LLModelLoader
bool mGltfLoaded;
bool mMeshesLoaded;
bool mMaterialsLoaded;
U32 mGeneratedModelLimit;

std::vector<gltf_mesh> mMeshes;
std::vector<gltf_render_material> mMaterials;
Expand All @@ -176,6 +177,11 @@ class LLGLTFLoader : public LLModelLoader
void computeCombinedNodeTransform(const LL::GLTF::Asset& asset, S32 node_index, glm::mat4& combined_transform) const;
bool populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &mesh, const LL::GLTF::Node &node, material_map& mats, S32 instance_count);
void populateJointFromSkin(S32 skin_idx);
void addModelToScene(
LLModel* pModel,
U32 submodel_limit,
const LLMatrix4& transformation,
const LLVolumeParams& volume_params);
S32 findClosestValidJoint(S32 source_joint, const LL::GLTF::Skin& gltf_skin) const;
S32 findValidRootJointNode(S32 source_joint_node, const LL::GLTF::Skin& gltf_skin) const;
S32 findGLTFRootJointNode(const LL::GLTF::Skin& gltf_skin) const; // if there are multiple roots, gltf stores them under one commor joint
Expand Down