summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHristo Stamenov <[email protected]>2021-03-09 01:11:08 +0200
committerGitHub <[email protected]>2021-03-09 00:11:08 +0100
commit5c2983f510f101b7684026d02a92a8b5269aa9af (patch)
treef270710357281566cdd26c4a04e8edf18670f1c0
parentf0ab4723b939087ee05181202a01a213219590a5 (diff)
downloadraylib-5c2983f510f101b7684026d02a92a8b5269aa9af.tar.gz
raylib-5c2983f510f101b7684026d02a92a8b5269aa9af.zip
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
-rw-r--r--examples/models/resources/gltf/AnimatedMorphCube.glbbin0 -> 6752 bytes
-rw-r--r--examples/models/resources/gltf/AnimatedTriangle.gltf118
-rw-r--r--examples/models/resources/gltf/BoxAnimated.glbbin0 -> 11944 bytes
-rw-r--r--examples/models/resources/gltf/GearboxAssy.glbbin0 -> 4958788 bytes
-rw-r--r--examples/models/resources/gltf/LICENSE13
-rw-r--r--src/models.c78
6 files changed, 202 insertions, 7 deletions
diff --git a/examples/models/resources/gltf/AnimatedMorphCube.glb b/examples/models/resources/gltf/AnimatedMorphCube.glb
new file mode 100644
index 00000000..219d2ac5
--- /dev/null
+++ b/examples/models/resources/gltf/AnimatedMorphCube.glb
Binary files differ
diff --git a/examples/models/resources/gltf/AnimatedTriangle.gltf b/examples/models/resources/gltf/AnimatedTriangle.gltf
new file mode 100644
index 00000000..d5c09549
--- /dev/null
+++ b/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"
+ }
+
+} \ No newline at end of file
diff --git a/examples/models/resources/gltf/BoxAnimated.glb b/examples/models/resources/gltf/BoxAnimated.glb
new file mode 100644
index 00000000..69481ec3
--- /dev/null
+++ b/examples/models/resources/gltf/BoxAnimated.glb
Binary files differ
diff --git a/examples/models/resources/gltf/GearboxAssy.glb b/examples/models/resources/gltf/GearboxAssy.glb
new file mode 100644
index 00000000..78cdad62
--- /dev/null
+++ b/examples/models/resources/gltf/GearboxAssy.glb
Binary files differ
diff --git a/examples/models/resources/gltf/LICENSE b/examples/models/resources/gltf/LICENSE
index 77c73c62..8617385f 100644
--- a/examples/models/resources/gltf/LICENSE
+++ b/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/
diff --git a/src/models.c b/src/models.c
index 00e4c1e3..eba6f4f6 100644
--- a/src/models.c
+++ b/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;