More Model animations management functions.

This commit is contained in:
jussi
2023-12-08 22:40:04 +02:00
parent eb7873be2b
commit 93b5b2eb37
8 changed files with 342 additions and 72 deletions

68
API.md
View File

@@ -6605,16 +6605,16 @@ Set model transform matrix
> success = RL.SetModelMesh( Model model, int meshId, Mesh mesh ) > success = RL.SetModelMesh( Model model, int meshId, Mesh mesh )
Get model mesh. Return as lightuserdata Set model mesh.
- Failure return false - Failure return false
- Success return true - Success return true
--- ---
> success = RL.SetModelMaterial( Model model, int modelMaterialId, Material material ) > success = RL.SetModelMaterial( Model model, int materialId, Material material )
Copies material to model material Set material to model material
- Failure return false - Failure return false
- Success return true - Success return true
@@ -7057,6 +7057,18 @@ Update model animation pose
--- ---
> RL.UnloadModelAnimation( ModelAnimation animation )
Unload animation data
---
> RL.UnloadModelAnimations( ModelAnimation{} animations )
Unload animation table data
---
> valid = RL.IsModelAnimationValid( Model model, ModelAnimation animation ) > valid = RL.IsModelAnimationValid( Model model, ModelAnimation animation )
Check model animation skeleton match Check model animation skeleton match
@@ -7065,6 +7077,30 @@ Check model animation skeleton match
--- ---
> success = RL.SetModelAnimationBone( ModelAnimation animation, int boneId, BoneInfo bone )
Set modelAnimation bones information (skeleton)
- Failure return false
- Success return true
---
> success = RL.SetModelAnimationFramePose( ModelAnimation animation, int frame, int boneId, Transform pose )
Set modelAnimation bones base transformation (pose)
- Failure return false
- Success return true
---
> RL.SetModelAnimationName( ModelAnimation animation, string name )
Set modelAnimation name
---
> boneCount = RL.GetModelAnimationBoneCount( ModelAnimation animation ) > boneCount = RL.GetModelAnimationBoneCount( ModelAnimation animation )
Return modelAnimation bone count Return modelAnimation bone count
@@ -7081,6 +7117,32 @@ Return modelAnimation frame count
--- ---
> bone = RL.GetModelAnimationBone( ModelAnimation animation, int boneId )
Get modelAnimation bones information (skeleton)
- Failure return nil
- Success return BoneInfo
---
> pose = RL.GetModelAnimationFramePose( ModelAnimation animation, int frame, int boneId )
Get modelAnimation bones base transformation (pose)
- Failure return nil
- Success return Transform
---
> name = RL.GetModelAnimationName( ModelAnimation animation )
Get modelAnimation name
- Success return string
---
## Model - Collision detection functions ## Model - Collision detection functions
--- ---

View File

