diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index 9d75dab31efd6f29db3c65955fcc477b121cf388..2395841eae04bd7211cde9b3b45d6f6013db8f30 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -10,12 +10,14 @@ include(LLCoreHttp)
 include(LLXML)
 include(LLPhysicsExtensions)
 include(LLCharacter)
+include(LLRender)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
     ${LLMESSAGE_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
+    ${LLRENDER_INCLUDE_DIRS}
     ${LIBS_PREBUILT_DIR}/include/collada
     ${LIBS_PREBUILT_DIR}/include/collada/1.4
     ${LLCHARACTER_INCLUDE_DIRS}
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 94f8500daba683eb881d2879994fd54e5572e290..68b29f01dad29a769783e6fbaca89158adc08b06 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -2504,20 +2504,6 @@ 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 diff version supports creating multiple models when material counts spill
 // over the 8 face server-side limit
 //
@@ -2608,31 +2594,3 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
 
 	return true;
 }
-
-bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh)
-{
-	if (mesh)
-	{
-		pModel->ClearFacesAndMaterials();
-
-		LLSD placeholder;
-		addVolumeFacesFromDomMesh(pModel, mesh, placeholder);
-
-		if (pModel->getNumVolumeFaces() > 0)
-		{
-			pModel->normalizeVolumeFaces();
-			pModel->optimizeVolumeFaces();
-
-			if (pModel->getNumVolumeFaces() > 0)
-			{
-				return true;
-			}
-		}
-	}
-	else
-	{	
-		LL_WARNS() << "no mesh found" << LL_ENDL;
-	}
-
-	return false;
-}
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 9e80980ddff49348bcae0be8c8aed3c4cccfce36..52ad908870a2c7ec41a1d01eca59de54291ac93f 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -90,9 +90,6 @@ class LLDAELoader : public LLModelLoader
 	bool verifyController( domController* pController );
 
 	static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh, LLSD& log_msg);
