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
This commit is contained in:
parent
f0ab4723b9
commit
5c2983f510
6 changed files with 202 additions and 7 deletions
BIN
examples/models/resources/gltf/AnimatedMorphCube.glb
Normal file
BIN
examples/models/resources/gltf/AnimatedMorphCube.glb
Normal file
Binary file not shown.
118
examples/models/resources/gltf/AnimatedTriangle.gltf
Normal file
118
examples/models/resources/gltf/AnimatedTriangle.gltf
Normal 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
Normal file
BIN
examples/models/resources/gltf/BoxAnimated.glb
Normal file
Binary file not shown.
BIN
examples/models/resources/gltf/GearboxAssy.glb
Normal file
BIN
examples/models/resources/gltf/GearboxAssy.glb
Normal file
Binary file not shown.
|
@ -1,11 +1,20 @@
|
||||||
Rigged Figure model has been created by Cesium (https://cesium.com/cesiumjs/),
|
Rigged Figure model has been created by Cesium (https://cesium.com/cesiumjs/),
|
||||||
and licensed as Creative Commons Attribution 4.0 International License.
|
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
|
Avocado model is provided by Microsoft
|
||||||
and licensed as CC0 Universal Public Domain
|
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/
|
GLTF sample models for testing are taken from: https://github.com/KhronosGroup/glTF-Sample-Models/
|
||||||
|
|
74
src/models.c
74
src/models.c
|
@ -3979,11 +3979,76 @@ static Model LoadGLTF(const char *fileName)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
model.meshMaterial[primitiveIndex] = model.materialCount - 1;;
|
model.meshMaterial[primitiveIndex] = model.materialCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (data->meshes[i].)
|
// 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++;
|
primitiveIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4053,8 +4118,8 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
|
|
||||||
result = cgltf_load_buffers(&options, data, fileName);
|
result = cgltf_load_buffers(&options, data, fileName);
|
||||||
if (result != cgltf_result_success) TRACELOG(LOG_WARNING, "MODEL: [%s] unable to load glTF animations 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));
|
animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));
|
||||||
|
*animCount = data->animations_count;
|
||||||
|
|
||||||
for (unsigned int a = 0; a < data->animations_count; a++)
|
for (unsigned int a = 0; a < data->animations_count; a++)
|
||||||
{
|
{
|
||||||
|
@ -4150,7 +4215,10 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
float previousInputTime = 0.0f;
|
float previousInputTime = 0.0f;
|
||||||
if (GltfReadFloat(sampler->input, outputMin, (float *)&previousInputTime, 1))
|
if (GltfReadFloat(sampler->input, outputMin, (float *)&previousInputTime, 1))
|
||||||
{
|
{
|
||||||
lerpPercent = (frameTime - previousInputTime)/(inputFrameTime - previousInputTime);
|
if((inputFrameTime - previousInputTime) != 0)
|
||||||
|
{
|
||||||
|
lerpPercent = (frameTime - previousInputTime)/(inputFrameTime - previousInputTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue