@ -130,7 +130,7 @@
# define MAX_MATERIAL_MAPS 12 / / Maximum number of maps supported
# endif
# ifndef MAX_MESH_VERTEX_BUFFERS
# define MAX_MESH_VERTEX_BUFFERS 7 / / Maximum vertex buffers (VBO) per mesh
# define MAX_MESH_VERTEX_BUFFERS 9 / / Maximum vertex buffers (VBO) per mesh
# endif
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1248,11 +1248,13 @@ void UploadMesh(Mesh *mesh, bool dynamic)
mesh - > vaoId = 0 ; / / Vertex Array Object
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION ] = 0 ; / / Vertex buffer : positions
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD ] = 0 ; / / Vertex buffer : texcoords
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL ] = 0 ; / / Vertex buffer : normals
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR ] = 0 ; / / Vertex buffer : colors
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT ] = 0 ; / / Vertex buffer : tangents
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 ] = 0 ; / / Vertex buffer : texcoords2
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES ] = 0 ; / / Vertex buffer : indices
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL ] = 0 ; / / Vertex buffer : normals
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR ] = 0 ; / / Vertex buffer : colors
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT ] = 0 ; / / Vertex buffer : tangents
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 ] = 0 ; / / Vertex buffer : texcoords2
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS ] = 0 ; / / Vertex buffer : boneIds
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS ] = 0 ; / / Vertex buffer : boneWeights
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES ] = 0 ; / / Vertex buffer : indices
# if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
mesh - > vaoId = rlLoadVertexArray ( ) ;
@ -1338,6 +1340,38 @@ void UploadMesh(Mesh *mesh, bool dynamic)
rlSetVertexAttributeDefault ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 , value , SHADER_ATTRIB_VEC2 , 2 ) ;
rlDisableVertexAttribute ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 ) ;
}
if ( mesh - > boneIds ! = NULL )
{
/ / Enable vertex attribute : boneIds ( shader - location = 6 )
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS ] = rlLoadVertexBuffer ( mesh - > boneIds , mesh - > vertexCount * 4 * sizeof ( unsigned char ) , dynamic ) ;
rlSetVertexAttribute ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS , 4 , RL_UNSIGNED_BYTE , 0 , 0 , 0 ) ;
rlEnableVertexAttribute ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS ) ;
}
else
{
/ / Default vertex attribute : boneIds
/ / WARNING : Default value provided to shader if location available
float value [ 4 ] = { 0.0f , 0.0f , 0.0f , 0.0f } ;
rlSetVertexAttributeDefault ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS , value , SHADER_ATTRIB_VEC4 , 4 ) ;
rlDisableVertexAttribute ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS ) ;
}
if ( mesh - > boneWeights ! = NULL )
{
/ / Enable vertex attribute : boneWeights ( shader - location = 7 )
mesh - > vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS ] = rlLoadVertexBuffer ( mesh - > boneWeights , mesh - > vertexCount * 4 * sizeof ( float ) , dynamic ) ;
rlSetVertexAttribute ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS , 4 , RL_FLOAT , 0 , 0 , 0 ) ;
rlEnableVertexAttribute ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS ) ;
}
else
{
/ / Default vertex attribute : boneWeights
/ / WARNING : Default value provided to shader if location available
float value [ 4 ] = { 0.0f , 0.0f , 0.0f , 0.0f } ;
rlSetVertexAttributeDefault ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS , value , SHADER_ATTRIB_VEC4 , 2 ) ;
rlDisableVertexAttribute ( RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS ) ;
}
if ( mesh - > indices ! = NULL )
{
@ -1451,6 +1485,13 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
/ / Upload model normal matrix ( if locations available )
if ( material . shader . locs [ SHADER_LOC_MATRIX_NORMAL ] ! = - 1 ) rlSetUniformMatrix ( material . shader . locs [ SHADER_LOC_MATRIX_NORMAL ] , MatrixTranspose ( MatrixInvert ( matModel ) ) ) ;
/ / Upload Bone Transforms
if ( material . shader . locs [ SHADER_LOC_BONE_MATRICES ] ! = - 1 & & mesh . boneMatrices )
{
rlSetUniformMatrices ( material . shader . locs [ SHADER_LOC_BONE_MATRICES ] , mesh . boneMatrices , mesh . boneCount ) ;
}
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/ / Bind active texture maps ( if available )
@ -1529,6 +1570,22 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
rlSetVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_TEXCOORD02 ] , 2 , RL_FLOAT , 0 , 0 , 0 ) ;
rlEnableVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_TEXCOORD02 ] ) ;
}
/ / Bind mesh VBO data : vertex bone ids ( shader - location = 6 , if available )
if ( material . shader . locs [ SHADER_LOC_VERTEX_BONEIDS ] ! = - 1 )
{
rlEnableVertexBuffer ( mesh . vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS ] ) ;
rlSetVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_BONEIDS ] , 4 , RL_UNSIGNED_BYTE , 0 , 0 , 0 ) ;
rlEnableVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_BONEIDS ] ) ;
}
/ / Bind mesh VBO data : vertex bone weights ( shader - location = 7 , if available )
if ( material . shader . locs [ SHADER_LOC_VERTEX_BONEWEIGHTS ] ! = - 1 )
{
rlEnableVertexBuffer ( mesh . vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS ] ) ;
rlSetVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_BONEWEIGHTS ] , 4 , RL_FLOAT , 0 , 0 , 0 ) ;
rlEnableVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_BONEWEIGHTS ] ) ;
}
if ( mesh . indices ! = NULL ) rlEnableVertexBufferElement ( mesh . vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES ] ) ;
}
@ -1671,6 +1728,13 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
/ / Upload model normal matrix ( if locations available )
if ( material . shader . locs [ SHADER_LOC_MATRIX_NORMAL ] ! = - 1 ) rlSetUniformMatrix ( material . shader . locs [ SHADER_LOC_MATRIX_NORMAL ] , MatrixTranspose ( MatrixInvert ( matModel ) ) ) ;
/ / Upload Bone Transforms
if ( material . shader . locs [ SHADER_LOC_BONE_MATRICES ] ! = - 1 & & mesh . boneMatrices )
{
rlSetUniformMatrices ( material . shader . locs [ SHADER_LOC_BONE_MATRICES ] , mesh . boneMatrices , mesh . boneCount ) ;
}
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/ / Bind active texture maps ( if available )
@ -1747,6 +1811,22 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
rlSetVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_TEXCOORD02 ] , 2 , RL_FLOAT , 0 , 0 , 0 ) ;
rlEnableVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_TEXCOORD02 ] ) ;
}
/ / Bind mesh VBO data : vertex bone ids ( shader - location = 6 , if available )
if ( material . shader . locs [ SHADER_LOC_VERTEX_BONEIDS ] ! = - 1 )
{
rlEnableVertexBuffer ( mesh . vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS ] ) ;
rlSetVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_BONEIDS ] , 4 , RL_UNSIGNED_BYTE , 0 , 0 , 0 ) ;
rlEnableVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_BONEIDS ] ) ;
}
/ / Bind mesh VBO data : vertex bone weights ( shader - location = 7 , if available )
if ( material . shader . locs [ SHADER_LOC_VERTEX_BONEWEIGHTS ] ! = - 1 )
{
rlEnableVertexBuffer ( mesh . vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS ] ) ;
rlSetVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_BONEWEIGHTS ] , 4 , RL_FLOAT , 0 , 0 , 0 ) ;
rlEnableVertexAttribute ( material . shader . locs [ SHADER_LOC_VERTEX_BONEWEIGHTS ] ) ;
}
if ( mesh . indices ! = NULL ) rlEnableVertexBufferElement ( mesh . vboId [ RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES ] ) ;
}
@ -1825,6 +1905,7 @@ void UnloadMesh(Mesh mesh)
RL_FREE ( mesh . animNormals ) ;
RL_FREE ( mesh . boneWeights ) ;
RL_FREE ( mesh . boneIds ) ;
RL_FREE ( mesh . boneMatrices ) ;
}
/ / Export mesh data to file
@ -2255,6 +2336,50 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
}
}
void UpdateModelAnimationBoneMatrices ( Model model , ModelAnimation anim , int frame )
{
if ( ( anim . frameCount > 0 ) & & ( anim . bones ! = NULL ) & & ( anim . framePoses ! = NULL ) )
{
if ( frame > = anim . frameCount ) frame = frame % anim . frameCount ;
for ( int i = 0 ; i < model . meshCount ; i + + )
{
if ( model . meshes [ i ] . boneMatrices )
{
assert ( model . meshes [ i ] . boneCount = = anim . boneCount ) ;
for ( int boneId = 0 ; boneId < model . meshes [ i ] . boneCount ; boneId + + )
{
Vector3 inTranslation = model . bindPose [ boneId ] . translation ;
Quaternion inRotation = model . bindPose [ boneId ] . rotation ;
Vector3 inScale = model . bindPose [ boneId ] . scale ;
Vector3 outTranslation = anim . framePoses [ frame ] [ boneId ] . translation ;
Quaternion outRotation = anim . framePoses [ frame ] [ boneId ] . rotation ;
Vector3 outScale = anim . framePoses [ frame ] [ boneId ] . scale ;
Vector3 invTranslation = Vector3RotateByQuaternion ( Vector3Negate ( inTranslation ) , QuaternionInvert ( inRotation ) ) ;
Quaternion invRotation = QuaternionInvert ( inRotation ) ;
Vector3 invScale = Vector3Divide ( ( Vector3 ) { 1.0f , 1.0f , 1.0f } , inScale ) ;
Vector3 boneTranslation = Vector3Add (
Vector3RotateByQuaternion ( Vector3Multiply ( outScale , invTranslation ) ,
outRotation ) , outTranslation ) ;
Quaternion boneRotation = QuaternionMultiply ( outRotation , invRotation ) ;
Vector3 boneScale = Vector3Multiply ( outScale , invScale ) ;
Matrix boneMatrix = MatrixMultiply ( MatrixMultiply (
QuaternionToMatrix ( boneRotation ) ,
MatrixTranslate ( boneTranslation . x , boneTranslation . y , boneTranslation . z ) ) ,
MatrixScale ( boneScale . x , boneScale . y , boneScale . z ) ) ;
model . meshes [ i ] . boneMatrices [ boneId ] = boneMatrix ;
}
}
}
}
}
/ / Unload animation array data
void UnloadModelAnimations ( ModelAnimation * animations , int animCount )
{
@ -4671,6 +4796,17 @@ static Model LoadIQM(const char *fileName)
}
BuildPoseFromParentJoints ( model . bones , model . boneCount , model . bindPose ) ;
for ( int i = 0 ; i < model . meshCount ; i + + )
{
model . meshes [ i ] . boneCount = model . boneCount ;
model . meshes [ i ] . boneMatrices = RL_CALLOC ( model . meshes [ i ] . boneCount , sizeof ( Matrix ) ) ;
for ( int j = 0 ; j < model . meshes [ i ] . boneCount ; j + + )
{
model . meshes [ i ] . boneMatrices [ j ] = MatrixIdentity ( ) ;
}
}
UnloadFileData ( fileData ) ;
@ -5754,6 +5890,15 @@ static Model LoadGLTF(const char *fileName)
{
memcpy ( model . meshes [ meshIndex ] . animNormals , model . meshes [ meshIndex ] . normals , model . meshes [ meshIndex ] . vertexCount * 3 * sizeof ( float ) ) ;
}
/ / Bone Transform Matrices
model . meshes [ meshIndex ] . boneCount = model . boneCount ;
model . meshes [ meshIndex ] . boneMatrices = RL_CALLOC ( model . meshes [ meshIndex ] . boneCount , sizeof ( Matrix ) ) ;
for ( int j = 0 ; j < model . meshes [ meshIndex ] . boneCount ; j + + )
{
model . meshes [ meshIndex ] . boneMatrices [ j ] = MatrixIdentity ( ) ;
}
meshIndex + + ; / / Move to next mesh
}
@ -6522,6 +6667,13 @@ static Model LoadM3D(const char *fileName)
{
memcpy ( model . meshes [ i ] . animVertices , model . meshes [ i ] . vertices , model . meshes [ i ] . vertexCount * 3 * sizeof ( float ) ) ;
memcpy ( model . meshes [ i ] . animNormals , model . meshes [ i ] . normals , model . meshes [ i ] . vertexCount * 3 * sizeof ( float ) ) ;
model . meshes [ i ] . boneCount = model . boneCount ;
model . meshes [ i ] . boneMatrices = RL_CALLOC ( model . meshes [ i ] . boneCount , sizeof ( Matrix ) ) ;
for ( j = 0 ; j < model . meshes [ i ] . boneCount ; j + + )
{
model . meshes [ i ] . boneMatrices [ j ] = MatrixIdentity ( ) ;
}
}
}