diff options
| author | Hristo Stamenov <[email protected]> | 2021-03-09 01:11:08 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-03-09 00:11:08 +0100 |
| commit | 5c2983f510f101b7684026d02a92a8b5269aa9af (patch) | |
| tree | f270710357281566cdd26c4a04e8edf18670f1c0 | |
| parent | f0ab4723b939087ee05181202a01a213219590a5 (diff) | |
| download | raylib-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.glb | bin | 0 -> 6752 bytes | |||
| -rw-r--r-- | examples/models/resources/gltf/AnimatedTriangle.gltf | 118 | ||||
| -rw-r--r-- | examples/models/resources/gltf/BoxAnimated.glb | bin | 0 -> 11944 bytes | |||
| -rw-r--r-- | examples/models/resources/gltf/GearboxAssy.glb | bin | 0 -> 4958788 bytes | |||
| -rw-r--r-- | examples/models/resources/gltf/LICENSE | 13 | ||||
| -rw-r--r-- | src/models.c | 78 |
6 files changed, 202 insertions, 7 deletions
diff --git a/examples/models/resources/gltf/AnimatedMorphCube.glb b/examples/models/resources/gltf/AnimatedMorphCube.glb Binary files differnew file mode 100644 index 00000000..219d2ac5 --- /dev/null +++ b/examples/models/resources/gltf/AnimatedMorphCube.glb 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 Binary files differnew file mode 100644 index 00000000..69481ec3 --- /dev/null +++ b/examples/models/resources/gltf/BoxAnimated.glb diff --git a/examples/models/resources/gltf/GearboxAssy.glb b/examples/models/resources/gltf/GearboxAssy.glb Binary files differnew file mode 100644 index 00000000..78cdad62 --- /dev/null +++ b/examples/models/resources/gltf/GearboxAssy.glb 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; |
