vlod пре 4 година
родитељ
комит
dbaea1005d
7 измењених фајлова са 616 додато и 298 уклоњено
  1. 0 1
      devUtils/shaders/geometryPass_optimized.vert
  2. 6 6
      gl3d/main.cpp
  3. 7 2
      gl3d/src/Animations.h
  4. 90 43
      gl3d/src/OBJ_Loader.h
  5. 107 85
      gl3d/src/gl3d.cpp
  6. 103 58
      headerOnly/gl3d.cpp
  7. 303 103
      headerOnly/gl3d.h

+ 0 - 1
devUtils/shaders/geometryPass_optimized.vert

@@ -28,7 +28,6 @@ void main()
 	vec4 totalLocalPos = vec4(0.f);
 	vec4 totalNorm = vec4(0.f);
 
-
 	if(u_hasAnimations != 0)
 	{
 		for(int i=0; i<4; i++)

+ 6 - 6
gl3d/main.cpp

@@ -400,17 +400,17 @@ int main()
 
 	//auto levelModel = renderer.loadModel("resources/donut/Donut.glb", 1.f);
 	//auto levelModel = renderer.loadModel("resources/mutant/Biomech_Mutant_Skin_1.gltf", 1.f);
-	auto barelModel = renderer.loadModel("resources/wine/wine_barrel_01_2k.gltf");
+	//auto barelModel = renderer.loadModel("resources/wine/wine_barrel_01_2k.gltf");
 	//auto rockModel = renderer.loadModel("resources/mutant/2/Biomech_Mutant_Skin_2.gltf", 1.f);
-	//auto rockModel = renderer.loadModel("resources/amogus.glb", 1.f);
-	auto rockModel = renderer.loadModel("resources/animatedModels/arrow.glb", 1.f);
+	auto rockModel = renderer.loadModel("resources/amogus.glb", 1.f);
+	//auto rockModel = renderer.loadModel("resources/animatedModels/arrow.glb", 1.f);
 	//auto rockModel = renderer.loadModel("resources/knight/uploads_files_1950170_Solus_the_knight.gltf", 1.f);
-	//auto sphereModel = renderer.loadModel("resources/obj/sphere.obj");
+	auto sphereModel = renderer.loadModel("resources/obj/sphere.obj");
 	//auto levelModel = renderer.loadModel("resources/sponza2/sponza.obj", 0.008);
-	auto sphereModel = renderer.loadModel("resources/katana/antique_katana_01_1k.gltf");
+	//auto sphereModel = renderer.loadModel("resources/katana/antique_katana_01_1k.gltf");
 	//auto rockModel = renderer.loadModel("resources/mutant/Biomech_Mutant_Skin_1.glb", 1.f);
 
-	//auto barelModel = renderer.loadModel("resources/barrel/Barrel_01.obj");
+	auto barelModel = renderer.loadModel("resources/barrel/Barrel_01.obj");
 	//auto rockModel = renderer.loadModel("resources/helmet/helmet.obj");
 	//auto rockModel = renderer.loadObject("resources/other/boulder.obj", 0.1);
 	//auto levelModel = renderer.loadModel("resources/city/city.obj", 0.01);

+ 7 - 2
gl3d/src/Animations.h

@@ -3,6 +3,7 @@
 #include <string>
 #include <glm/mat4x4.hpp>
 #include <glm/vec4.hpp>
+#include <glm/vec3.hpp>
 #include <vector>
 #include <glm/gtc/quaternion.hpp>
 #include <glm/gtx/quaternion.hpp>
@@ -17,9 +18,12 @@ namespace gl3d
 		glm::mat4 localBindTransform{1.f};
 		std::string name{};
 		std::vector<int> children;
+		glm::quat rotation{ 0.f,0.f,0.f,1.f };
+		glm::vec3 trans{ 1.f,1.f,1.f };
+		glm::vec3 scale{ 1.f,1.f,1.f };
+
 		//int index{};
-		int root = 0;
-		int used = 0;
+		//int root = 0;
 	};
 
 	struct KeyFrame
@@ -73,6 +77,7 @@ namespace gl3d
 
 		float animationDuration=0;
 		float totalTimePassed=0;
+		int root = 0;
 		//std::vector<float> timePassed;
 		//std::vector<std::vector<KeyFrame>> keyFrames;
 	};

+ 90 - 43
gl3d/src/OBJ_Loader.h

@@ -727,33 +727,48 @@ namespace objl
 
 		#pragma region bones
 
-			joints.resize(model.nodes.size());
 			//int indexCount = 0;
 			std::vector<int> isMain;
-			isMain.resize(model.nodes.size(), 0);
-
 			std::vector<int> skinJoints;
+			int skeletonRoot = 0;
 
-			if (!model.skins.empty())
+			auto convertNode = [&skinJoints](int index)
 			{
+				auto convertedNode = std::find(skinJoints.begin(), skinJoints.end(), index);
+				if (convertedNode == skinJoints.end())
+				{
+					return -1;
+				}
+				return convertedNode - skinJoints.begin();
+			};
 
+			if (!model.skins.empty())
+			{
 				auto skin = model.skins[0];
 
+				joints.resize(skin.joints.size());
+				isMain.resize(skin.joints.size(), 1);
+
+				skinJoints.reserve(skin.joints.size());
 				for (auto &j : skin.joints)
 				{
-					isMain[j] = 1;
+					skinJoints.push_back(j);
 				}
 
+				skeletonRoot = skin.skeleton;
+
 				for (auto &j : skin.joints)
 				{
 					auto &b = model.nodes[j];
-
-					skinJoints.push_back(j);
-
+					
 					gl3d::Joint joint;
-					joint.used = true;
-					//joint.index = j;
-					joint.children = b.children;
+					
+					joint.children.reserve(b.children.size());
+					for (int i = 0; i < b.children.size(); i++) 
+					{
+						joint.children.push_back(convertNode(b.children[i]));
+					}
+
 				
 					for (auto &c : joint.children)
 					{
@@ -776,38 +791,57 @@ namespace objl
 						rot.w = b.rotation[3];
 				
 						rotation = glm::toMat4(rot);
+						joint.rotation = rot;
 					}
 				
 					//suppose 3 component translation
 					if (!b.translation.empty())
 					{
-						translation = glm::translate(glm::vec3((float)b.translation[0], (float)b.translation[1], (float)b.translation[2]));
+						glm::vec3 trans;
+						trans.x = b.translation[0];
+						trans.y = b.translation[1];
+						trans.z = b.translation[2];
+
+						translation = glm::translate(trans);
+						joint.trans = trans;
 					}
 				
 					//suppose 3 component scale
 					if (!b.scale.empty())
 					{
-						scale = glm::scale(glm::vec3((float)b.scale[0], (float)b.scale[1], (float)b.scale[2]));
+						glm::vec3 s;
+						s.x = b.scale[0];
+						s.y = b.scale[1];
+						s.z = b.scale[2];
+
+						scale = glm::scale(s);
+						joint.scale = s;
 					}
 				
 					joint.localBindTransform = translation * rotation * scale;
-				
-					joints[j] = std::move(joint);
+
+					joints[convertNode(j)] = std::move(joint);
 				}
 
-				for (int i = 0; i < isMain.size(); i++)
+				if (skeletonRoot < 0) 
 				{
-					if (isMain[i] == 1) 
+					for (int i = 0; i < isMain.size(); i++)
 					{
-						joints[i].root = true;
-						calculateInverseBindTransform(i, glm::mat4(1.f), joints);
-					};
+						if (isMain[i] == 1)
+						{
+							skeletonRoot = i;
+							calculateInverseBindTransform(i, glm::mat4(1.f), joints);
+							break;
+						};
+					}
+				}
+				else 
+				{
+					calculateInverseBindTransform(skeletonRoot, glm::mat4(1.f), joints);
 				}
