Fix import rotation and UVs

master
Jonathan "Geenz" Goodman 2025-05-04 23:40:10 -04:00
parent e87c629406
commit dd74b361e3
3 changed files with 35 additions and 209 deletions

View File

@ -111,6 +111,7 @@ public:
bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info)
model_list mModelList;
// The scene is pretty much what ends up getting loaded for upload. Basically assign things to this guy if you want something uploaded.
scene mScene;
typedef std::queue<LLPointer<LLModel> > model_queue;

View File

@ -153,15 +153,20 @@ bool LLGLTFLoader::parseMeshes()
{
LLModel* pModel = new LLModel(volume_params, 0.f);
auto mesh = mGLTFAsset.mMeshes[meshidx];
if (populateModelFromMesh(pModel, mesh, mats) && (LLModel::NO_ERRORS == pModel->getStatus()) && validate_model(pModel))
if (populateModelFromMesh(pModel, mesh, node, mats) && (LLModel::NO_ERRORS == pModel->getStatus()) && validate_model(pModel))
{
mModelList.push_back(pModel);
LLMatrix4 saved_transform = mTransform;
LLMatrix4 gltf_transform = LLMatrix4(glm::value_ptr(node.mMatrix));
mTransform *= gltf_transform;
mTransform.condition();
// GLTF is +Y up, SL is +Z up
LLMatrix4 rotation;
rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
mTransform *= rotation;
transformation = mTransform;
// adjust the transformation to compensate for mesh normalization
LLVector3 mesh_scale_vector;
@ -206,7 +211,7 @@ bool LLGLTFLoader::parseMeshes()
return true;
}
bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &mesh, material_map &mats)
bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh& mesh, const LL::GLTF::Node& node, material_map& mats)
{
pModel->mLabel = mesh.mName;
pModel->ClearFacesAndMaterials();
@ -222,10 +227,10 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &
// count. Just go ahead and populate faces direct from the GLTF primitives here. -Geenz 2025-04-07
LLVolumeFace face;
LLVolumeFace::VertexMapData::PointMap point_map;
std::vector<GLTFVertex> vertices;
std::vector<U16> indices;
LLImportMaterial impMat;
LL::GLTF::Material* material = nullptr;
@ -240,7 +245,7 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &
GLTFVertex vert;
vert.position = glm::vec3(prim.mPositions[i][0], prim.mPositions[i][1], prim.mPositions[i][2]);
vert.normal = glm::vec3(prim.mNormals[i][0], prim.mNormals[i][1], prim.mNormals[i][2]);
vert.uv0 = glm::vec2(prim.mTexCoords0[i][0], prim.mTexCoords0[i][1]);
vert.uv0 = glm::vec2(prim.mTexCoords0[i][0],-prim.mTexCoords0[i][1]);
vertices.push_back(vert);
}
@ -250,12 +255,29 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &
}
std::vector<LLVolumeFace::VertexData> faceVertices;
glm::vec3 min = glm::vec3(0);
glm::vec3 max = glm::vec3(0);
for (U32 i = 0; i < vertices.size(); i++)
{
LLVolumeFace::VertexData vert;
LLVector4a position = LLVector4a(vertices[i].position.x, vertices[i].position.y, vertices[i].position.z);
LLVector4a normal = LLVector4a(vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z);
if (vertices[i].position.x > max.x)
max.x = vertices[i].position.x;
if (vertices[i].position.y > max.y)
max.y = vertices[i].position.y;
if (vertices[i].position.z > max.z)
max.z = vertices[i].position.z;
if (vertices[i].position.x < min.x)
min.x = vertices[i].position.x;
if (vertices[i].position.y < min.y)
min.y = vertices[i].position.y;
if (vertices[i].position.z < min.z)
min.z = vertices[i].position.z;
LLVector4a position = LLVector4a(vertices[i].position.x, vertices[i].position.y, vertices[i].position.z);
LLVector4a normal = LLVector4a(vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z);
vert.setPosition(position);
vert.setNormal(normal);
vert.mTexCoord = LLVector2(vertices[i].uv0.x, vertices[i].uv0.y);
@ -263,6 +285,8 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &
}
face.fillFromLegacyData(faceVertices, indices);
face.mExtents[0] = LLVector4a(min.x, min.y, min.z, 0);
face.mExtents[1] = LLVector4a(max.x, max.y, max.z, 0);
pModel->getVolumeFaces().push_back(face);
pModel->getMaterialList().push_back("mat" + std::to_string(prim.mMaterial));
@ -280,205 +304,6 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &
return true;
}
/*
LLModel::EModelStatus loadFaceFromGLTFModel(LLModel* pModel, const LL::GLTF::Mesh& mesh, material_map& mats, LLSD& log_msg)
{
LLVolumeFace face;
std::vector<LLVolumeFace::VertexData> verts;
std::vector<U16> indices;
S32 pos_offset = -1;
S32 tc_offset = -1;
S32 norm_offset = -1;
auto pos_source = mesh.mPrimitives[0].mPositions;
auto tc_source = mesh.mPrimitives[0].mNormals;
auto norm_source = mesh.mPrimitives[0].mTexCoords0;
S32 idx_stride = 0;
if (pos_source.size() > USHRT_MAX)
{
LL_WARNS() << "Unable to process mesh due to 16-bit index limits; invalid model; invalid model." << LL_ENDL;
LLSD args;
args["Message"] = "ParsingErrorBadElement";
log_msg.append(args);
return LLModel::BAD_ELEMENT;
}
std::vector<U32> idx = mesh.mPrimitives[0].mIndexArray;
domListOfFloats dummy;
domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy;
domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy;
domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy;
if (pos_source.size() == 0)
{
return LLModel::BAD_ELEMENT;
}
// VFExtents change
face.mExtents[0].set(pos_source[0][0], pos_source[0][1], pos_source[0][2]);
face.mExtents[1].set(pos_source[0][0], pos_source[0][1], pos_source[0][2]);
LLVolumeFace::VertexMapData::PointMap point_map;
if (idx_stride <= 0 || (pos_source && pos_offset >= idx_stride) || (tc_source && tc_offset >= idx_stride) ||
(norm_source && norm_offset >= idx_stride))
{
// Looks like these offsets should fit inside idx_stride
// Might be good idea to also check idx.getCount()%idx_stride != 0
LL_WARNS() << "Invalid pos_offset " << pos_offset << ", tc_offset " << tc_offset << " or norm_offset " << norm_offset << LL_ENDL;
return LLModel::BAD_ELEMENT;
}
for (U32 i = 0; i < idx.getCount(); i += idx_stride)
{
LLVolumeFace::VertexData cv;
if (pos_source)
{
cv.setPosition(
LLVector4a((F32)v[idx[i + pos_offset] * 3 + 0], (F32)v[idx[i + pos_offset] * 3 + 1], (F32)v[idx[i + pos_offset] * 3 + 2]));
}
if (tc_source)
{
cv.mTexCoord.setVec((F32)tc[idx[i + tc_offset] * 2 + 0], (F32)tc[idx[i + tc_offset] * 2 + 1]);
}
if (norm_source)
{
cv.setNormal(LLVector4a((F32)n[idx[i + norm_offset] * 3 + 0],
(F32)n[idx[i + norm_offset] * 3 + 1],
(F32)n[idx[i + norm_offset] * 3 + 2]));
}
bool found = false;
LLVolumeFace::VertexMapData::PointMap::iterator point_iter;
point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr()));
if (point_iter != point_map.end())
{
for (U32 j = 0; j < point_iter->second.size(); ++j)
{
// We have a matching loc
//
if ((point_iter->second)[j] == cv)
{
U16 shared_index = (point_iter->second)[j].mIndex;
// Don't share verts within the same tri, degenerate
//
U32 indx_size = static_cast<U32>(indices.size());
U32 verts_new_tri = indx_size % 3;
if ((verts_new_tri < 1 || indices[indx_size - 1] != shared_index) &&
(verts_new_tri < 2 || indices[indx_size - 2] != shared_index))
{
found = true;
indices.push_back(shared_index);
}
break;
}
}
}
if (!found)
{
// VFExtents change
update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
verts.push_back(cv);
if (verts.size() >= 65535)
{
// llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL;
return LLModel::VERTEX_NUMBER_OVERFLOW;
}
U16 index = (U16)(verts.size() - 1);
indices.push_back(index);
LLVolumeFace::VertexMapData d;
d.setPosition(cv.getPosition());
d.mTexCoord = cv.mTexCoord;
d.setNormal(cv.getNormal());
d.mIndex = index;
if (point_iter != point_map.end())
{
point_iter->second.push_back(d);
}
else
{
point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d);
}
}
if (indices.size() % 3 == 0 && verts.size() >= 65532)
{
std::string material;
if (tri->getMaterial())
{
material = std::string(tri->getMaterial());
}
materials.push_back(material);
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
// ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
// ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
face = LLVolumeFace();
// VFExtents change
face.mExtents[0].set((F32)v[0], (F32)v[1], (F32)v[2]);
face.mExtents[1].set((F32)v[0], (F32)v[1], (F32)v[2]);
verts.clear();
indices.clear();
point_map.clear();
}
}
if (!verts.empty())
{
std::string material;
if (tri->getMaterial())
{
material = std::string(tri->getMaterial());
}
materials.push_back(material);
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
// ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
// ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
return LLModel::NO_ERRORS;
}
*/
bool LLGLTFLoader::parseMaterials()
{
return true;

View File

@ -165,7 +165,7 @@ private:
void uploadMeshes();
bool parseMaterials();
void uploadMaterials();
bool populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &mesh, material_map& mats);
bool populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &mesh, const LL::GLTF::Node &node, material_map& mats);
LLUUID imageBufferToTextureUUID(const gltf_texture& tex);
// bool mPreprocessGLTF;