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