-
 
 			}
 
-
 			//for (auto &b : model.nodes)
 			//{
 			//	gl3d::Joint joint;
@@ -871,11 +905,13 @@ namespace objl
 		#pragma region animations
 			
 			animations.reserve(model.animations.size());
+			std::cout << model.animations.size() << " :size\n";
 			for (auto &a : model.animations)
 			{
 				gl3d::Animation animation;
 				animation.name = a.name;
-				
+				animation.root = skeletonRoot;
+
 			#pragma region set key frames a default value
 
 				animation.keyFramesRot.resize(joints.size()); //each joint will potentially have keyframes
@@ -883,23 +919,26 @@ namespace objl
 				animation.keyFramesScale.resize(joints.size()); //each joint will potentially have keyframes
 				animation.timeStamps.resize(joints.size());
 				//animation.timePassed.resize(joints.size());
-
 				//animation.keyFrames.resize(joints.size());
 
 			#pragma endregion
 
-				for (int i = 0; i < a.channels.size(); i++) 
+				for (int i = 0; i < a.channels.size(); i++)
 				{
 					auto &channel = a.channels[i];
 					auto &sampler = a.samplers[channel.sampler];
 
-					int node = channel.target_node;
+					int node = convertNode(channel.target_node);
+					if (node == -1)
+					{
+						//std::cout << channel.target_path <<" : " << i <<"\n";
+						continue;
+					}
+
 					int type = 0; //translation rotation scale
 
 					std::vector<float> timeStamps;
 					{
-						auto &channel = a.channels[i];
-						auto &sampler = a.samplers[channel.sampler];
 						tinygltf::Accessor &accessor = model.accessors[sampler.input];
 						tinygltf::BufferView &bufferView = model.bufferViews[accessor.bufferView];
 						tinygltf::Buffer &buffer = model.buffers[bufferView.buffer];
@@ -936,6 +975,8 @@ namespace objl
 							float *translation = (float *)
 								(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
 
+							gl3dAssert(accessor.count == timeStamps.size());
+
 							move.x = translation[t * 3 + 0];
 							move.y = translation[t * 3 + 1];
 							move.z = translation[t * 3 + 2];
@@ -958,13 +999,14 @@ namespace objl
 							float *rotation = (float *)
 								(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
 
-							accessor.count;
+							gl3dAssert(accessor.count == timeStamps.size());
 
 							rot.x = rotation[t * 4 + 0];
 							rot.y = rotation[t * 4 + 1];
 							rot.z = rotation[t * 4 + 2];
 							rot.w = rotation[t * 4 + 3];
 
+
 							animation.keyFramesRot[node][t].timeStamp = timeStamps[t];
 							animation.keyFramesRot[node][t].rotation = rot;
 						}
@@ -984,7 +1026,7 @@ namespace objl
 							float *scaleBuffer = (float *)
 								(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
 
-							accessor.count;
+							gl3dAssert(accessor.count == timeStamps.size());
 
 							scale.x = scaleBuffer[t * 3 + 0];
 							scale.y = scaleBuffer[t * 3 + 1];
@@ -994,8 +1036,14 @@ namespace objl
 							animation.keyFramesScale[node][t].scale = scale;
 						}
 					}
+					else if (channel.target_path == "weights") 
+					{
+						gl3dAssertComment(0, "weights are supported");
+					}
 					else 
 					{
+						std::cout << channel.target_path << "\n";
+						gl3dAssertComment(0, "unknow animation target");
 						continue;
 					}
 				}
@@ -1093,7 +1141,6 @@ namespace objl
 
 
 		#pragma endregion
-
 		
 		#pragma region meshes
 
@@ -1238,18 +1285,18 @@ namespace objl
 									}
 								}
 
