Sfoglia il codice sorgente

Gltf model and animations exploring problems (#1635)

* Added bone binding to whole mesh and not only set vertices.
+ Also added missed setting of the animation count.
+ Removed double ; on one line

* Added more of the gltf sample models

https://github.com/KhronosGroup/glTF-Sample-Models
We need to make it working for all of them.

* Binding to initial bind pose added.

* Fix cube disappearing bug because lerpPercent could be Inf.

* Fixed for rigged figure also
Hristo Stamenov 4 anni fa
parent
commit
5c2983f510

BIN
examples/models/resources/gltf/AnimatedMorphCube.glb


+ 118 - 0
examples/models/resources/gltf/AnimatedTriangle.gltf

@@ -0,0 +1,118 @@
+{
+  "scene" : 0,
+  "scenes" : [
+    {
+      "nodes" : [ 0 ]
+    }
+  ],
+  
+  "nodes" : [
+    {
+      "mesh" : 0,
+      "rotation" : [ 0.0, 0.0, 0.0, 1.0 ]
+    }
+  ],
+  
+  "meshes" : [
+    {
+      "primitives" : [ {
+        "attributes" : {
+          "POSITION" : 1
+        },
+        "indices" : 0
+      } ]
+    }
+  ],
+  
+  "animations": [
+    {
+      "samplers" : [
+        {
+          "input" : 2,
+          "interpolation" : "LINEAR",
+          "output" : 3
+        }
+      ],
+      "channels" : [ {
+        "sampler" : 0,
+        "target" : {
+          "node" : 0,
+          "path" : "rotation"
+        }
+      } ]
+    }
+  ],
+
+  "buffers" : [
+    {
+      "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=",
+      "byteLength" : 44
+    },
+    {
+      "uri" : "data:application/octet-stream;base64,AAAAAAAAgD4AAAA/AABAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAD0/TQ/9P00PwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAPT9ND/0/TS/AAAAAAAAAAAAAAAAAACAPw==",
+      "byteLength" : 100
+    }
+  ],
+  "bufferViews" : [
+    {
+      "buffer" : 0,
+      "byteOffset" : 0,
+      "byteLength" : 6,
+      "target" : 34963
+    },
+    {
+      "buffer" : 0,
+      "byteOffset" : 8,
+      "byteLength" : 36,
+      "target" : 34962
+    },
+    {
+      "buffer" : 1,
+      "byteOffset" : 0,
+      "byteLength" : 100
+    }
+  ],
+  "accessors" : [
+    {
+      "bufferView" : 0,
+      "byteOffset" : 0,
+      "componentType" : 5123,
+      "count" : 3,
+      "type" : "SCALAR",
+      "max" : [ 2 ],
+      "min" : [ 0 ]
+    },
+    {
+      "bufferView" : 1,
+      "byteOffset" : 0,
+      "componentType" : 5126,
+      "count" : 3,
+      "type" : "VEC3",
+      "max" : [ 1.0, 1.0, 0.0 ],
+      "min" : [ 0.0, 0.0, 0.0 ]
+    },
+    {
+      "bufferView" : 2,
+      "byteOffset" : 0,
+      "componentType" : 5126,
+      "count" : 5,
+      "type" : "SCALAR",
+      "max" : [ 1.0 ],
+      "min" : [ 0.0 ]
+    },
+    {
+      "bufferView" : 2,
+      "byteOffset" : 20,
+      "componentType" : 5126,
+      "count" : 5,
+      "type" : "VEC4",
+      "max" : [ 0.0, 0.0, 1.0, 1.0 ],
+      "min" : [ 0.0, 0.0, 0.0, -0.707 ]
+    }
+  ],
+  
+  "asset" : {
+    "version" : "2.0"
+  }
+  
+}

BIN
examples/models/resources/gltf/BoxAnimated.glb


BIN
examples/models/resources/gltf/GearboxAssy.glb


+ 11 - 2
examples/models/resources/gltf/LICENSE

@@ -1,11 +1,20 @@
 Rigged Figure model has been created by Cesium (https://cesium.com/cesiumjs/),
 and licensed as Creative Commons Attribution 4.0 International License.
 
-Check for details: http://creativecommons.org/licenses/by/4.0/
+Box Animated model has been created by Cesium (https://cesium.com/cesiumjs/)
+and is licensed as Creative Commons Attribution 4.0 International License
 
 Avocado model is provided by Microsoft
 and licensed as CC0 Universal Public Domain
 
-Check for details: https://creativecommons.org/publicdomain/zero/1.0/
+Animated Morph Cube model is provided by Microsoft
+and licensed as CC0 Universal Public Domain
+
+Animated Triangle model is licensed as CC0 Universal Public Domain
+
+Gearbox Assy model has been provided by Okino Computer Graphics, using Okino Polytrans Software.
+no license information was provided
 
+Check for details on CC0: https://creativecommons.org/publicdomain/zero/1.0/
+Check for details on CC4: http://creativecommons.org/licenses/by/4.0/
 GLTF sample models for testing are taken from: https://github.com/KhronosGroup/glTF-Sample-Models/

+ 73 - 5
src/models.c

@@ -754,7 +754,7 @@ Model LoadModel(const char *fileName)
 
         if (model.meshMaterial == NULL) model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
     }
-
+	
     return model;
 }
 
@@ -3979,10 +3979,75 @@ static Model LoadGLTF(const char *fileName)
                 }
                 else
                 {
-                    model.meshMaterial[primitiveIndex] = model.materialCount - 1;;
+                    model.meshMaterial[primitiveIndex] = model.materialCount - 1;
                 }
                 
 //                if (data->meshes[i].)