@@ -4001,7 +4001,7 @@ function RL.GetModelBoundingBox( model ) end
---@return any RL.SetModelTransform ---@return any RL.SetModelTransform
function RL.SetModelTransform( model, transform ) end function RL.SetModelTransform( model, transform ) end
---Get model mesh. Return as lightuserdata ---Set model mesh.
---- Failure return false ---- Failure return false
---- Success return true ---- Success return true
---@param model any ---@param model any
@@ -4010,14 +4010,14 @@ function RL.SetModelTransform( model, transform ) end
---@return any success ---@return any success
function RL.SetModelMesh( model, meshId, mesh ) end function RL.SetModelMesh( model, meshId, mesh ) end
---Copies material to model material ---Set material to model material
---- Failure return false ---- Failure return false
---- Success return true ---- Success return true
---@param model any ---@param model any
---@param modelMaterialId integer ---@param materialId integer
---@param material any ---@param material any
---@return any success ---@return any success
function RL.SetModelMaterial( model, modelMaterialId, material ) end function RL.SetModelMaterial( model, materialId, material ) end
---Set material for a mesh (Mesh and material on this model) ---Set material for a mesh (Mesh and material on this model)
---@param model any ---@param model any
@@ -4436,6 +4436,16 @@ function RL.LoadModelAnimations( fileName ) end
---@return any RL.UpdateModelAnimation ---@return any RL.UpdateModelAnimation
function RL.UpdateModelAnimation( model, animation, frame ) end function RL.UpdateModelAnimation( model, animation, frame ) end
---Unload animation data
---@param animation any
---@return any RL.UnloadModelAnimation
function RL.UnloadModelAnimation( animation ) end
---Unload animation table data
---@param animations table
---@return any RL.UnloadModelAnimations
function RL.UnloadModelAnimations( animations ) end
---Check model animation skeleton match ---Check model animation skeleton match
---- Success return bool ---- Success return bool
---@param model any ---@param model any
@@ -4443,6 +4453,31 @@ function RL.UpdateModelAnimation( model, animation, frame ) end
---@return any valid ---@return any valid
function RL.IsModelAnimationValid( model, animation ) end function RL.IsModelAnimationValid( model, animation ) end
---Set modelAnimation bones information (skeleton)
---- Failure return false
---- Success return true
---@param animation any
---@param boneId integer
---@param bone any
---@return any success
function RL.SetModelAnimationBone( animation, boneId, bone ) end
---Set modelAnimation bones base transformation (pose)
---- Failure return false
---- Success return true
---@param animation any
---@param frame integer
---@param boneId integer
---@param pose any
---@return any success
function RL.SetModelAnimationFramePose( animation, frame, boneId, pose ) end
---Set modelAnimation name
---@param animation any
---@param name string
---@return any RL.SetModelAnimationName
function RL.SetModelAnimationName( animation, name ) end
---Return modelAnimation bone count ---Return modelAnimation bone count
---- Success return int ---- Success return int
---@param animation any ---@param animation any
@@ -4455,6 +4490,29 @@ function RL.GetModelAnimationBoneCount( animation ) end
---@return any frameCount ---@return any frameCount
function RL.GetModelAnimationFrameCount( animation ) end function RL.GetModelAnimationFrameCount( animation ) end
---Get modelAnimation bones information (skeleton)
---- Failure return nil
---- Success return BoneInfo
---@param animation any
---@param boneId integer
---@return any bone
function RL.GetModelAnimationBone( animation, boneId ) end
---Get modelAnimation bones base transformation (pose)
---- Failure return nil
---- Success return Transform
---@param animation any
---@param frame integer
---@param boneId integer
---@return any pose
function RL.GetModelAnimationFramePose( animation, frame, boneId ) end
---Get modelAnimation name
---- Success return string
---@param animation any
---@return any name
function RL.GetModelAnimationName( animation ) end
-- Model - Collision detection functions -- Model - Collision detection functions
---Check collision between two spheres ---Check collision between two spheres

View File

@@ -21,6 +21,7 @@ KEY CHANGES:
- ADDED: Raygui wrapper library disabled and styles for each element. - ADDED: Raygui wrapper library disabled and styles for each element.
- ADDED: Files management functions. - ADDED: Files management functions.
- ADDED: More Model management functions. - ADDED: More Model management functions.
- ADDED: More Model animations management functions.
DETAILED CHANGES: DETAILED CHANGES:
- REMOVED: DrawLineBezierQuad, DrawLineBezierCubic. - REMOVED: DrawLineBezierQuad, DrawLineBezierCubic.

View File

@@ -19,7 +19,7 @@ Backlog {
* Core * Core
* Automation events functionality. * Automation events functionality.
* Models * Models
* More Animation management functions. * Mesh bone weight management?
* Examples * Examples
* Improve Dungeon crawler example by generating custom mesh instead of drawing 3D quads. * Improve Dungeon crawler example by generating custom mesh instead of drawing 3D quads.
@@ -38,5 +38,4 @@ Needs Testing {
* rlUpdateTexture * rlUpdateTexture
* rlReadTexturePixels * rlReadTexturePixels
* rlReadScreenPixels * rlReadScreenPixels
* SetModelMesh Test unloading for double free or other errors.
} }