-								for (int j = 0; j < 4; j++) 
-								{
-									if (jointsIndex[j] == -1)
-									{
-										break;
-									}
-									else
-									{
-										jointsIndex[j] = skinJoints[jointsIndex[j]]; 
-									}
-
-								}
+								//for (int j = 0; j < 4; j++) 
+								//{
+								//	if (jointsIndex[j] == -1)
+								//	{
+								//		break;
+								//	}
+								//	else
+								//	{
+								//		jointsIndex[j] = skinJoints[jointsIndex[j]]; 
+								//	}
+								//
+								//}
 
 								if (componentCount > 4)
 								{

+ 107 - 85
gl3d/src/gl3d.cpp

@@ -482,11 +482,9 @@ namespace gl3d
 		ModelData returnModel;
 		{
 
-
 			int s = model.loader.LoadedMeshes.size();
 			returnModel.models.reserve(s);
 
-
 			returnModel.createdMaterials.reserve(model.loader.LoadedMaterials.size());
 			for(int i=0;i<model.loader.LoadedMaterials.size(); i++)
 			{
@@ -845,7 +843,6 @@ namespace gl3d
 
 							}
 						}
-					
 
 						/*
 						
@@ -902,7 +899,6 @@ namespace gl3d
 					}
 				}
 
-				
 				if (!model.loader.animations.empty())
 				{
 					gm.animation = model.loader.animations[0];
@@ -913,7 +909,6 @@ namespace gl3d
 					gm.joints = model.loader.joints;
 				}
 
-				
 
 				if(model.loader.LoadedMeshes[index].materialIndex > -1)
 				{
@@ -3620,7 +3615,6 @@ namespace gl3d
 			glUniformMatrix4fv(internal.lightShader.u_modelTransform, 1, GL_FALSE, &transformMat[0][0]);
 			glUniformMatrix4fv(internal.lightShader.u_motelViewTransform, 1, GL_FALSE, &(worldToViewMatrix * transformMat)[0][0]);
 			
-			
 			bool changed = 1;
 
 			for (auto& i : entity.models)
@@ -3647,7 +3641,7 @@ namespace gl3d
 					std::vector<glm::mat4> skinningMatrixes;
 					skinningMatrixes.resize(i.joints.size(), glm::mat4(1.f));
 
-					i.animation.totalTimePassed += deltaTime;
+					i.animation.totalTimePassed += deltaTime*0.2;
 					while (i.animation.totalTimePassed >= i.animation.animationDuration)
 					{
 						i.animation.totalTimePassed -= i.animation.animationDuration;
@@ -3655,105 +3649,130 @@ namespace gl3d
 
 					for (int b = 0; b < i.joints.size(); b++)
 					{
+
 						glm::mat4 rotMat(1.f);
 						glm::mat4 transMat(1.f);
 						glm::mat4 scaleMat(1.f);
 						
-						if (!i.animation.keyFramesRot[b].empty()) //no key frames for this bone...
-						{
+						auto &joint = i.joints[b];
 
-							for (int frame = i.animation.keyFramesRot[b].size()-1; frame >= 0; frame--)
+						if(
+							i.animation.keyFramesRot[b].empty() &&
+							i.animation.keyFramesTrans[b].empty() &&
+							i.animation.keyFramesScale[b].empty()
+							)
+						{
+							skinningMatrixes[b] = i.joints[b].localBindTransform; //no animations at all here
+						}
+						else
+						{
+							if (!i.animation.keyFramesRot[b].empty()) //no key frames for this bone...
 							{
-								int frames = i.animation.keyFramesRot[b].size();
-								float time = i.animation.totalTimePassed;
-								auto &currentFrame = i.animation.keyFramesRot[b][frame];
-								if (time >= currentFrame.timeStamp)
+								for (int frame = i.animation.keyFramesRot[b].size() - 1; frame >= 0; frame--)
 								{
-									auto first = currentFrame.rotation;
-
-									if (frame == i.animation.keyFramesRot[b].size() - 1)
-									{
-										rotMat = glm::toMat4(first);
-									}
-									else
+									int frames = i.animation.keyFramesRot[b].size();
+									float time = i.animation.totalTimePassed;
+									auto &currentFrame = i.animation.keyFramesRot[b][frame];
+									if (time >= currentFrame.timeStamp)
 									{
-										auto second = i.animation.keyFramesRot[b][frame + 1].rotation;
-										float secondTime = i.animation.keyFramesRot[b][frame + 1].timeStamp;
-										float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
-										rotMat = glm::toMat4(glm::slerp(first, second, interpolation));
+										auto first = currentFrame.rotation;
+
+										if (frame == i.animation.keyFramesRot[b].size() - 1)
+										{
+											rotMat = glm::toMat4(first);
+										}
+										else
+										{
+											auto second = i.animation.keyFramesRot[b][frame + 1].rotation;
+											float secondTime = i.animation.keyFramesRot[b][frame + 1].timeStamp;
+											float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
+											rotMat = glm::toMat4(glm::slerp(first, second, interpolation));
+										}
+										break;
+
 									}
-									break;
 
 								}
-
+								//rotMat = glm::toMat4(i.animation.keyFramesRot[b][0].rotation);
+							}
+							else
+							{
+								rotMat = glm::toMat4(joint.rotation);
 							}
-							//rotMat = glm::toMat4(i.animation.keyFramesRot[b][0].rotation);
-						}
 
-						auto lerp = [](glm::vec3 a, glm::vec3 b, float x) -> glm::vec3
-						{
-							return a *(1.f - x) + (b * x);
-						};
+							auto lerp = [](glm::vec3 a, glm::vec3 b, float x) -> glm::vec3
+							{
+								return a * (1.f - x) + (b * x);
+							};
 
-						if (!i.animation.keyFramesTrans[b].empty()) //no key frames for this bone...
-						{
-							for (int frame = i.animation.keyFramesTrans[b].size() - 1; frame >= 0; frame--)
+							if (!i.animation.keyFramesTrans[b].empty()) //no key frames for this bone...
 							{
-								int frames = i.animation.keyFramesTrans[b].size();
-								float time = i.animation.totalTimePassed;
-								auto &currentFrame = i.animation.keyFramesTrans[b][frame];
-								if (time >= currentFrame.timeStamp)
+								for (int frame = i.animation.keyFramesTrans[b].size() - 1; frame >= 0; frame--)
 								{
-									auto first = currentFrame.translation;
-
-									if (frame == i.animation.keyFramesTrans[b].size() - 1)
+									int frames = i.animation.keyFramesTrans[b].size();
+									float time = i.animation.totalTimePassed;
+									auto &currentFrame = i.animation.keyFramesTrans[b][frame];
+									if (time >= currentFrame.timeStamp)
 									{
-										transMat = glm::translate(first);
-									}
-									else
-									{
-										auto second = i.animation.keyFramesTrans[b][frame + 1].translation;
-										float secondTime = i.animation.keyFramesTrans[b][frame + 1].timeStamp;
-										float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
-										transMat = glm::translate(lerp(first, second, interpolation));
+										auto first = currentFrame.translation;
+
+										if (frame == i.animation.keyFramesTrans[b].size() - 1)
+										{
+											transMat = glm::translate(first);
+										}
+										else
+										{
+											auto second = i.animation.keyFramesTrans[b][frame + 1].translation;
+											float secondTime = i.animation.keyFramesTrans[b][frame + 1].timeStamp;
+											float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
+											transMat = glm::translate(lerp(first, second, interpolation));
+										}
+										break;
 									}
-									break;
 								}
+								//transMat = glm::translate(i.animation.keyFramesTrans[b][0].translation);
+							}
+							else
+							{
+								transMat = glm::translate(joint.trans);
 							}
-							//transMat = glm::translate(i.animation.keyFramesTrans[b][0].translation);
-						}
 
-						if (!i.animation.keyFramesScale[b].empty()) //no key frames for this bone...
-						{
-							for (int frame = i.animation.keyFramesScale[b].size() - 1; frame >= 0; frame--)
+							if (!i.animation.keyFramesScale[b].empty()) //no key frames for this bone...
 							{
-								int frames = i.animation.keyFramesScale[b].size();
-								float time = i.animation.totalTimePassed;
-								auto &currentFrame = i.animation.keyFramesScale[b][frame];
-								if (time >= currentFrame.timeStamp)
+								for (int frame = i.animation.keyFramesScale[b].size() - 1; frame >= 0; frame--)
 								{
-									auto first = currentFrame.scale;
-
-									if (frame == i.animation.keyFramesScale[b].size() - 1)
-									{
-										scaleMat = glm::translate(first);
-									}
-									else
+									int frames = i.animation.keyFramesScale[b].size();
+									float time = i.animation.totalTimePassed;
+									auto &currentFrame = i.animation.keyFramesScale[b][frame];
+									if (time >= currentFrame.timeStamp)
 									{
-										auto second = i.animation.keyFramesScale[b][frame + 1].scale;
-										float secondTime = i.animation.keyFramesScale[b][frame + 1].timeStamp;
-										float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
-										scaleMat = glm::scale(lerp(first, second, interpolation));
+										auto first = currentFrame.scale;
+
+										if (frame == i.animation.keyFramesScale[b].size() - 1)
+										{
+											scaleMat = glm::translate(first);
+										}
+										else
+										{
+											auto second = i.animation.keyFramesScale[b][frame + 1].scale;
+											float secondTime = i.animation.keyFramesScale[b][frame + 1].timeStamp;
+											float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
+											scaleMat = glm::scale(lerp(first, second, interpolation));
+										}
+										break;
 									}
-									break;
 								}
+								//scaleMat = glm::scale(i.animation.keyFramesScale[b][0].scale);
+							}
+							else
+							{
+								scaleMat = glm::scale(joint.scale);
 							}
-							//scaleMat = glm::scale(i.animation.keyFramesScale[b][0].scale);
-						}
 
-						skinningMatrixes[b] = transMat * rotMat * scaleMat;
+							skinningMatrixes[b] = transMat * rotMat * scaleMat;
+							//skinningMatrixes[b] = i.joints[b].localBindTransform; //no animations
 
-						//skinningMatrixes[b] = i.joints[b].localBindTransform;
+						}
 
 					}
 
@@ -3762,14 +3781,17 @@ namespace gl3d
 					std::vector<glm::mat4> appliedSkinningMatrixes;
 					appliedSkinningMatrixes.resize(i.joints.size(), glm::mat4(1.f));
 
-					for (int j = 0; j < i.joints.size(); j++)
-					{
-						if (i.joints[j].root)
-						{
-							applyPoseToJoints(skinningMatrixes, appliedSkinningMatrixes, i.joints,
-								j, glm::mat4(1.f));
-						}
-					}
+					//for (int j = 0; j < i.joints.size(); j++)
+					//{
+					//	if (i.joints[j].root)
+					//	{
+					//		applyPoseToJoints(skinningMatrixes, appliedSkinningMatrixes, i.joints,
+					//			j, glm::mat4(1.f));
+					//	}
+					//}
+
+					applyPoseToJoints(skinningMatrixes, appliedSkinningMatrixes, i.joints,
+						i.animation.root, glm::mat4(1.f));
 
 
 					//send data

+ 103 - 58
headerOnly/gl3d.cpp

@@ -1,6 +1,6 @@
 ////////////////////////////////////////////////
 //gl32 --Vlad Luta -- 
-//built on 2021-09-13
+//built on 2021-09-15
 ////////////////////////////////////////////////
 
 #include "gl3d.h"
@@ -38130,8 +38130,8 @@ namespace gl3d
 		glm::mat4 parentTransform
 	)
 	{
-		auto currentTransform = skinningMatrixes[index];
-		auto worldSpaceTransform = parentTransform * currentTransform;
+		auto currentLocalTransform = skinningMatrixes[index];
+		auto worldSpaceTransform = parentTransform * currentLocalTransform;
 
 		auto &j = joints[index];
 		for (auto &c : j.children)
@@ -38140,6 +38140,7 @@ namespace gl3d
 		}
 
 		appliedSkinningMatrixes[index] = worldSpaceTransform * j.inverseBindTransform;
+		//appliedSkinningMatrixes[index] = glm::mat4(1.f);
 
 	};
 
@@ -39069,92 +39070,137 @@ namespace gl3d
 
 				glUniform1i(internal.lightShader.materialIndexLocation, materialId);
 
-				if (!i.joints.empty())
+				#pragma region animations
+				if (!i.joints.empty() && !i.animation.keyFramesRot.empty())
 				{
 					glUniform1i(internal.lightShader.u_hasAnimations, true);
 					std::vector<glm::mat4> skinningMatrixes;
 					skinningMatrixes.resize(i.joints.size(), glm::mat4(1.f));
 
+					i.animation.totalTimePassed += deltaTime;
+					while (i.animation.totalTimePassed >= i.animation.animationDuration)
+					{
+						i.animation.totalTimePassed -= i.animation.animationDuration;
+					}
+
 					for (int b = 0; b < i.joints.size(); b++)
 					{
+
 						glm::mat4 rotMat(1.f);
 						glm::mat4 transMat(1.f);
+						glm::mat4 scaleMat(1.f);
 						
-						glm::vec3 scale;
-						glm::vec3 trans;
-
-						i.animation.timeStamps[b].passedTimeTrans += deltaTime;
-						i.animation.timeStamps[b].passedTimeScale += deltaTime;
-
-						
-						if (!i.animation.keyFramesRot[b].empty()) //no key frames for this bone...
+						if(
+							i.animation.keyFramesRot[b].empty() &&
+							i.animation.keyFramesTrans[b].empty() &&
+							i.animation.keyFramesScale[b].empty()
+							)
 						{
-							i.animation.timeStamps[b].passedTimeRot += deltaTime;
-
-							while (i.animation.timeStamps[b].passedTimeRot >= i.animation.keyFramesRot[b].back().timeStemp)
-							{
-								i.animation.timeStamps[b].passedTimeRot -= i.animation.keyFramesRot[b].back().timeStemp;
-							}
-
-
-							for (int frame = i.animation.keyFramesRot[b].size()-1; frame >= 0; frame--)
+							skinningMatrixes[b] = i.joints[b].localBindTransform; //no animations at all here
+						}
+						else
+						{
+							if (!i.animation.keyFramesRot[b].empty()) //no key frames for this bone...
 							{
-								int frames = i.animation.keyFramesRot[b].size();
-								float time = i.animation.timeStamps[b].passedTimeRot;
-								auto &currentFrame = i.animation.keyFramesRot[b][frame];
-								if (time >= currentFrame.timeStemp)
+								for (int frame = i.animation.keyFramesRot[b].size() - 1; frame >= 0; frame--)
 								{
-									auto first = currentFrame.rotation;
-									auto second = i.animation.keyFramesRot[b][frame + 1].rotation;
+									int frames = i.animation.keyFramesRot[b].size();
+									float time = i.animation.totalTimePassed;
+									auto &currentFrame = i.animation.keyFramesRot[b][frame];
+									if (time >= currentFrame.timeStamp)
+									{
+										auto first = currentFrame.rotation;
 
-									float secondTime = i.animation.keyFramesRot[b][frame + 1].timeStemp;
-									float interpolation = (time - currentFrame.timeStemp) / (secondTime - currentFrame.timeStemp);
-								
-									rotMat = glm::toMat4(glm::slerp(first, second, interpolation));
-									break;
+										if (frame == i.animation.keyFramesRot[b].size() - 1)
+										{
+											rotMat = glm::toMat4(first);
+										}
+										else
+										{
+											auto second = i.animation.keyFramesRot[b][frame + 1].rotation;
+											float secondTime = i.animation.keyFramesRot[b][frame + 1].timeStamp;
+											float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
+											rotMat = glm::toMat4(glm::slerp(first, second, interpolation));
+										}
+										break;
 
-								}
+									}
 
+								}
+								//rotMat = glm::toMat4(i.animation.keyFramesRot[b][0].rotation);
 							}
 
-						}
-
-						if (!i.animation.keyFramesTrans[b].empty()) //no key frames for this bone...
-						{
-							i.animation.timeStamps[b].passedTimeTrans += deltaTime;
-
-							while (i.animation.timeStamps[b].passedTimeTrans >= i.animation.keyFramesTrans[b].back().timeStemp)
+							auto lerp = [](glm::vec3 a, glm::vec3 b, float x) -> glm::vec3
 							{
-								i.animation.timeStamps[b].passedTimeTrans -= i.animation.keyFramesTrans[b].back().timeStemp;
-							}
+								return a * (1.f - x) + (b * x);
+							};
 
-
-							for (int frame = i.animation.keyFramesTrans[b].size() - 1; frame >= 0; frame--)
+							if (!i.animation.keyFramesTrans[b].empty()) //no key frames for this bone...
 							{
-								int frames = i.animation.keyFramesTrans[b].size();
-								float time = i.animation.timeStamps[b].passedTimeTrans;
-								auto &currentFrame = i.animation.keyFramesTrans[b][frame];
-								if (time >= currentFrame.timeStemp)
+								for (int frame = i.animation.keyFramesTrans[b].size() - 1; frame >= 0; frame--)
 								{
-									auto first = currentFrame.translation;
-									auto second = i.animation.keyFramesTrans[b][frame + 1].translation;
+									int frames = i.animation.keyFramesTrans[b].size();
+									float time = i.animation.totalTimePassed;
+									auto &currentFrame = i.animation.keyFramesTrans[b][frame];
+									if (time >= currentFrame.timeStamp)
+									{
+										auto first = currentFrame.translation;
 
-									float secondTime = i.animation.keyFramesTrans[b][frame + 1].timeStemp;
-									float interpolation = (time - currentFrame.timeStemp) / (secondTime - currentFrame.timeStemp);
+										if (frame == i.animation.keyFramesTrans[b].size() - 1)
+										{
+											transMat = glm::translate(first);
+										}
+										else
+										{
+											auto second = i.animation.keyFramesTrans[b][frame + 1].translation;
+											float secondTime = i.animation.keyFramesTrans[b][frame + 1].timeStamp;
+											float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
+											transMat = glm::translate(lerp(first, second, interpolation));
+										}
+										break;
+									}
+								}
+								//transMat = glm::translate(i.animation.keyFramesTrans[b][0].translation);
+							}
 
-									glm::lerp(first, second, interpolation);
-									break;
+							if (!i.animation.keyFramesScale[b].empty()) //no key frames for this bone...
+							{
+								for (int frame = i.animation.keyFramesScale[b].size() - 1; frame >= 0; frame--)
+								{
+									int frames = i.animation.keyFramesScale[b].size();
+									float time = i.animation.totalTimePassed;
+									auto &currentFrame = i.animation.keyFramesScale[b][frame];
+									if (time >= currentFrame.timeStamp)
+									{
+										auto first = currentFrame.scale;
 
+										if (frame == i.animation.keyFramesScale[b].size() - 1)
+										{
+											scaleMat = glm::translate(first);
+										}
+										else
+										{
+											auto second = i.animation.keyFramesScale[b][frame + 1].scale;
+											float secondTime = i.animation.keyFramesScale[b][frame + 1].timeStamp;
+											float interpolation = (time - currentFrame.timeStamp) / (secondTime - currentFrame.timeStamp);
+											scaleMat = glm::scale(lerp(first, second, interpolation));
+										}
+										break;
+									}
 								}
-
+								//scaleMat = glm::scale(i.animation.keyFramesScale[b][0].scale);
 							}
 
+							skinningMatrixes[b] = transMat * rotMat * scaleMat;
+							//skinningMatrixes[b] = i.joints[b].localBindTransform; //no animations
+
 						}
 
 
-						skinningMatrixes[b] = moveMat;
 					}
 
+					//skinningMatrixes[4] = glm::translate(glm::vec3{ -2,0.2,0 });
+
 					std::vector<glm::mat4> appliedSkinningMatrixes;
 					appliedSkinningMatrixes.resize(i.joints.size(), glm::mat4(1.f));
 
@@ -39176,10 +39222,9 @@ namespace gl3d
 				}
 				else
 				{
-
 					glUniform1i(internal.lightShader.u_hasAnimations, false);
-
 				}
+				#pragma endregion
 
 
 				TextureDataForMaterial textureData = internal.materialTexturesData[materialId];

+ 303 - 103
headerOnly/gl3d.h

@@ -1,6 +1,6 @@
 ////////////////////////////////////////////////
 //gl32 --Vlad Luta -- 
-//built on 2021-09-13
+//built on 2021-09-15
 ////////////////////////////////////////////////
 
 
@@ -31308,6 +31308,8 @@ namespace tinygltf
 
 // Vector - STD Vector/Array Library
 #include <vector>
+#include <unordered_set>
+#include <algorithm>
 
 // String - STD String Library
 #include <string>
@@ -31942,22 +31944,25 @@ namespace objl
 					return "";
 				};
 
-				auto setTexture = [&](int index, LoadedTexture *t, bool checkData)->std::string
+				auto setTexture = [&](int index, LoadedTexture *t, bool checkData)
 				{
 					if (index != -1)
 					{
+						auto &texture = model.textures[index];
+						auto &image = model.images[texture.source];
+
 						if (t)
 						{
 							if (checkData)
 							{
 								bool isData = false;
-								t->data.resize(4 * model.images[index].width * model.images[index].height);
-								for (int i = 0; i < model.images[index].width * model.images[index].height; i++)
+								t->data.resize(4 * image.width * image.height);
+								for (int i = 0; i < image.width * image.height; i++)
 								{
-									auto r = model.images[index].image[i * 4 + 0];
-									auto g = model.images[index].image[i * 4 + 1];
-									auto b = model.images[index].image[i * 4 + 2];
-									auto a = model.images[index].image[i * 4 + 3];
+									auto r = image.image[i * 4 + 0];
+									auto g = image.image[i * 4 + 1];
+									auto b = image.image[i * 4 + 2];
+									auto a = image.image[i * 4 + 3];
 
 									if (r != 0 || g != 0 || b != 0) { isData = true; }
 
@@ -31970,9 +31975,9 @@ namespace objl
 
 								if (isData)
 								{
-									t->w = model.images[index].width;
-									t->h = model.images[index].height;
-									t->components = model.images[index].component; //todo check component
+									t->w = image.width;
+									t->h = image.height;
+									t->components = image.component; //todo check component
 								}
 								else
 								{
@@ -31981,52 +31986,35 @@ namespace objl
 							}
 							else
 							{
-								t->w = model.images[index].width;
-								t->h = model.images[index].height;
-								t->components = model.images[index].component; //todo check component
-								t->data = model.images[index].image; //
+								t->w = image.width;
+								t->h = image.height;
+								t->components = image.component; //todo check component
+								t->data = image.image; //
 							}
 
 						}
-
-						//if (model.images[index].uri.empty())
-						//{
-						//	//std::string ret = model.images[index].name;
-						//	//ret += "." + MimeToExt(model.images[index].mimeType);
-						//	//return ret;
-						//	return "";
-						//}
-						//else 
-						//{
-						//	//std::string ret = 
-						//	//	std::string(model.images[index].uri.begin()+2, model.images[index].uri.end());
-						//	//return ret;
-						//	return "";
-						//}
-						return "";
-
-					}
-					else
-					{
-						return std::string();
 					}
 
 				};
 
 
-				LoadedMaterials[i].map_Kd = setTexture(mat.pbrMetallicRoughness.baseColorTexture.index,
+				//LoadedMaterials[i].map_Kd
+				setTexture(mat.pbrMetallicRoughness.baseColorTexture.index,
 					&LoadedMaterials[i].loadedDiffuse, false);
 
-				LoadedMaterials[i].map_Kn = setTexture(mat.normalTexture.index,
+				//LoadedMaterials[i].map_Kn
+				setTexture(mat.normalTexture.index,
 					&LoadedMaterials[i].loadedNormal, false);
 
-				LoadedMaterials[i].map_emissive = setTexture(mat.emissiveTexture.index,
+				//LoadedMaterials[i].map_emissive
+				setTexture(mat.emissiveTexture.index,
 					&LoadedMaterials[i].loadedEmissive, false);
 
 				//LoadedMaterials[i].map_Ka = setTexture(mat.occlusionTexture.index);
 				//LoadedMaterials[i].map_Pr = setTexture(mat.pbrMetallicRoughness.metallicRoughnessTexture.index);
 				//LoadedMaterials[i].map_Pm = setTexture(mat.pbrMetallicRoughness.metallicRoughnessTexture.index);
-				LoadedMaterials[i].map_ORM = setTexture(mat.pbrMetallicRoughness.metallicRoughnessTexture.index,
+				//LoadedMaterials[i].map_ORM
+				setTexture(mat.pbrMetallicRoughness.metallicRoughnessTexture.index,
 					&LoadedMaterials[i].loadedORM, true);
 
 
@@ -32036,70 +32024,160 @@ namespace objl
 
 		#pragma region bones
 
-			joints.reserve(model.nodes.size());
-			int indexCount = 0;
+			//int indexCount = 0;
 			std::vector<int> isMain;
-			isMain.resize(model.nodes.size(), 1);
+			std::vector<int> skinJoints;
 
-			for (auto &b : model.nodes)
+			auto convertNode = [&skinJoints](int index)
 			{
-				gl3d::Joint joint;
-
-				joint.index = indexCount;
-				joint.children = b.children;
-
-				for (auto &c : joint.children)
+				auto convertedNode = std::find(skinJoints.begin(), skinJoints.end(), index);
+				if (convertedNode == skinJoints.end())
 				{
-					isMain[c] = 0;
+					return -1;
 				}
+				return convertedNode - skinJoints.begin();
+			};
 
-				joint.name = b.name;
-
-				glm::mat4 rotation(1.f);
-				glm::mat4 scale(1.f);
-				glm::mat4 translation(1.f);
+			if (!model.skins.empty())
+			{
+				auto skin = model.skins[0];
 
-				//suppose 4 component quaternion
-				if (!b.rotation.empty())
-				{
-					glm::quat rot;
-					rot.x = b.rotation[0];
-					rot.y = b.rotation[1];
-					rot.z = b.rotation[2];
-					rot.w = b.rotation[3];
+				//joints.resize(model.nodes.size());
+				//isMain.resize(model.nodes.size(), 0);
 
-					rotation = glm::toMat4(rot);
-				}
+				joints.resize(skin.joints.size());
+				isMain.resize(skin.joints.size(), 1);
 
-				//suppose 3 component translation
-				if (!b.translation.empty())
+				skinJoints.reserve(skin.joints.size());
+				for (auto &j : skin.joints)
 				{
-					translation = glm::translate(glm::vec3((float)b.translation[0], (float)b.translation[1], (float)b.translation[2]));
+					skinJoints.push_back(j);
 				}
 
-				//suppose 3 component scale
-				if (!b.scale.empty())
+
+				for (auto &j : skin.joints)
 				{
-					scale = glm::scale(glm::vec3((float)b.scale[0], (float)b.scale[1], (float)b.scale[2]));
-				}
+					auto &b = model.nodes[j];
 
+					gl3d::Joint joint;
+					//joint.index = j;
+					
+					joint.children.reserve(b.children.size());
+					for (int i = 0; i < b.children.size(); i++) 
+					{
+						joint.children.push_back(convertNode(b.children[i]));
+					}
 
-				joint.localBindTransform = translation * rotation * scale;
-				//joint.inverseBindTransform =  glm::inverse(joint.inverseBindTransform);
+					//joint.children = b.children;
+				
+					for (auto &c : joint.children)
+					{
+						isMain[c] = 0;
+					}
+				
+					joint.name = b.name;
+				
+					glm::mat4 rotation(1.f);
+					glm::mat4 scale(1.f);
+					glm::mat4 translation(1.f);
+				
+					//suppose 4 component quaternion
+					if (!b.rotation.empty())
+					{
+						glm::quat rot;
+						rot.x = b.rotation[0];
+						rot.y = b.rotation[1];
+						rot.z = b.rotation[2];
+						rot.w = b.rotation[3];
+				
+						rotation = glm::toMat4(rot);
+					}
+				
+					//suppose 3 component translation
+					if (!b.translation.empty())
+					{
+						translation = glm::translate(glm::vec3((float)b.translation[0], (float)b.translation[1], (float)b.translation[2]));
+					}
+				
+					//suppose 3 component scale
+					if (!b.scale.empty())
+					{
+						scale = glm::scale(glm::vec3((float)b.scale[0], (float)b.scale[1], (float)b.scale[2]));
+					}
+				
+					joint.localBindTransform = translation * rotation * scale;
 
-				joints.push_back(std::move(joint));
-			}
+					joints[convertNode(j)] = std::move(joint);
+				}
 
-			for (int i = 0; i < isMain.size(); i++)
-			{
-				if (isMain[i] == 1) 
+				for (int i = 0; i < isMain.size(); i++)
 				{
-					joints[i].root = true;
-					calculateInverseBindTransform(i, glm::mat4(1.f), joints);
-				};
+					if (isMain[i] == 1) 
+					{
+						joints[i].root = true;
+						calculateInverseBindTransform(i, glm::mat4(1.f), joints);
+					};
+				}
+
 			}
 
-			//todo calculate the proper invers bind local transform?
+			//for (auto &b : model.nodes)
+			//{
+			//	gl3d::Joint joint;
+			//
+			//	joint.index = indexCount;
+			//	joint.children = b.children;
+			//
+			//	for (auto &c : joint.children)
+			//	{
+			//		isMain[c] = 0;
+			//	}
+			//
+			//	joint.name = b.name;
+			//
+			//	glm::mat4 rotation(1.f);
+			//	glm::mat4 scale(1.f);
+			//	glm::mat4 translation(1.f);
+			//
+			//	//suppose 4 component quaternion
+			//	if (!b.rotation.empty())
+			//	{
+			//		glm::quat rot;
+			//		rot.x = b.rotation[0];
+			//		rot.y = b.rotation[1];
+			//		rot.z = b.rotation[2];
+			//		rot.w = b.rotation[3];
+			//
+			//		rotation = glm::toMat4(rot);
+			//	}
+			//
+			//	//suppose 3 component translation
+			//	if (!b.translation.empty())
+			//	{
+			//		translation = glm::translate(glm::vec3((float)b.translation[0], (float)b.translation[1], (float)b.translation[2]));
+			//	}
+			//
+			//	//suppose 3 component scale
+			//	if (!b.scale.empty())
+			//	{
+			//		scale = glm::scale(glm::vec3((float)b.scale[0], (float)b.scale[1], (float)b.scale[2]));
+			//	}
+			//
+			//	joint.localBindTransform = translation * rotation * scale;
+			//	//joint.inverseBindTransform =  glm::inverse(joint.inverseBindTransform);
+			//
+			//	joints.push_back(std::move(joint));
+			//}
+			//
+			//for (int i = 0; i < isMain.size(); i++)
+			//{
+			//	if (isMain[i] == 1) 
+			//	{
+			//		joints[i].root = true;
+			//		calculateInverseBindTransform(i, glm::mat4(1.f), joints);
+			//	};
+			//}
+
 
 		#pragma endregion
 
@@ -32110,7 +32188,6 @@ namespace objl
 			{
 				gl3d::Animation animation;
 				animation.name = a.name;
-				
 
 			#pragma region set key frames a default value
 
@@ -32118,19 +32195,22 @@ namespace objl
 				animation.keyFramesTrans.resize(joints.size()); //each joint will potentially have keyframes
 				animation.keyFramesScale.resize(joints.size()); //each joint will potentially have keyframes
 				animation.timeStamps.resize(joints.size());
+				//animation.timePassed.resize(joints.size());
+				//animation.keyFrames.resize(joints.size());
 
 			#pragma endregion
 
-
-				for (int i = 0; i < a.channels.size(); i++) 
+				for (int i = 0; i < a.channels.size(); i++)
 				{
 					auto &channel = a.channels[i];
 					auto &sampler = a.samplers[channel.sampler];
 
-					int node = channel.target_node;
+					//int node = channel.target_node;
+					int node = convertNode(channel.target_node);
+					if (node == -1) { continue; }
+
 					int type = 0; //translation rotation scale
 
-					
 					std::vector<float> timeStamps;
 					{
 						auto &channel = a.channels[i];
@@ -32148,6 +32228,14 @@ namespace objl
 						}
 					}
 
+					for (auto &t : timeStamps)
+					{
+						if (t > animation.animationDuration)
+						{
+							animation.animationDuration = t;
+						}
+					}
+
 					if (channel.target_path == "translation") 
 					{
 						type = 0;
@@ -32163,12 +32251,13 @@ namespace objl
 							float *translation = (float *)
 								(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
 
+							gl3dAssert(accessor.count == timeStamps.size());
 
 							move.x = translation[t * 3 + 0];
 							move.y = translation[t * 3 + 1];
 							move.z = translation[t * 3 + 2];
 
-							animation.keyFramesTrans[node][t].timeStemp = timeStamps[t];
+							animation.keyFramesTrans[node][t].timeStamp = timeStamps[t];
 							animation.keyFramesTrans[node][t].translation = move;
 						}
 					}
@@ -32186,14 +32275,15 @@ namespace objl
 							float *rotation = (float *)
 								(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
 
-							accessor.count;
+							gl3dAssert(accessor.count == timeStamps.size());
 
 							rot.x = rotation[t * 4 + 0];
 							rot.y = rotation[t * 4 + 1];
 							rot.z = rotation[t * 4 + 2];
 							rot.w = rotation[t * 4 + 3];
 
-							animation.keyFramesRot[node][t].timeStemp = timeStamps[t];
+
+							animation.keyFramesRot[node][t].timeStamp = timeStamps[t];
 							animation.keyFramesRot[node][t].rotation = rot;
 						}
 					}
@@ -32212,25 +32302,114 @@ namespace objl
 							float *scaleBuffer = (float *)
 								(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
 
-							accessor.count;
+							gl3dAssert(accessor.count == timeStamps.size());
 
 							scale.x = scaleBuffer[t * 3 + 0];
 							scale.y = scaleBuffer[t * 3 + 1];
 							scale.z = scaleBuffer[t * 3 + 2];
 
-							animation.keyFramesScale[node][t].timeStemp = timeStamps[t];
+							animation.keyFramesScale[node][t].timeStamp = timeStamps[t];
 							animation.keyFramesScale[node][t].scale = scale;
 						}
 					}
+					else if (channel.target_path == "weights") 
+					{
+						gl3dAssertComment(0, "weights are supported");
+					}
 					else 
 					{
 						continue;
 					}
-
-
-				
 				}
 
+				//this code is not done
+				// it merges frames
+				// it will probably not be used
+				//for (int node = 0; node < animation.timeStamps.size(); node++)
+				//{
+				//
+				//	#pragma region get all the time stamps
+				//	std::vector<float> allFrames;
+				//	{
+				//		std::unordered_set<float> allFramesSet;
+				//		allFramesSet.reserve(animation.keyFramesTrans[node].size() +
+				//			animation.keyFramesScale[node].size() +
+				//			animation.keyFramesRot[node].size()
+				//		);
+				//
+				//		for (auto &frame : animation.keyFramesTrans[node])
+				//		{
+				//			allFramesSet.insert(frame.timeStamp);
+				//		}
+				//		for (auto &frame : animation.keyFramesScale[node])
+				//		{
+				//			allFramesSet.insert(frame.timeStamp);
+				//		}
+				//		for (auto &frame : animation.keyFramesRot[node])
+				//		{
+				//			allFramesSet.insert(frame.timeStamp);
+				//		}
+				//
+				//		allFrames.reserve(allFramesSet.size());
+				//		for (auto i : allFramesSet)
+				//		{
+				//			allFrames.push_back(i);
+				//		}
+				//
+				//		std::sort(allFrames.begin(), allFrames.end());
+				//	}
+				//	#pragma endregion
+				//
+				//	animation.keyFrames[node].resize(allFrames.size());
+				//	for (int i = 0; i < allFrames.size(); i++)
+				//	{
+				//		animation.keyFrames[node][i].timeStamp = allFrames[i];
+				//	}
+				//
+				//	//add translation
+				//	for (auto &frame : animation.keyFramesTrans[node])
+				//	{
+				//		for (int i = 0; i < allFrames.size(); i++) 
+				//		{
+				//			if (allFrames[i] == frame.timeStamp)
+				//			{
+				//				animation.keyFrames[node][i].translation = frame.translation;
+				//				animation.keyFrames[node][i].translationSet = true;
+				//				break;
+				//			}
+				//		}
+				//	}
+				//
+				//	//add rotation
+				//	for (auto &frame : animation.keyFramesRot[node])
+				//	{
+				//		for (int i = 0; i < allFrames.size(); i++)
+				//		{
+				//			if (allFrames[i] == frame.timeStamp)
+				//			{
+				//				animation.keyFrames[node][i].rotation = frame.rotation;
+				//				animation.keyFrames[node][i].rotationSet = true;
+				//				break;
+				//			}
+				//		}
+				//	}
+				//
+				//	//add rotation
+				//	for (auto &frame : animation.keyFramesRot[node])
+				//	{
+				//		for (int i = 0; i < allFrames.size(); i++)
+				//		{
+				//			if (allFrames[i] == frame.timeStamp)
+				//			{
+				//				animation.keyFrames[node][i].rotation = frame.rotation;
+				//				animation.keyFrames[node][i].rotationSet = true;
+				//				break;
+				//			}
+				//		}
+				//	}
+				//
+				//}
+
 				animations.push_back(std::move(animation));
 			}
 
@@ -32279,9 +32458,6 @@ namespace objl
 						float *tex = (float *)
 							(&bufferTex.data[bufferViewTex.byteOffset + accessorTex.byteOffset]);
 
-						
-
-
 						//todo look into support models without texcoords
 
 						if(p.attributes.find("JOINTS_0") != p.attributes.end() && 
@@ -32292,14 +32468,13 @@ namespace objl
 							tinygltf::BufferView &bufferViewJoints = model.bufferViews[accessorJoints.bufferView];
 							tinygltf::Buffer &bufferJoints = model.buffers[bufferViewJoints.buffer];
 							
-
 							tinygltf::Accessor &accessorWeights = model.accessors[p.attributes["WEIGHTS_0"]];
 							tinygltf::BufferView &bufferViewWeights = model.bufferViews[accessorWeights.bufferView];
 							tinygltf::Buffer &bufferWeights = model.buffers[bufferViewWeights.buffer];
 							float *weights = (float *)
 								(&bufferWeights.data[bufferViewWeights.byteOffset + accessorWeights.byteOffset]);
 
-
+							m.VerticesAnimations.reserve(accessor.count);
 							for (size_t i = 0; i < accessor.count; ++i)
 							{
 								glm::ivec4 jointsIndex(-1,-1,-1,-1);
@@ -32342,7 +32517,6 @@ namespace objl
 									case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
 									{
 										componentCount /= sizeof(unsigned short);
-
 										unsigned short *joint = (unsigned short *)
 											(&bufferJoints.data[bufferViewJoints.byteOffset + accessorJoints.byteOffset]);
 
@@ -32374,6 +32548,31 @@ namespace objl
 
 								};
 
+								for (int j = 3; j>=0; j--)
+								{
+									if (weightsVec[j] == 0.f)
+									{
+										jointsIndex[j] = -1;
+									}
+									else
+									{
+										break;
+									}
+								}
+
+								//for (int j = 0; j < 4; j++) 
+								//{
+								//	if (jointsIndex[j] == -1)
+								//	{
+								//		break;
+								//	}
+								//	else
+								//	{
+								//		jointsIndex[j] = skinJoints[jointsIndex[j]]; 
+								//	}
+								//
+								//}
+
 								if (componentCount > 4)
 								{
 									weightsVec /= weightsVec.x + weightsVec.y + weightsVec.z + weightsVec.w;
@@ -32404,6 +32603,7 @@ namespace objl
 						}
 						else
 						{
+							m.Vertices.reserve(accessor.count);
 							for (size_t i = 0; i < accessor.count; ++i)
 							{
 								// Positions are Vec3 components, so for each vec3 stride, offset for x, y, and z.