-	static bool createVolumeFacesFromDomMesh(LLModel* model, 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
index 001623ac9ef291f3baea15ca923efd7b5119b9cb..bc9c4760f7fc0f168d3c250a25cba9accbb9ae80 100644
--- a/indra/llprimitive/llgltfloader.cpp
+++ b/indra/llprimitive/llgltfloader.cpp
@@ -211,9 +211,9 @@ bool LLGLTFLoader::parseMaterials()
     mSamplers.clear();
     for (auto in_sampler : mGltfModel.samplers)
     {
-        gltf_sampler sampler{ 0 };
-        sampler.magFilter = in_sampler.magFilter;
-        sampler.minFilter = in_sampler.minFilter;
+        gltf_sampler sampler;
+        sampler.magFilter = in_sampler.magFilter > 0 ? in_sampler.magFilter : GL_LINEAR;
+        sampler.minFilter = in_sampler.minFilter > 0 ? in_sampler.minFilter : GL_LINEAR;;
         sampler.wrapS     = in_sampler.wrapS;
         sampler.wrapT     = in_sampler.wrapT;
         sampler.name      = in_sampler.name; // unused
@@ -223,10 +223,10 @@ bool LLGLTFLoader::parseMaterials()
     mImages.clear();
     for (auto in_image : mGltfModel.images)
     {
-        gltf_image image{ 0 };
+        gltf_image image;
         image.numChannels     = in_image.component;
-        image.bytesPerChannel = in_image.bits >> 3;
-        image.pixelType       = in_image.pixel_type;
+        image.bytesPerChannel = in_image.bits >> 3;     // Convert bits to bytes
+        image.pixelType       = in_image.pixel_type;    // Maps exactly, i.e. TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE == GL_UNSIGNED_BYTE, etc
         image.size            = in_image.image.size();
         image.height          = in_image.height;
         image.width           = in_image.width;
@@ -250,7 +250,7 @@ bool LLGLTFLoader::parseMaterials()
     mTextures.clear();
     for (auto in_tex : mGltfModel.textures)
     {
-        gltf_texture tex{ 0 };
+        gltf_texture tex;
         tex.image_idx   = in_tex.source;
         tex.sampler_idx = in_tex.sampler;
 
@@ -266,18 +266,21 @@ bool LLGLTFLoader::parseMaterials()
     // parse each material
     for (tinygltf::Material gltf_material : mGltfModel.materials)
     {
-        gltf_render_material mat{ 0 };
+        gltf_render_material mat;
         mat.name = gltf_material.name;
 
         mat.normalScale = gltf_material.normalTexture.scale;
+        mat.hasNormalTex = gltf_material.normalTexture.index > 0;
         mat.normalTexIdx = gltf_material.normalTexture.index;
         mat.normalTexCoordIdx = gltf_material.normalTexture.texCoord;
 
         mat.occlusionScale = gltf_material.occlusionTexture.strength;
+        mat.hasOcclusionTex = gltf_material.occlusionTexture.index > 0;
         mat.occlusionTexIdx = gltf_material.occlusionTexture.index;
         mat.occlusionTexCoordIdx = gltf_material.occlusionTexture.texCoord;
 
         mat.emissiveColor.set(gltf_material.emissiveFactor.data());
+        mat.hasEmissiveTex = gltf_material.emissiveTexture.index > 0;
         mat.emissiveColorTexIdx = gltf_material.emissiveTexture.index;
         mat.emissiveColorTexCoordIdx = gltf_material.emissiveTexture.texCoord;
 
@@ -288,29 +291,31 @@ bool LLGLTFLoader::parseMaterials()
         mat.hasPBR = true;
 
         mat.pbr.baseColor.set(pbr.baseColorFactor.data());
+        mat.pbr.hasBaseTex = pbr.baseColorTexture.index > 0;
         mat.pbr.baseColorTexIdx = pbr.baseColorTexture.index;
         mat.pbr.baseColorTexCoordIdx = pbr.baseColorTexture.texCoord;
 
         mat.pbr.metalness = pbr.metallicFactor;
         mat.pbr.roughness = pbr.roughnessFactor;
+        mat.pbr.hasMRTex = pbr.metallicRoughnessTexture.index > 0;
         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())
+        if ((mat.hasNormalTex    && (mat.normalTexIdx         >= mTextures.size())) ||
+            (mat.hasOcclusionTex && (mat.occlusionTexIdx      >= mTextures.size())) ||
+            (mat.hasEmissiveTex  && (mat.emissiveColorTexIdx  >= mTextures.size())) ||
+            (mat.pbr.hasBaseTex  && (mat.pbr.baseColorTexIdx  >= mTextures.size())) ||
+            (mat.pbr.hasMRTex    && (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)
+        if ((mat.hasNormalTex    && (mat.normalTexCoordIdx         > 2)) ||    // mesh can have up to 3 sets of UV
+            (mat.hasOcclusionTex && (mat.occlusionTexCoordIdx      > 2)) ||
+            (mat.hasEmissiveTex  && (mat.emissiveColorTexCoordIdx  > 2)) ||
+            (mat.pbr.hasBaseTex  && (mat.pbr.baseColorTexCoordIdx  > 2)) ||
+            (mat.pbr.hasMRTex    && (mat.pbr.metalRoughTexCoordIdx > 2)))
         {
             LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL;
             return false;
@@ -331,6 +336,7 @@ void LLGLTFLoader::uploadMeshes()
 // TODO: convert raw index buffers to UUIDs
 void LLGLTFLoader::uploadMaterials()
 {
-    llassert(0);
+    //llassert(0);
+
 }
 
diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h
index 9bffeef4ab1615cbbe5634538536fd809e60357f..08e9836d0729a65e2deae36af85e479e31dc6ae6 100644
--- a/indra/llprimitive/llgltfloader.h
+++ b/indra/llprimitive/llgltfloader.h
@@ -27,8 +27,9 @@
 #ifndef LL_LLGLTFLoader_H
 #define LL_LLGLTFLoader_H
 
-#include "tinygltf\tiny_gltf.h"
+#include "tinygltf/tiny_gltf.h"
 
+#include "llglheaders.h"
 #include "llmodelloader.h"
 
 typedef struct // gltf sampler
@@ -74,6 +75,8 @@ typedef struct  // gltf_pbrMR_material
 
     U32 metalRoughTexIdx;       // always linear, roughness in G channel, metalness in B channel
     U32 metalRoughTexCoordIdx;
+
+    bool    hasBaseTex, hasMRTex;
 } gltf_pbr;
 
 typedef struct // render material
@@ -100,6 +103,7 @@ typedef struct // render material
     // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry??
 
     bool        hasPBR;
+    bool        hasNormalTex, hasOcclusionTex, hasEmissiveTex;
     gltf_pbr    pbr;
 
 } gltf_render_material;