summaryrefslogtreecommitdiff
path: root/indra/llprimitive
diff options
context:
space:
mode:
authorDave Houlton <euclid@lindenlab.com>2022-04-13 12:32:58 -0600
committerDave Houlton <euclid@lindenlab.com>2022-06-08 13:33:59 -0600
commit8c0163bcb48df56112a625550d411741c20c5846 (patch)
tree3039fe3694a08ed8ada130ba9f6eead0688198aa /indra/llprimitive
parentd385c73b6e6df968a19a2bb7f0ec1e72bd01e8dc (diff)
SL-17214 initial loader class skeleton
Diffstat (limited to 'indra/llprimitive')
-rw-r--r--indra/llprimitive/CMakeLists.txt2
-rw-r--r--indra/llprimitive/lldaeloader.cpp26
-rw-r--r--indra/llprimitive/lldaeloader.h2
-rw-r--r--indra/llprimitive/llgltfloader.cpp336
-rw-r--r--indra/llprimitive/llgltfloader.h207
-rw-r--r--indra/llprimitive/llmodelloader.cpp13
6 files changed, 566 insertions, 20 deletions
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index fff4d8ef0a..9d75dab31e 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -28,6 +28,7 @@ include_directories(SYSTEM
set(llprimitive_SOURCE_FILES
lldaeloader.cpp
+ llgltfloader.cpp
llmaterialid.cpp
llmaterial.cpp
llmaterialtable.cpp
@@ -46,6 +47,7 @@ set(llprimitive_SOURCE_FILES
set(llprimitive_HEADER_FILES
CMakeLists.txt
lldaeloader.h
+ llgltfloader.h
legacy_object_types.h
llmaterial.h
llmaterialid.h
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index e89690438e..94f8500dab 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -2504,19 +2504,19 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD&
return (status == LLModel::NO_ERRORS);
}
-//static
-LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh)
-{
- LLVolumeParams volume_params;
- volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
- LLModel* ret = new LLModel(volume_params, 0.f);
- createVolumeFacesFromDomMesh(ret, mesh);
- if (ret->mLabel.empty())
- {
- ret->mLabel = getElementLabel(mesh);
- }
- return ret;
-}
+////static
+//LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh)
+//{
+// LLVolumeParams volume_params;
+// volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+// LLModel* ret = new LLModel(volume_params, 0.f);
+// createVolumeFacesFromDomMesh(ret, mesh);
+// if (ret->mLabel.empty())
+// {
+// ret->mLabel = getElementLabel(mesh);
+// }
+// return ret;
+//}
//static diff version supports creating multiple models when material counts spill
// over the 8 face server-side limit
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 2b211343e1..9e80980ddf 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -92,7 +92,7 @@ protected:
static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh, LLSD& log_msg);
static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh);
- static LLModel* loadModelFromDomMesh(domMesh* mesh);
+ //static LLModel* loadModelFromDomMesh(domMesh* mesh);
// Loads a mesh breaking it into one or more models as necessary
// to get around volume face limitations while retaining >8 materials
diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp
new file mode 100644
index 0000000000..001623ac9e
--- /dev/null
+++ b/indra/llprimitive/llgltfloader.cpp
@@ -0,0 +1,336 @@
+/**
+ * @file LLGLTFLoader.cpp
+ * @brief LLGLTFLoader class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "LLGLTFLoader.h"
+
+// Import & define single-header gltf import/export lib
+#define TINYGLTF_IMPLEMENTATION
+#define TINYGLTF_USE_CPP14 // default is C++ 11
+
+// tinygltf by default loads image files using STB
+#define STB_IMAGE_IMPLEMENTATION
+// to use our own image loading:
+// 1. replace this definition with TINYGLTF_NO_STB_IMAGE
+// 2. provide image loader callback with TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)
+
+// tinygltf saves image files using STB
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+// similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and TinyGLTF::SetImageWriter(fxn, data)
+
+// Additionally, disable inclusion of STB header files entirely with
+// TINYGLTF_NO_INCLUDE_STB_IMAGE
+// TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
+#include "tinygltf\tiny_gltf.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "llsdserialize.h"
+#include "lljoint.h"
+
+#include "glh/glh_linear.h"
+#include "llmatrix4a.h"
+
+#include <boost/regex.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+static const std::string lod_suffix[LLModel::NUM_LODS] =
+{
+ "_LOD0",
+ "_LOD1",
+ "_LOD2",
+ "",
+ "_PHYS",
+};
+
+const U32 LIMIT_MATERIALS_OUTPUT = 12;
+
+LLGLTFLoader::LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map<std::string, std::string> &jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit) //,
+ //bool preprocess)
+ : LLModelLoader( filename,
+ lod,
+ load_cb,
+ joint_lookup_func,
+ texture_load_func,
+ state_cb,
+ opaque_userdata,
+ jointTransformMap,
+ jointsFromNodes,
+ jointAliasMap,
+ maxJointsPerMesh ),
+ mGeneratedModelLimit(modelLimit),
+ //mPreprocessGLTF(preprocess),
+ mMeshesLoaded(false),
+ mMaterialsLoaded(false)
+{
+}
+
+LLGLTFLoader::~LLGLTFLoader() {}
+
+bool LLGLTFLoader::OpenFile(const std::string &filename)
+{
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ if (std::string::npos == filename.rfind(".gltf"))
+ { // file is binary
+ mGltfLoaded = loader.LoadBinaryFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
+ }
+ else
+ { // file is ascii
+ mGltfLoaded = loader.LoadASCIIFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
+ }
+
+ if (!mGltfLoaded)
+ {
+ if (!warn_msg.empty())
+ LL_WARNS() << "gltf load warning: " << warn_msg.c_str() << LL_ENDL;
+ if (!error_msg.empty())
+ LL_WARNS() << "gltf load error: " << error_msg.c_str() << LL_ENDL;
+ return false;
+ }
+
+ mMeshesLoaded = parseMeshes();
+ if (mMeshesLoaded) uploadMeshes();
+
+ mMaterialsLoaded = parseMaterials();
+ if (mMaterialsLoaded) uploadMaterials();
+
+ return (mMeshesLoaded || mMaterialsLoaded);
+}
+
+bool LLGLTFLoader::parseMeshes()
+{
+ if (!mGltfLoaded) return false;
+
+ // 2022-04 DJH Volume params from dae example. TODO understand PCODE
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+
+ for (tinygltf::Mesh mesh : mGltfModel.meshes)
+ {
+ LLModel *pModel = new LLModel(volume_params, 0.f);
+
+ if (populateModelFromMesh(pModel, mesh) &&
+ (LLModel::NO_ERRORS == pModel->getStatus()) &&
+ validate_model(pModel))
+ {
+ mModelList.push_back(pModel);
+ }
+ else
+ {
+ setLoadState(ERROR_MODEL + pModel->getStatus());
+ delete(pModel);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh)
+{
+ pModel->mLabel = mesh.name;
+ int pos_idx, norm_idx, tan_idx, uv0_idx, uv1_idx, color0_idx, color1_idx;
+ tinygltf::Accessor indices_a, positions_a, normals_a, uv0_a, color0_a;
+
+ auto prims = mesh.primitives;
+ for (auto prim : prims)
+ {
+ if (prim.indices >= 0) indices_a = mGltfModel.accessors[prim.indices];
+
+ pos_idx = (prim.attributes.count("POSITION") > 0) ? prim.attributes.at("POSITION") : -1;
+ if (pos_idx >= 0)
+ {
+ positions_a = mGltfModel.accessors[pos_idx];
+ if (TINYGLTF_COMPONENT_TYPE_FLOAT != positions_a.componentType)
+ continue;
+ auto positions_bv = mGltfModel.bufferViews[positions_a.bufferView];
+ auto positions_buf = mGltfModel.buffers[positions_bv.buffer];
+ //auto type = positions_vb.
+ //if (positions_buf.name
+ }
+
+ norm_idx = (prim.attributes.count("NORMAL") > 0) ? prim.attributes.at("NORMAL") : -1;
+ tan_idx = (prim.attributes.count("TANGENT") > 0) ? prim.attributes.at("TANGENT") : -1;
+ uv0_idx = (prim.attributes.count("TEXCOORDS_0") > 0) ? prim.attributes.at("TEXCOORDS_0") : -1;
+ uv1_idx = (prim.attributes.count("TEXCOORDS_1") > 0) ? prim.attributes.at("TEXCOORDS_1") : -1;
+ color0_idx = (prim.attributes.count("COLOR_0") > 0) ? prim.attributes.at("COLOR_0") : -1;
+ color1_idx = (prim.attributes.count("COLOR_1") > 0) ? prim.attributes.at("COLOR_1") : -1;
+
+ if (prim.mode == TINYGLTF_MODE_TRIANGLES)
+ {
+ //auto pos = mesh. TODO resume here DJH 2022-04
+ }
+ }
+
+ //pModel->addFace()
+ return false;
+}
+
+bool LLGLTFLoader::parseMaterials()
+{
+ if (!mGltfLoaded) return false;
+
+ // fill local texture data structures
+ mSamplers.clear();
+ for (auto in_sampler : mGltfModel.samplers)
+ {
+ gltf_sampler sampler{ 0 };
+ sampler.magFilter = in_sampler.magFilter;
+ sampler.minFilter = in_sampler.minFilter;
+ sampler.wrapS = in_sampler.wrapS;
+ sampler.wrapT = in_sampler.wrapT;
+ sampler.name = in_sampler.name; // unused
+ mSamplers.push_back(sampler);
+ }
+
+ mImages.clear();
+ for (auto in_image : mGltfModel.images)
+ {
+ gltf_image image{ 0 };
+ image.numChannels = in_image.component;
+ image.bytesPerChannel = in_image.bits >> 3;
+ image.pixelType = in_image.pixel_type;
+ image.size = in_image.image.size();
+ image.height = in_image.height;
+ image.width = in_image.width;
+ image.data = in_image.image.data();
+
+ if (in_image.as_is)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Unsupported image encoding" << LL_ENDL;
+ return false;
+ }
+
+ if (image.size != image.height * image.width * image.numChannels * image.bytesPerChannel)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Image size error" << LL_ENDL;
+ return false;
+ }
+
+ mImages.push_back(image);
+ }
+
+ mTextures.clear();
+ for (auto in_tex : mGltfModel.textures)
+ {
+ gltf_texture tex{ 0 };
+ tex.image_idx = in_tex.source;
+ tex.sampler_idx = in_tex.sampler;
+
+ if (tex.image_idx >= mImages.size() || tex.sampler_idx >= mSamplers.size())
+ {
+ LL_WARNS("GLTF_IMPORT") << "Texture sampler/image index error" << LL_ENDL;
+ return false;
+ }
+
+ mTextures.push_back(tex);
+ }
+
+ // parse each material
+ for (tinygltf::Material gltf_material : mGltfModel.materials)
+ {
+ gltf_render_material mat{ 0 };
+ mat.name = gltf_material.name;
+
+ mat.normalScale = gltf_material.normalTexture.scale;
+ mat.normalTexIdx = gltf_material.normalTexture.index;
+ mat.normalTexCoordIdx = gltf_material.normalTexture.texCoord;
+
+ mat.occlusionScale = gltf_material.occlusionTexture.strength;
+ mat.occlusionTexIdx = gltf_material.occlusionTexture.index;
+ mat.occlusionTexCoordIdx = gltf_material.occlusionTexture.texCoord;
+
+ mat.emissiveColor.set(gltf_material.emissiveFactor.data());
+ mat.emissiveColorTexIdx = gltf_material.emissiveTexture.index;
+ mat.emissiveColorTexCoordIdx = gltf_material.emissiveTexture.texCoord;
+
+ mat.alphaMode = gltf_material.alphaMode;
+ mat.alphaMask = gltf_material.alphaCutoff;
+
+ tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness;
+ mat.hasPBR = true;
+
+ mat.pbr.baseColor.set(pbr.baseColorFactor.data());
+ mat.pbr.baseColorTexIdx = pbr.baseColorTexture.index;
+ mat.pbr.baseColorTexCoordIdx = pbr.baseColorTexture.texCoord;
+
+ mat.pbr.metalness = pbr.metallicFactor;
+ mat.pbr.roughness = pbr.roughnessFactor;
+ mat.pbr.metalRoughTexIdx = pbr.metallicRoughnessTexture.index;
+ mat.pbr.metalRoughTexCoordIdx = pbr.metallicRoughnessTexture.texCoord;
+
+ if (mat.normalTexIdx >= mTextures.size() ||
+ mat.occlusionTexIdx >= mTextures.size() ||
+ mat.emissiveColorTexIdx >= mTextures.size() ||
+ mat.pbr.baseColorTexIdx >= mTextures.size() ||
+ mat.pbr.metalRoughTexIdx >= mTextures.size())
+ {
+ LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL;
+ return false;
+ }
+
+ if (mat.normalTexCoordIdx > 0 || // May have to loosen this condition
+ mat.occlusionTexCoordIdx > 0 ||
+ mat.emissiveColorTexCoordIdx > 0 ||
+ mat.pbr.baseColorTexCoordIdx > 0 ||
+ mat.pbr.metalRoughTexCoordIdx > 0)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL;
+ return false;
+ }
+
+ mMaterials.push_back(mat);
+ }
+
+ return true;
+}
+
+// TODO: convert raw vertex buffers to UUIDs
+void LLGLTFLoader::uploadMeshes()
+{
+ llassert(0);
+}
+
+// TODO: convert raw index buffers to UUIDs
+void LLGLTFLoader::uploadMaterials()
+{
+ llassert(0);
+}
+
diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h
new file mode 100644
index 0000000000..9bffeef4ab
--- /dev/null
+++ b/indra/llprimitive/llgltfloader.h
@@ -0,0 +1,207 @@
+/**
+ * @file LLGLTFLoader.h
+ * @brief LLGLTFLoader class definition
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLGLTFLoader_H
+#define LL_LLGLTFLoader_H
+
+#include "tinygltf\tiny_gltf.h"
+
+#include "llmodelloader.h"
+
+typedef struct // gltf sampler
+{ // Uses GL enums
+ S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR
+ S32 magFilter; // GL_NEAREST or GL_LINEAR
+ S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
+ S32 wrapT; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
+ //S32 wrapR; // seen in some sample files, but not part of glTF 2.0 spec. Ignored.
+ std::string name; // optional, currently unused
+ // extensions and extras are sampler optional fields that we don't support - at least initially
+} gltf_sampler;
+
+typedef struct // gltf image
+{ // Note that glTF images are defined with row 0 at the top
+ U8* data; // ptr to decoded image data
+ U32 size; // in bytes, regardless of channel width
+ U32 width;
+ U32 height;
+ U32 numChannels; // range 1..4
+ U32 bytesPerChannel; // converted from gltf "bits", expects only 8, 16 or 32 as input
+ U32 pixelType; // one of (TINYGLTF_COMPONENT_TYPE)_UNSIGNED_BYTE, _UNSIGNED_SHORT, _UNSIGNED_INT, or _FLOAT
+} gltf_image;
+
+typedef struct // texture
+{
+ U32 image_idx;
+ U32 sampler_idx;
+} gltf_texture;
+
+
+// TODO: 2022-05 DJH add UUIDs for each texture
+typedef struct // gltf_pbrMR_material
+{
+ // scalar values
+ LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present.
+ double metalness;
+ double roughness;
+
+ // textures
+ U32 baseColorTexIdx; // always sRGB encoded
+ U32 baseColorTexCoordIdx;
+
+ U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel
+ U32 metalRoughTexCoordIdx;
+} gltf_pbr;
+
+typedef struct // render material
+{
+ std::string name;
+
+ // scalar values
+ double normalScale; // scale applies only to X,Y components of normal
+ double occlusionScale; // strength multiplier for occlusion
+ LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent)
+ std::string alphaMode; // "OPAQUE", "MASK" or "BLEND"
+ double alphaMask;
+
+ // textures
+ U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0)
+ U32 normalTexCoordIdx;
+
+ U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded
+ U32 occlusionTexCoordIdx;
+
+ U32 emissiveColorTexIdx; // always stored as sRGB, in nits (candela / meter^2)
+ U32 emissiveColorTexCoordIdx;
+
+ // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry??
+
+ bool hasPBR;
+ gltf_pbr pbr;
+
+} gltf_render_material;
+
+typedef struct // gltf_mesh
+{
+ std::string name;
+
+ // TODO DJH 2022-04
+
+} gltf_mesh;
+
+class LLGLTFLoader : public LLModelLoader
+{
+ public:
+ typedef std::map<std::string, LLImportMaterial> material_map;
+ typedef void gltfElement; // TBD
+ typedef void GLTF; // TBD
+
+ // typedef std::map<gltfElement*, std::vector<LLPointer<LLModel> > > gltf_model_map;
+ // gltf_model_map mModelsMap;
+
+ LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map<std::string, std::string> &jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit); //,
+ //bool preprocess );
+ virtual ~LLGLTFLoader();
+
+ virtual bool OpenFile(const std::string &filename);
+
+protected:
+ tinygltf::Model mGltfModel;
+ bool mGltfLoaded;
+ bool mMeshesLoaded;
+ bool mMaterialsLoaded;
+
+ std::vector<gltf_mesh> mMeshes;
+ std::vector<gltf_render_material> mMaterials;
+
+ std::vector<gltf_texture> mTextures;
+ std::vector<gltf_image> mImages;
+ std::vector<gltf_sampler> mSamplers;
+
+private:
+ U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels
+// bool mPreprocessGLTF;
+
+ bool parseMeshes();
+ void uploadMeshes();
+ bool parseMaterials();
+ void uploadMaterials();
+ bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh);
+
+ /*
+ void processElement(gltfElement *element, bool &badElement, GLTF *gltf);
+ void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin);
+
+ material_map getMaterials(LLModel *model, gltfInstance_geometry *instance_geo, GLTF *gltf);
+ LLImportMaterial profileToMaterial(gltfProfile_COMMON *material, GLTF *gltf);
+ LLColor4 getGltfColor(gltfElement *element);
+
+ gltfElement *getChildFromElement(gltfElement *pElement, std::string const &name);
+
+ bool isNodeAJoint(gltfNode *pNode);
+ void processJointNode(gltfNode *pNode, std::map<std::string, LLMatrix4> &jointTransforms);
+ void extractTranslation(gltfTranslate *pTranslate, LLMatrix4 &transform);
+ void extractTranslationViaElement(gltfElement *pTranslateElement, LLMatrix4 &transform);
+ void extractTranslationViaSID(gltfElement *pElement, LLMatrix4 &transform);
+ void buildJointToNodeMappingFromScene(gltfElement *pRoot);
+ void processJointToNodeMapping(gltfNode *pNode);
+ void processChildJoints(gltfNode *pParentNode);
+
+ bool verifyCount(int expected, int result);
+
+ // Verify that a controller matches vertex counts
+ bool verifyController(gltfController *pController);
+
+ static bool addVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh, LLSD &log_msg);
+ static bool createVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh);
+
+ static LLModel *loadModelFromGltfMesh(gltfMesh *mesh);
+
+ // Loads a mesh breaking it into one or more models as necessary
+ // to get around volume face limitations while retaining >8 materials
+ //
+ bool loadModelsFromGltfMesh(gltfMesh *mesh, std::vector<LLModel *> &models_out, U32 submodel_limit);
+
+ static std::string getElementLabel(gltfElement *element);
+ static size_t getSuffixPosition(std::string label);
+ static std::string getLodlessLabel(gltfElement *element);
+
+ static std::string preprocessGLTF(std::string filename);
+ */
+
+};
+#endif // LL_LLGLTFLLOADER_H
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index 5171621007..554ed54de1 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -160,7 +160,8 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin
std::string::size_type i = model_filename.rfind(".");
if (i != std::string::npos)
{
- slm_filename.replace(i, model_filename.size()-1, ".slm");
+ slm_filename.resize(i, '\0');
+ slm_filename.append(".slm");
return true;
}
else
@@ -172,7 +173,7 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin
bool LLModelLoader::doLoadModel()
{
//first, look for a .slm file of the same name that was modified later
- //than the .dae
+ //than the specified model file
if (mTrySLM)
{
@@ -182,13 +183,13 @@ bool LLModelLoader::doLoadModel()
llstat slm_status;
if (LLFile::stat(slm_filename, &slm_status) == 0)
{ //slm file exists
- llstat dae_status;
- if (LLFile::stat(mFilename, &dae_status) != 0 ||
- dae_status.st_mtime < slm_status.st_mtime)
+ llstat model_file_status;
+ if (LLFile::stat(mFilename, &model_file_status) != 0 ||
+ model_file_status.st_mtime < slm_status.st_mtime)
{
if (loadFromSLM(slm_filename))
{ //slm successfully loaded, if this fails, fall through and
- //try loading from dae
+ //try loading from model file
mLod = -1; //successfully loading from an slm implicitly sets all
//LoDs