+
+                if (model.meshes[primitiveIndex].boneIds == NULL && data->nodes_count > 0)
+                {
+                    for (int nodeId = 0; nodeId < data->nodes_count; nodeId++)
+                    {
+                        if (data->nodes[nodeId].mesh == &(data->meshes[i]))
+                        {
+                            model.meshes[primitiveIndex].boneIds = RL_CALLOC(4 * model.meshes[primitiveIndex].vertexCount, sizeof(int));
+                            model.meshes[primitiveIndex].boneWeights = RL_CALLOC(4 * model.meshes[primitiveIndex].vertexCount, sizeof(float));
+
+                        	for (int b = 0; b < 4 * model.meshes[primitiveIndex].vertexCount; b++)
+                            {
+                        		if(b % 4 == 0)
+                        		{
+                                    model.meshes[primitiveIndex].boneIds[b] = nodeId;
+                                    model.meshes[primitiveIndex].boneWeights[b] = 1.0f;
+                        		}
+                        		else
+                        		{
+                                    model.meshes[primitiveIndex].boneIds[b] = 0;
+                                    model.meshes[primitiveIndex].boneWeights[b] = 0.0f;
+                        		}
+                            
+                            }
+    
+                            Vector3 boundVertex = { 0 };
+                            Vector3 boundNormal = { 0 };
+    
+                            Vector3 outTranslation = { 0 };
+                            Quaternion outRotation = { 0 };
+                            Vector3 outScale = { 0 };
+    
+                            int vCounter = 0;
+                            int boneCounter = 0;
+                            int boneId = 0;
+    
+                            for (int i = 0; i < model.meshes[primitiveIndex].vertexCount; i++)
+                            {
+                                boneId = model.meshes[primitiveIndex].boneIds[boneCounter];
+                                outTranslation = model.bindPose[boneId].translation;
+                                outRotation = model.bindPose[boneId].rotation;
+                                outScale = model.bindPose[boneId].scale;
+        
+                                // Vertices processing
+                                boundVertex = (Vector3){ model.meshes[primitiveIndex].vertices[vCounter], model.meshes[primitiveIndex].vertices[vCounter + 1], model.meshes[primitiveIndex].vertices[vCounter + 2] };
+                                boundVertex = Vector3Multiply(boundVertex, outScale);
+                                boundVertex = Vector3RotateByQuaternion(boundVertex, outRotation);
+                                boundVertex = Vector3Add(boundVertex, outTranslation);
+                                model.meshes[primitiveIndex].vertices[vCounter] = boundVertex.x;
+                                model.meshes[primitiveIndex].vertices[vCounter + 1] = boundVertex.y;
+                                model.meshes[primitiveIndex].vertices[vCounter + 2] = boundVertex.z;
+        
+                                // Normals processing
+                                boundNormal = (Vector3){ model.meshes[primitiveIndex].normals[vCounter], model.meshes[primitiveIndex].normals[vCounter + 1], model.meshes[primitiveIndex].normals[vCounter + 2] };
+                                boundNormal = Vector3RotateByQuaternion(boundNormal, outRotation);
+                                model.meshes[primitiveIndex].normals[vCounter] = boundNormal.x;
+                                model.meshes[primitiveIndex].normals[vCounter + 1] = boundNormal.y;
+                                model.meshes[primitiveIndex].normals[vCounter + 2] = boundNormal.z;
+                                vCounter += 3;
+        
+                                boneCounter += 4;
+                            }
+                        }
+                    }
+                }
                 
                 primitiveIndex++;
             }
@@ -4053,9 +4118,9 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
 
         result = cgltf_load_buffers(&options, data, fileName);
         if (result != cgltf_result_success) TRACELOG(LOG_WARNING, "MODEL: [%s] unable to load glTF animations data", fileName);
-        
         animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));
-    
+        *animCount = data->animations_count;
+
         for (unsigned int a = 0; a < data->animations_count; a++)
         {
             // gltf animation consists of the following structures:
@@ -4150,7 +4215,10 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
                                 float previousInputTime = 0.0f;
                                 if (GltfReadFloat(sampler->input, outputMin, (float *)&previousInputTime, 1))
                                 {
-                                    lerpPercent = (frameTime - previousInputTime)/(inputFrameTime - previousInputTime);
+                                    if((inputFrameTime - previousInputTime) != 0)
+                                    {
+                                        lerpPercent = (frameTime - previousInputTime)/(inputFrameTime - previousInputTime);
+                                    }
                                 }
                                 
                                 break;