[rmodels] Updated blend function signature and added function to update verts from bones
Signed-off-by: Kirandeep-Singh-Khehra <kirandeepsinghkhehra@gmail.com>
This commit is contained in:
parent
438318e7ee
commit
7f7815e3a2
|
|
@ -48,6 +48,7 @@ int main(void)
|
|||
// Load gltf model
|
||||
Model characterModel = LoadModel("resources/models/gltf/robot.glb"); // Load character model
|
||||
|
||||
/* INFO: Uncomment this to use GPU skinning
|
||||
// Load skinning shader
|
||||
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
|
||||
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
|
||||
|
|
@ -56,6 +57,7 @@ int main(void)
|
|||
{
|
||||
characterModel.materials[i].shader = skinningShader;
|
||||
}
|
||||
*/
|
||||
|
||||
// Load gltf model animations
|
||||
int animsCount = 0;
|
||||
|
|
@ -93,7 +95,10 @@ int main(void)
|
|||
|
||||
// Update bones
|
||||
// Note: Same animation frame index is used below. By default it loops both animations
|
||||
UpdateModelAnimationBonesWithBlending(characterModel, modelAnimations[animIndex0], animCurrentFrame, modelAnimations[animIndex1], animCurrentFrame, blendFactor);
|
||||
UpdateModelAnimationBonesLerp(characterModel, modelAnimations[animIndex0], animCurrentFrame, modelAnimations[animIndex1], animCurrentFrame, blendFactor);
|
||||
|
||||
// INFO: Comment the following line to use GPU skinning
|
||||
UpdateModelVertsToCurrentBones(characterModel);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
|
@ -103,12 +108,17 @@ int main(void)
|
|||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
|
||||
/* INFO: Uncomment this to use GPU skinning
|
||||
// Draw character mesh, pose calculation is done in shader (GPU skinning)
|
||||
for (int i = 0; i < characterModel.meshCount; i++)
|
||||
{
|
||||
DrawMesh(characterModel.meshes[i], characterModel.materials[characterModel.meshMaterial[i]], characterModel.transform);
|
||||
}
|
||||
*/
|
||||
|
||||
// INFO: Comment the following line to use GPU skinning
|
||||
DrawModel(characterModel, (Vector3){0.0f, 0.0f, 0.0f}, 1.0f, WHITE);
|
||||
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
|
@ -129,7 +139,9 @@ int main(void)
|
|||
//--------------------------------------------------------------------------------------
|
||||
UnloadModelAnimations(modelAnimations, animsCount); // Unload model animation
|
||||
UnloadModel(characterModel); // Unload model and meshes/material
|
||||
UnloadShader(skinningShader); // Unload GPU skinning shader
|
||||
|
||||
// INFO: Uncomment the following line to use GPU skinning
|
||||
// UnloadShader(skinningShader); // Unload GPU skinning shader
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1605,7 +1605,8 @@ RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId);
|
|||
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
|
||||
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU)
|
||||
RLAPI void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning)
|
||||
RLAPI void UpdateModelAnimationBonesWithBlending(Model model, ModelAnimation animA, int frameA, ModelAnimation animB, int frameB, float blendFactor); // Update model animation mesh bone matrices with blending between two poses(GPU skinning)
|
||||
RLAPI void UpdateModelAnimationBonesLerp(Model model, ModelAnimation animA, int frameA, ModelAnimation animB, int frameB, float value); // Update model animation mesh bone matrices with interpolation between two poses(GPU skinning)
|
||||
RLAPI void UpdateModelVertsToCurrentBones(Model model); // Update model vertices according to mesh bone matrices (CPU)
|
||||
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
||||
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
|
||||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||
|
|
|
|||
|
|
@ -2311,11 +2311,11 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
|
|||
// Update model animated bones transform matrices by blendin between two different given frames of different ModelAnimation(could be same too)
|
||||
// NOTE: Updated data is not uploaded to GPU but kept at model.meshes[i].boneMatrices[boneId],
|
||||
// to be uploaded to shader at drawing, in case GPU skinning is enabled
|
||||
void UpdateModelAnimationBonesWithBlending(Model model, ModelAnimation animA, int frameA, ModelAnimation animB, int frameB, float blendFactor)
|
||||
void UpdateModelAnimationBonesLerp(Model model, ModelAnimation animA, int frameA, ModelAnimation animB, int frameB, float value)
|
||||
{
|
||||
if ((animA.frameCount > 0) && (animA.bones != NULL) && (animA.framePoses != NULL) &&
|
||||
(animB.frameCount > 0) && (animB.bones != NULL) && (animB.framePoses != NULL) &&
|
||||
(blendFactor >= 0.0f) && (blendFactor <= 1.0f))
|
||||
(value >= 0.0f) && (value <= 1.0f))
|
||||
{
|
||||
frameA = frameA % animA.frameCount;
|
||||
frameB = frameB % animB.frameCount;
|
||||
|
|
@ -2341,9 +2341,9 @@ void UpdateModelAnimationBonesWithBlending(Model model, ModelAnimation animA, in
|
|||
Quaternion outBRotation = animB.framePoses[frameB][boneId].rotation;
|
||||
Vector3 outBScale = animB.framePoses[frameB][boneId].scale;
|
||||
|
||||
Vector3 outTranslation = Vector3Lerp(outATranslation, outBTranslation, blendFactor);
|
||||
Quaternion outRotation = QuaternionSlerp(outARotation, outBRotation, blendFactor);
|
||||
Vector3 outScale = Vector3Lerp(outAScale, outBScale, blendFactor);
|
||||
Vector3 outTranslation = Vector3Lerp(outATranslation, outBTranslation, value);
|
||||
Quaternion outRotation = QuaternionSlerp(outARotation, outBRotation, value);
|
||||
Vector3 outScale = Vector3Lerp(outAScale, outBScale, value);
|
||||
|
||||
Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), QuaternionInvert(inRotation));
|
||||
Quaternion invRotation = QuaternionInvert(inRotation);
|
||||
|
|
@ -2367,6 +2367,67 @@ void UpdateModelAnimationBonesWithBlending(Model model, ModelAnimation animA, in
|
|||
}
|
||||
}
|
||||
|
||||
// Update model vertex data (positions and normals) from mesh bone data
|
||||
// NOTE: Updated data is uploaded to GPU
|
||||
void UpdateModelVertsToCurrentBones(Model model)
|
||||
{
|
||||
for (int m = 0; m < model.meshCount; m++)
|
||||
{
|
||||
Mesh mesh = model.meshes[m];
|
||||
Vector3 animVertex = { 0 };
|
||||
Vector3 animNormal = { 0 };
|
||||
int boneId = 0;
|
||||
int boneCounter = 0;
|
||||
float boneWeight = 0.0;
|
||||
bool updated = false; // Flag to check when anim vertex information is updated
|
||||
const int vValues = mesh.vertexCount*3;
|
||||
for (int vCounter = 0; vCounter < vValues; vCounter += 3)
|
||||
{
|
||||
mesh.animVertices[vCounter] = 0;
|
||||
mesh.animVertices[vCounter + 1] = 0;
|
||||
mesh.animVertices[vCounter + 2] = 0;
|
||||
if (mesh.animNormals != NULL)
|
||||
{
|
||||
mesh.animNormals[vCounter] = 0;
|
||||
mesh.animNormals[vCounter + 1] = 0;
|
||||
mesh.animNormals[vCounter + 2] = 0;
|
||||
}
|
||||
// Iterates over 4 bones per vertex
|
||||
for (int j = 0; j < 4; j++, boneCounter++)
|
||||
{
|
||||
boneWeight = mesh.boneWeights[boneCounter];
|
||||
boneId = mesh.boneIds[boneCounter];
|
||||
|
||||
// Early stop when no transformation will be applied
|
||||
if (boneWeight == 0.0f) continue;
|
||||
animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };
|
||||
animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]);
|
||||
mesh.animVertices[vCounter] += animVertex.x*boneWeight;
|
||||
mesh.animVertices[vCounter+1] += animVertex.y*boneWeight;
|
||||
mesh.animVertices[vCounter+2] += animVertex.z*boneWeight;
|
||||
updated = true;
|
||||
|
||||
// Normals processing
|
||||
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
|
||||
if (mesh.normals != NULL)
|
||||
{
|
||||
animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };
|
||||
animNormal = Vector3Transform(animNormal,model.meshes[m].boneMatrices[boneId]);
|
||||
mesh.animNormals[vCounter] += animNormal.x*boneWeight;
|
||||
mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;
|
||||
mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position
|
||||
rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// at least 2x speed up vs the old method
|
||||
// Update model animated vertex data (positions and normals) for a given frame
|
||||
// NOTE: Updated data is uploaded to GPU
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user