View File

@@ -24,6 +24,10 @@ function RL.init()
RL.SetCamera3DTarget( camera, { 0, 0, 0 } ) RL.SetCamera3DTarget( camera, { 0, 0, 0 } )
RL.SetCamera3DUp( camera, { 0, 1, 0 } ) RL.SetCamera3DUp( camera, { 0, 1, 0 } )
RL.SetTextLineSpacing( 26 )
-- If custom material or mesh is set to model, we need to use custom unloading to prevent double free errors.
RL.SetGCUnload( false )
texture = RL.LoadTexture( RL.GetBasePath().."../resources/images/monkey_tex.png" ) texture = RL.LoadTexture( RL.GetBasePath().."../resources/images/monkey_tex.png" )
material = RL.CreateMaterial( { material = RL.CreateMaterial( {
@@ -37,8 +41,10 @@ function RL.init()
}, },
}, },
} ) } )
model = RL.LoadModel( RL.GetBasePath().."../resources/iqm/monkey.iqm" ) model = RL.LoadModel( RL.GetBasePath().."../resources/iqm/monkey.iqm" )
-- Unload old material.
RL.UnloadMaterial( RL.GetModelMaterial( model, 0 ) )
RL.SetModelMaterial( model, 0, material ) RL.SetModelMaterial( model, 0, material )
animations = RL.LoadModelAnimations( RL.GetBasePath().."../resources/iqm/monkey.iqm" ) animations = RL.LoadModelAnimations( RL.GetBasePath().."../resources/iqm/monkey.iqm" )
end end
@@ -85,5 +91,12 @@ function RL.draw()
Space: Play animation\ Space: Play animation\
Up arrow: Inreace animation speed\ Up arrow: Inreace animation speed\
Down arrow: Decreace animation speed", Down arrow: Decreace animation speed",
{ 10, 10 }, 30, RL.WHITE ) { 10, 10 }, 30, RL.WHITE
)
end
function RL.exit()
RL.UnloadTexture( texture )
RL.UnloadModel( model )
RL.UnloadModelAnimations( animations )
end end

View File

@@ -3,7 +3,6 @@
/* Internals. */ /* Internals. */
void unloadMaterial( Material *material ); void unloadMaterial( Material *material );
/* Deleted from raylib. Need for freeing models. */ /* Deleted from raylib. Need for freeing models. */
void UnloadModelKeepMeshes( Model model );
void DrawBillboardProNoRatio( Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint ); void DrawBillboardProNoRatio( Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint );
void DrawBillboardRecNoRatio( Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint ); void DrawBillboardRecNoRatio( Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint );
@@ -97,9 +96,17 @@ int lmodelsGetMaterialParams( lua_State *L );
/* Model animations management functions. */ /* Model animations management functions. */
int lmodelsLoadModelAnimations( lua_State *L ); int lmodelsLoadModelAnimations( lua_State *L );
int lmodelsUpdateModelAnimation( lua_State *L ); int lmodelsUpdateModelAnimation( lua_State *L );
int lmodelsUnloadModelAnimation( lua_State *L );
int lmodelsUnloadModelAnimations( lua_State *L );
int lmodelsIsModelAnimationValid( lua_State *L ); int lmodelsIsModelAnimationValid( lua_State *L );
int lmodelsSetModelAnimationBone( lua_State *L );
int lmodelsSetModelAnimationFramePose( lua_State *L );
int lmodelsSetModelAnimationName( lua_State *L );
int lmodelsGetModelAnimationBoneCount( lua_State *L ); int lmodelsGetModelAnimationBoneCount( lua_State *L );
int lmodelsGetModelAnimationFrameCount( lua_State *L ); int lmodelsGetModelAnimationFrameCount( lua_State *L );
int lmodelsGetModelAnimationBone( lua_State *L );
int lmodelsGetModelAnimationFramePose( lua_State *L );
int lmodelsGetModelAnimationName( lua_State *L );
/* Collision detection functions. */ /* Collision detection functions. */
int lmodelsCheckCollisionSpheres( lua_State *L ); int lmodelsCheckCollisionSpheres( lua_State *L );
int lmodelsCheckCollisionBoxes( lua_State *L ); int lmodelsCheckCollisionBoxes( lua_State *L );

