Browse Source

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
pull/1648/head
Hristo Stamenov 3 years ago
committed by GitHub
parent
commit
5c2983f510
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 202 additions and 7 deletions
  1. BIN
      examples/models/resources/gltf/AnimatedMorphCube.glb
  2. +118
    -0
      examples/models/resources/gltf/AnimatedTriangle.gltf
  3. BIN
      examples/models/resources/gltf/BoxAnimated.glb
  4. BIN
      examples/models/resources/gltf/GearboxAssy.glb
  5. +11
    -2
      examples/models/resources/gltf/LICENSE
  6. +73
    -5
      src/models.c

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


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

@ -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 View File


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


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

@ -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 View File

@ -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;

Loading…
Cancel
Save