View File

@@ -77,7 +77,6 @@ static void defineTexture() {
luaL_newmetatable( L, "Texture" ); luaL_newmetatable( L, "Texture" );
lua_pushvalue( L, -1 ); lua_pushvalue( L, -1 );
lua_setfield( L, -2, "__index" ); lua_setfield( L, -2, "__index" );
lua_pushcfunction( L, gcTexture ); lua_pushcfunction( L, gcTexture );
lua_setfield( L, -2, "__gc" ); lua_setfield( L, -2, "__gc" );
} }
@@ -267,7 +266,6 @@ static int gcModel( lua_State *L ) {
if ( state->gcUnload ) { if ( state->gcUnload ) {
Model *model = luaL_checkudata( L, 1, "Model" ); Model *model = luaL_checkudata( L, 1, "Model" );
UnloadModel( *model ); UnloadModel( *model );
// UnloadModelKeepMeshes( *model );
} }
return 0; return 0;
} }
@@ -1649,9 +1647,17 @@ void luaRegister() {
/* Model animations management functions. */ /* Model animations management functions. */
assingGlobalFunction( "LoadModelAnimations", lmodelsLoadModelAnimations ); assingGlobalFunction( "LoadModelAnimations", lmodelsLoadModelAnimations );
assingGlobalFunction( "UpdateModelAnimation", lmodelsUpdateModelAnimation ); assingGlobalFunction( "UpdateModelAnimation", lmodelsUpdateModelAnimation );
assingGlobalFunction( "UnloadModelAnimation", lmodelsUnloadModelAnimation );
assingGlobalFunction( "UnloadModelAnimations", lmodelsUnloadModelAnimations );
assingGlobalFunction( "IsModelAnimationValid", lmodelsIsModelAnimationValid ); assingGlobalFunction( "IsModelAnimationValid", lmodelsIsModelAnimationValid );
assingGlobalFunction( "SetModelAnimationBone", lmodelsSetModelAnimationBone );
assingGlobalFunction( "SetModelAnimationFramePose", lmodelsSetModelAnimationFramePose );
assingGlobalFunction( "SetModelAnimationName", lmodelsSetModelAnimationName );
assingGlobalFunction( "GetModelAnimationBoneCount", lmodelsGetModelAnimationBoneCount ); assingGlobalFunction( "GetModelAnimationBoneCount", lmodelsGetModelAnimationBoneCount );
assingGlobalFunction( "GetModelAnimationFrameCount", lmodelsGetModelAnimationFrameCount ); assingGlobalFunction( "GetModelAnimationFrameCount", lmodelsGetModelAnimationFrameCount );
assingGlobalFunction( "GetModelAnimationBone", lmodelsGetModelAnimationBone );
assingGlobalFunction( "GetModelAnimationFramePose", lmodelsGetModelAnimationFramePose );
assingGlobalFunction( "GetModelAnimationName", lmodelsGetModelAnimationName );
/* Collision detection functions. */ /* Collision detection functions. */
assingGlobalFunction( "CheckCollisionSpheres", lmodelsCheckCollisionSpheres ); assingGlobalFunction( "CheckCollisionSpheres", lmodelsCheckCollisionSpheres );
assingGlobalFunction( "CheckCollisionBoxes", lmodelsCheckCollisionBoxes ); assingGlobalFunction( "CheckCollisionBoxes", lmodelsCheckCollisionBoxes );

View File

@@ -10,26 +10,6 @@ void unloadMaterial( Material *material ) {
free( material->maps ); free( material->maps );
} }
// Unload model (but not meshes) from memory (RAM and/or VRAM)
void UnloadModelKeepMeshes( Model model ) {
// Unload materials maps
// NOTE: As the user could be sharing shaders and textures between models,
// we don't unload the material but just free it's maps,
// the user is responsible for freeing models shaders and textures
for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps);
// Unload arrays
RL_FREE(model.meshes);
RL_FREE(model.materials);
RL_FREE(model.meshMaterial);
// Unload animation data
RL_FREE(model.bones);
RL_FREE(model.bindPose);
TraceLog( LOG_INFO, "MODEL: Unloaded model (but not meshes) from RAM and VRAM" );
}
void DrawBillboardProNoRatio( Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint ) { void DrawBillboardProNoRatio( Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint ) {
// NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width // NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width
// Vector2 sizeRatio = { size.x*(float)source.width/source.height, size.y }; // Vector2 sizeRatio = { size.x*(float)source.width/source.height, size.y };
@@ -589,7 +569,7 @@ int lmodelsSetModelTransform( lua_State *L ) {
/* /*
> success = RL.SetModelMesh( Model model, int meshId, Mesh mesh ) > success = RL.SetModelMesh( Model model, int meshId, Mesh mesh )
Get model mesh. Return as lightuserdata Set model mesh.
- Failure return false - Failure return false
- Success return true - Success return true
@@ -600,52 +580,35 @@ int lmodelsSetModelMesh( lua_State *L ) {
Mesh *mesh = uluaGetMesh( L, 3 ); Mesh *mesh = uluaGetMesh( L, 3 );
if ( 0 <= meshId && meshId < model->meshCount ) { if ( 0 <= meshId && meshId < model->meshCount ) {
// TODO Test if mesh should be copied instead. Is there issues with unloading.
model->meshes[ meshId ] = *mesh; model->meshes[ meshId ] = *mesh;
lua_pushboolean( L, true ); lua_pushboolean( L, true );
} }
else { else {
TraceLog( LOG_WARNING, "MeshId %d out of bounds", meshId ); TraceLog( LOG_WARNING, "SetModelMesh meshId %d out of bounds", meshId );
lua_pushboolean( L, false ); lua_pushboolean( L, false );
} }
return 1; return 1;
} }
/* /*
> success = RL.SetModelMaterial( Model model, int modelMaterialId, Material material ) > success = RL.SetModelMaterial( Model model, int materialId, Material material )
Copies material to model material Set material to model material
- Failure return false - Failure return false
- Success return true - Success return true
*/ */
int lmodelsSetModelMaterial( lua_State *L ) { int lmodelsSetModelMaterial( lua_State *L ) {
Model *model = uluaGetModel( L, 1 ); Model *model = uluaGetModel( L, 1 );
int modelMaterialId = luaL_checkinteger( L, 2 ); int materialId = luaL_checkinteger( L, 2 );
Material *material = uluaGetMaterial( L, 3 ); Material *material = uluaGetMaterial( L, 3 );
if ( 0 <= modelMaterialId && modelMaterialId < model->materialCount ) { if ( 0 <= materialId && materialId < model->materialCount ) {
/* Copy material data instead of using pointer. Pointer would result in double free error. */ model->materials[ materialId ] = *material;
model->materials[ modelMaterialId ].shader = material->shader;
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_ALBEDO ] = material->maps[ MATERIAL_MAP_ALBEDO ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_METALNESS ] = material->maps[ MATERIAL_MAP_METALNESS ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_NORMAL ] = material->maps[ MATERIAL_MAP_NORMAL ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_ROUGHNESS ] = material->maps[ MATERIAL_MAP_ROUGHNESS ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_OCCLUSION ] = material->maps[ MATERIAL_MAP_OCCLUSION ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_EMISSION ] = material->maps[ MATERIAL_MAP_EMISSION ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_HEIGHT ] = material->maps[ MATERIAL_MAP_HEIGHT ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_CUBEMAP ] = material->maps[ MATERIAL_MAP_CUBEMAP ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_IRRADIANCE ] = material->maps[ MATERIAL_MAP_IRRADIANCE ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_PREFILTER ] = material->maps[ MATERIAL_MAP_PREFILTER ];
model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_BRDF ] = material->maps[ MATERIAL_MAP_BRDF ];
for ( int i = 0; i < 4; i++ ) {
model->materials[ modelMaterialId ].params[i] = material->params[i];
}
lua_pushboolean( L, true ); lua_pushboolean( L, true );
} }
else { else {
TraceLog( LOG_WARNING, "SetModelMaterial modelMaterialId %d out of bounds", modelMaterialId ); TraceLog( LOG_WARNING, "SetModelMaterial materialId %d out of bounds", materialId );
lua_pushboolean( L, false ); lua_pushboolean( L, false );
} }
return 1; return 1;
@@ -661,8 +624,14 @@ int lmodelsSetModelMeshMaterial( lua_State *L ) {
int meshId = luaL_checkinteger( L, 2 ); int meshId = luaL_checkinteger( L, 2 );
int materialId = luaL_checkinteger( L, 3 ); int materialId = luaL_checkinteger( L, 3 );
SetModelMeshMaterial( model, meshId, materialId ); if ( 0 <= meshId && meshId < model->meshCount && 0 <= materialId && materialId < model->materialCount ) {
SetModelMeshMaterial( model, meshId, materialId );
lua_pushboolean( L, true );
}
else {
TraceLog( LOG_WARNING, "SetModelMaterial meshId %d or materialId %d out of bounds", meshId, materialId );
lua_pushboolean( L, false );
}
return 0; return 0;
} }
@@ -684,7 +653,7 @@ int lmodelsSetModelBone( lua_State *L ) {
lua_pushboolean( L, true ); lua_pushboolean( L, true );
} }
else { else {
TraceLog( LOG_WARNING, "boneId %d out of bounds", boneId ); TraceLog( LOG_WARNING, "SetModelBone boneId %d out of bounds", boneId );
lua_pushboolean( L, false ); lua_pushboolean( L, false );
} }
return 1; return 1;
@@ -708,7 +677,7 @@ int lmodelsSetModelBindPose( lua_State *L ) {
lua_pushboolean( L, true ); lua_pushboolean( L, true );
} }
else { else {
TraceLog( LOG_WARNING, "boneId %d out of bounds", boneId ); TraceLog( LOG_WARNING, "SetModelBindPose boneId %d out of bounds", boneId );
lua_pushboolean( L, false ); lua_pushboolean( L, false );
} }
return 1; return 1;
@@ -775,7 +744,7 @@ int lmodelsGetModelMesh( lua_State *L ) {
lua_pushlightuserdata( L, &model->meshes[ meshId ] ); lua_pushlightuserdata( L, &model->meshes[ meshId ] );
} }
else { else {
TraceLog( LOG_WARNING, "MeshId %d out of bounds", meshId ); TraceLog( LOG_WARNING, "GetModelMesh meshId %d out of bounds", meshId );
lua_pushnil( L ); lua_pushnil( L );
} }
return 1; return 1;
@@ -797,7 +766,7 @@ int lmodelsGetModelMaterial( lua_State *L ) {
lua_pushlightuserdata( L, &model->materials[ materialId ] ); lua_pushlightuserdata( L, &model->materials[ materialId ] );
} }
else { else {
TraceLog( LOG_WARNING, "MaterialId %d out of bounds", materialId ); TraceLog( LOG_WARNING, "GetModelMaterial materialId %d out of bounds", materialId );
lua_pushnil( L ); lua_pushnil( L );
} }
return 1; return 1;
@@ -834,7 +803,7 @@ int lmodelsGetModelBone( lua_State *L ) {
uluaPushBoneInfo( L, model->bones[ boneId ] ); uluaPushBoneInfo( L, model->bones[ boneId ] );
} }
else { else {
TraceLog( LOG_WARNING, "BoneId %d out of bounds", boneId ); TraceLog( LOG_WARNING, "GetModelBone boneId %d out of bounds", boneId );
lua_pushnil( L ); lua_pushnil( L );
} }
return 1; return 1;
@@ -856,7 +825,7 @@ int lmodelsGetModelBindPose( lua_State *L ) {
uluaPushTransform( L, model->bindPose[ boneId ] ); uluaPushTransform( L, model->bindPose[ boneId ] );
} }
else { else {
TraceLog( LOG_WARNING, "BoneId %d out of bounds", boneId ); TraceLog( LOG_WARNING, "GetModelBindPose boneId %d out of bounds", boneId );
lua_pushnil( L ); lua_pushnil( L );
} }
return 1; return 1;
@@ -1955,7 +1924,6 @@ int lmodelsLoadModelAnimations( lua_State *L ) {
uluaPushModelAnimation( L, anims[i] ); uluaPushModelAnimation( L, anims[i] );
lua_rawseti( L, -2, i+1 ); lua_rawseti( L, -2, i+1 );
} }
return 1; return 1;
} }
TraceLog( state->logLevelInvalid, "Invalid file '%s'", lua_tostring( L, 1 ) ); TraceLog( state->logLevelInvalid, "Invalid file '%s'", lua_tostring( L, 1 ) );
@@ -1971,14 +1939,47 @@ Update model animation pose
*/ */
int lmodelsUpdateModelAnimation( lua_State *L ) { int lmodelsUpdateModelAnimation( lua_State *L ) {
Model *model = uluaGetModel( L, 1 ); Model *model = uluaGetModel( L, 1 );
ModelAnimation *modelAnimation = uluaGetModelAnimation( L, 2 ); ModelAnimation *animation = uluaGetModelAnimation( L, 2 );
int frame = luaL_checkinteger( L, 3 ); int frame = luaL_checkinteger( L, 3 );
UpdateModelAnimation( *model, *modelAnimation, frame ); UpdateModelAnimation( *model, *animation, frame );
return 0; return 0;
} }
/*
> RL.UnloadModelAnimation( ModelAnimation animation )
Unload animation data
*/
int lmodelsUnloadModelAnimation( lua_State *L ) {
ModelAnimation *animation = uluaGetModelAnimation( L, 1 );
UnloadModelAnimation( *animation );
return 0;
}
/*
> RL.UnloadModelAnimations( ModelAnimation{} animations )
Unload animation table data
*/
int lmodelsUnloadModelAnimations( lua_State *L ) {
int t = 1, i = 0;
lua_pushnil( L );
while ( lua_next( L, t ) != 0 ) {
if ( lua_isuserdata( L, -1 ) ) {
ModelAnimation *animation = uluaGetModelAnimation( L, lua_gettop( L ) );
UnloadModelAnimation( *animation );
}
i++;
lua_pop( L, 1 );
}
return 0;
}
/* /*
> valid = RL.IsModelAnimationValid( Model model, ModelAnimation animation ) > valid = RL.IsModelAnimationValid( Model model, ModelAnimation animation )
@@ -1988,9 +1989,72 @@ Check model animation skeleton match
*/ */
int lmodelsIsModelAnimationValid( lua_State *L ) { int lmodelsIsModelAnimationValid( lua_State *L ) {
Model *model = uluaGetModel( L, 1 ); Model *model = uluaGetModel( L, 1 );
ModelAnimation *modelAnimation = uluaGetModelAnimation( L, 2 ); ModelAnimation *animation = uluaGetModelAnimation( L, 2 );
lua_pushboolean( L, IsModelAnimationValid( *model, *modelAnimation ) ); lua_pushboolean( L, IsModelAnimationValid( *model, *animation ) );
return 1;
}
/*
> success = RL.SetModelAnimationBone( ModelAnimation animation, int boneId, BoneInfo bone )
Set modelAnimation bones information (skeleton)
- Failure return false
- Success return true
*/
int lmodelsSetModelAnimationBone( lua_State *L ) {
ModelAnimation *animation = uluaGetModelAnimation( L, 1 );
int boneId = luaL_checkinteger( L, 2 );
BoneInfo bone = uluaGetBoneInfo( L, 3 );
if ( 0 <= boneId && boneId < animation->boneCount ) {
animation->bones[ boneId ] = bone;
lua_pushboolean( L, true );
}
else {
TraceLog( LOG_WARNING, "SetModelAnimationBone boneId %d out of bounds", boneId );
lua_pushboolean( L, false );
}
return 1;
}
/*
> success = RL.SetModelAnimationFramePose( ModelAnimation animation, int frame, int boneId, Transform pose )
Set modelAnimation bones base transformation (pose)
- Failure return false
- Success return true
*/
int lmodelsSetModelAnimationFramePose( lua_State *L ) {
ModelAnimation *animation = uluaGetModelAnimation( L, 1 );
int frame = luaL_checkinteger( L, 2 );
int boneId = luaL_checkinteger( L, 3 );
Transform pose = uluaGetTransform( L, 4 );
if ( 0 <= frame && frame < animation->frameCount && 0 <= boneId && boneId < animation->boneCount ) {
animation->framePoses[ frame ][ boneId ] = pose;
lua_pushboolean( L, true );
}
else {
TraceLog( LOG_WARNING, "SetModelAnimationFramePose frame %d or BoneId %d out of bounds", frame, boneId );
lua_pushboolean( L, false );
}
return 1;
}
/*
> RL.SetModelAnimationName( ModelAnimation animation, string name )
Set modelAnimation name
*/
int lmodelsSetModelAnimationName( lua_State *L ) {
ModelAnimation *animation = uluaGetModelAnimation( L, 1 );
const char *name = luaL_checkstring( L, 2 );
strncpy( animation->name, name, 32 );
return 1; return 1;
} }
@@ -2025,6 +2089,66 @@ int lmodelsGetModelAnimationFrameCount( lua_State *L ) {
return 1; return 1;
} }
/*
> bone = RL.GetModelAnimationBone( ModelAnimation animation, int boneId )
Get modelAnimation bones information (skeleton)
- Failure return nil
- Success return BoneInfo
*/
int lmodelsGetModelAnimationBone( lua_State *L ) {
ModelAnimation *animation = uluaGetModelAnimation( L, 1 );
int boneId = luaL_checkinteger( L, 2 );
if ( 0 <= boneId && boneId < animation->boneCount ) {
uluaPushBoneInfo( L, animation->bones[ boneId ] );
}
else {
TraceLog( LOG_WARNING, "GetModelAnimationBone boneId %d out of bounds", boneId );
lua_pushnil( L );
}
return 1;
}
/*
> pose = RL.GetModelAnimationFramePose( ModelAnimation animation, int frame, int boneId )
Get modelAnimation bones base transformation (pose)
- Failure return nil
- Success return Transform
*/
int lmodelsGetModelAnimationFramePose( lua_State *L ) {
ModelAnimation *animation = uluaGetModelAnimation( L, 1 );
int frame = luaL_checkinteger( L, 2 );
int boneId = luaL_checkinteger( L, 3 );
if ( 0 <= frame && frame < animation->frameCount && 0 <= boneId && boneId < animation->boneCount ) {
uluaPushTransform( L, animation->framePoses[ frame ][ boneId ] );
}
else {
TraceLog( LOG_WARNING, "GetModelAnimationFramePose frame %d or BoneId %d out of bounds", frame, boneId );
lua_pushnil( L );
}
return 1;
}
/*
> name = RL.GetModelAnimationName( ModelAnimation animation )
Get modelAnimation name
- Success return string
*/
int lmodelsGetModelAnimationName( lua_State *L ) {
ModelAnimation *animation = uluaGetModelAnimation( L, 1 );
lua_pushstring( L, animation->name );
return 1;
}
/* /*
## Model - Collision detection functions ## Model - Collision detection functions
*/ */