From 118a1f3a8bc468077fdd8bac4d46c452965ce283 Mon Sep 17 00:00:00 2001 From: jussi Date: Wed, 15 Nov 2023 22:04:45 +0200 Subject: Quaternion library. --- API.md | 11 ++- README.md | 4 +- ReiLua_API.lua | 8 +- changelog | 1 + devnotes | 5 +- docgen.lua | 7 +- examples/resources/lib/color.lua | 2 + examples/resources/lib/matrix.lua | 8 +- examples/resources/lib/quaternion.lua | 153 ++++++++++++++++++++++++++++++++++ src/models.c | 47 ++++++----- 10 files changed, 211 insertions(+), 35 deletions(-) create mode 100644 examples/resources/lib/quaternion.lua diff --git a/API.md b/API.md index e4d2f07..8f823d9 100644 --- a/API.md +++ b/API.md @@ -41,6 +41,10 @@ This function will be called on program close. Cleanup could be done here. --- +## Object unloading + +Some objects allocate memory that needs to be freed when object is no longer needed. By default objects like Textures are unloaded by the Lua garbage collector. It is generatty however recommended to handle this manually in more complex projects. You can change the behavior with SetGCUnload. + ## Arguments Arguments are stored in 'RL.arg' array. @@ -69,7 +73,7 @@ Vector4, 4 components --- -> Quaternion = { 1.0, 1.0, 1.0, 1.0 } or { x = 1.0, y = 1.0, z = 1.0, w = 1.0 } +> Quaternion = { 0.0, 0.0, 0.0, 1.0 } or { x = 0.0, y = 0.0, z = 0.0, w = 1.0 } Quaternion, 4 components (Vector4 alias) @@ -6310,10 +6314,13 @@ Compute model bounding box limits (considers all meshes) --- -> RL.SetModelMaterial( Model model, Material modelMaterial, Material material ) +> success = RL.SetModelMaterial( Model model, int modelMaterialId, Material material ) Copies material to model material. (Model material is the material id in models.) +- Failure return false +- Success return true + --- > RL.SetModelMeshMaterial( Model model, int meshId, int materialId ) diff --git a/README.md b/README.md index b67dc96..a710f00 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Included submodules. * Raymath * Lights * Easings -* RLGL WIP +* RLGL WIP (Mostly done) List of some MISSING features that are planned to be included. For specific function, check API. @@ -28,7 +28,7 @@ List of some MISSING features that are planned to be included. For specific func ## Roadmap * v0.7 - * Switch to Raylib v5.0? + * Switch to Raylib v5.0 ## Usage diff --git a/ReiLua_API.lua b/ReiLua_API.lua index f1ffa0b..7e93b23 100644 --- a/ReiLua_API.lua +++ b/ReiLua_API.lua @@ -3712,11 +3712,13 @@ function RL.UnloadModel( model ) end function RL.GetModelBoundingBox( model ) end ---Copies material to model material. (Model material is the material id in models.) +---- Failure return false +---- Success return true ---@param model any ----@param modelMaterial any +---@param modelMaterialId integer ---@param material any ----@return any RL.SetModelMaterial -function RL.SetModelMaterial( model, modelMaterial, material ) end +---@return any success +function RL.SetModelMaterial( model, modelMaterialId, material ) end ---Set material for a mesh (Mesh and material on this model) ---@param model any diff --git a/changelog b/changelog index 015a52c..c5923f8 100644 --- a/changelog +++ b/changelog @@ -19,6 +19,7 @@ KEY CHANGES: - CHANGED: Organized functions by putting them in the same order as in Raylib. - ADDED: Matrix library. - Removed: GC_UNLOAD build time define and replaced with flag to change it at runtime. + - ADDED: Quaternion library. DETAILED CHANGES: - CHANGED: GenImageColor now takes Vector2 as size. diff --git a/devnotes b/devnotes index 361c46f..7241aa2 100644 --- a/devnotes +++ b/devnotes @@ -8,16 +8,13 @@ Backlog { * Audio * AudioStream. * Models + * More Model management functions. Get mesh and material etc. * BoneInfo. - * LoadMaterials (Load materials from model file). * LoadMaterialsFromModel (Could then for example edit and set back to model). * rlgl * More Textures management functions. * Shader buffer storage object management (ssbo). - * Matrix class. - * Quaternion class. - * Examples * Improve Dungeon crawler example by generating custom mesh instead of drawing 3D quads. * Platformer example physics process for true framerate independence. diff --git a/docgen.lua b/docgen.lua index 1c3b2bb..8312c0f 100644 --- a/docgen.lua +++ b/docgen.lua @@ -122,6 +122,11 @@ luaApiFile:write( luaApiFile:write( "---"..FUNC_DESC.exit.."\nfunction RL.exit() end\n" ) +-- Object unloading. + +apiFile:write( "\n## Object unloading\n" ) +apiFile:write( "\nSome objects allocate memory that needs to be freed when object is no longer needed. By default objects like Textures are unloaded by the Lua garbage collector. It is generatty however recommended to handle this manually in more complex projects. You can change the behavior with SetGCUnload.\n" ) + -- Arguments. apiFile:write( "\n## Arguments\n" ) @@ -138,7 +143,7 @@ apiFile:write( "\n> Vector3 = { 1.0, 1.0, 1.0 } or { x = 1.0, y = 1.0, z = 1.0 } Vector3, 3 components\n\n---\n" ) apiFile:write( "\n> Vector4 = { 1.0, 1.0, 1.0, 1.0 } or { x = 1.0, y = 1.0, z = 1.0, w = 1.0 }\n\ Vector4, 4 components\n\n---\n" ) -apiFile:write( "\n> Quaternion = { 1.0, 1.0, 1.0, 1.0 } or { x = 1.0, y = 1.0, z = 1.0, w = 1.0 }\n\ +apiFile:write( "\n> Quaternion = { 0.0, 0.0, 0.0, 1.0 } or { x = 0.0, y = 0.0, z = 0.0, w = 1.0 }\n\ Quaternion, 4 components (Vector4 alias)\n\n---\n" ) apiFile:write( "\n> Matrix = { { 1.0, 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0, 0.0 }, { 0.0, 0.0, 0.0, 1.0 } }\n\ Matrix, 4x4 components, column major, OpenGL style, right-handed. Identity matrix example\n\n---\n" ) diff --git a/examples/resources/lib/color.lua b/examples/resources/lib/color.lua index 5f868b6..8948ac7 100644 --- a/examples/resources/lib/color.lua +++ b/examples/resources/lib/color.lua @@ -3,6 +3,8 @@ if table.unpack == nil then table.unpack = unpack end +local Vector3 = require( "vector3" ) + Color = {} Color.meta = { __index = Color, diff --git a/examples/resources/lib/matrix.lua b/examples/resources/lib/matrix.lua index 4b8cee3..e825102 100644 --- a/examples/resources/lib/matrix.lua +++ b/examples/resources/lib/matrix.lua @@ -27,10 +27,10 @@ Matrix.meta = { __index = Matrix, __tostring = function( m ) return "{\n" - .." { "..m.m[1][1]..", "..m.m[1][2]..", "..m.m[1][3]..", "..m.m[1][4].." },\n" - .." { "..m.m[2][1]..", "..m.m[2][2]..", "..m.m[2][3]..", "..m.m[2][4].." },\n" - .." { "..m.m[3][1]..", "..m.m[3][2]..", "..m.m[3][3]..", "..m.m[3][4].." },\n" - .." { "..m.m[3][1]..", "..m.m[3][2]..", "..m.m[3][3]..", "..m.m[3][4].." },\n" + .." {"..m.m[1][1]..", "..m.m[1][2]..", "..m.m[1][3]..", "..m.m[1][4].."},\n" + .." {"..m.m[2][1]..", "..m.m[2][2]..", "..m.m[2][3]..", "..m.m[2][4].."},\n" + .." {"..m.m[3][1]..", "..m.m[3][2]..", "..m.m[3][3]..", "..m.m[3][4].."},\n" + .." {"..m.m[3][1]..", "..m.m[3][2]..", "..m.m[3][3]..", "..m.m[3][4].."},\n" .."}" end, __add = function( m1, m2 ) diff --git a/examples/resources/lib/quaternion.lua b/examples/resources/lib/quaternion.lua new file mode 100644 index 0000000..4c42265 --- /dev/null +++ b/examples/resources/lib/quaternion.lua @@ -0,0 +1,153 @@ +-- For luaJit compatibility. +if table.unpack == nil then + table.unpack = unpack +end + +local Vector3 = require( "vector3" ) +local Matrix = require( "matrix" ) + +Quaternion = {} +Quaternion.meta = { + __index = Quaternion, + __tostring = function( q ) + return "{"..tostring( q.x )..", "..tostring( q.y )..", "..tostring( q.z )..", "..tostring( q.w ).."}" + end, + __add = function( q1, q2 ) + return Quaternion:new( RL.QuaternionAdd( q1, q2 ) ) + end, + __sub = function( q1, q2 ) + return Quaternion:new( RL.QuaternionSubtract( q1, q2 ) ) + end, + __mul = function( q1, q2 ) + return Quaternion:new( RL.QuaternionMultiply( q1, q2 ) ) + end, + __div = function( q1, q2 ) + return Quaternion:new( RL.QuaternionDivide( q1, q2 ) ) + end, + __unm = function( q ) + return Quaternion:new( RL.QuaternionInvert( q ) ) + end, + __len = function( _ ) + return 4 + end, + __eq = function( q1, q2 ) + return RL.QuaternionEquals( q1, q2 ) == 1 + end, +} + +function Quaternion:new( x, y, z, w ) + if type( x ) == "table" then + x, y, z, w = table.unpack( x ) + elseif type( x ) == "nil" then + x, y, z, w = 0, 0, 0, 1 -- QuaternionIdentity. + end + + local object = setmetatable( {}, Quaternion.meta ) + + object.x = x + object.y = y + object.z = z + object.w = w + + return object +end + +function Quaternion:set( x, y, z, w ) + if type( x ) == "table" then + x, y, z, w = table.unpack( x ) + elseif type( x ) == "nil" then + x, y, z, w = 0, 0, 0, 1 -- QuaternionIdentity. + end + + self.x = x + self.y = y + self.z = z + self.w = w +end + +function Quaternion:arr() + return { self.x, self.y, self.z, self.w } +end + +function Quaternion:unpack() + return self.x, self.y, self.z, self.w +end + +function Quaternion:clone() + return Quaternion:new( self.x, self.y, self.z, self.w ) +end + +function Quaternion:addValue( value ) + return Quaternion:new( RL.QuaternionAddValue( self, value ) ) +end + +function Quaternion:subValue( value ) + return Quaternion:new( RL.QuaternionSubtractValue( self, value ) ) +end + +function Quaternion:identity() + return Quaternion:new( RL.QuaternionIdentity() ) +end + +function Quaternion:length() + return RL.QuaternionLength( self ) +end + +function Quaternion:normalize() + return Quaternion:new( RL.QuaternionNormalize( self ) ) +end + +function Quaternion:invert() + return Quaternion:new( RL.QuaternionInvert( self ) ) +end + +function Quaternion:scale( scalar ) + return Quaternion:new( RL.QuaternionScale( self, scalar ) ) +end + +function Quaternion:lerp( q2, value ) + return Quaternion:new( RL.QuaternionLerp( self, q2, value ) ) +end + +function Quaternion:nLerp( q2, value ) + return Quaternion:new( RL.QuaternionNLerp( self, q2, value ) ) +end + +function Quaternion:sLerp( q2, value ) + return Quaternion:new( RL.QuaternionSLerp( self, q2, value ) ) +end + +function Quaternion:fromVector3ToVector3( from, to ) + return Vector3:new( RL.QuaternionFromVector3ToVector3( from, to ) ) +end + +function Quaternion:fromMatrix( mat ) + return Quaternion:new( RL.QuaternionFromMatrix( mat ) ) +end + +function Quaternion:toMatrix() + return Matrix:new( RL.QuaternionToMatrix( self ) ) +end + +function Quaternion:fromAxisAngle( axis, angle ) + return Quaternion:new( RL.QuaternionFromAxisAngle( axis, angle ) ) +end + +function Quaternion:toAxisAngle() + local axis, angle = Quaternion:new( RL.QuaternionToAxisAngle( self ) ) + return Vector3:new( axis ), angle +end + +function Quaternion:fromEuler( pitch, yaw, roll ) + return Quaternion:new( RL.QuaternionFromEuler( pitch, yaw, roll ) ) +end + +function Quaternion:toEuler() + return Vector3:new( RL.QuaternionToEuler( self ) ) +end + +function Quaternion:transform( mat ) + return Quaternion:new( RL.QuaternionTransform( self, mat ) ) +end + +return Quaternion diff --git a/src/models.c b/src/models.c index ae0a5cb..eb4b978 100644 --- a/src/models.c +++ b/src/models.c @@ -573,9 +573,12 @@ int lmodelsGetModelBoundingBox( lua_State *L ) { } /* -> RL.SetModelMaterial( Model model, Material modelMaterial, Material material ) +> success = RL.SetModelMaterial( Model model, int modelMaterialId, Material material ) Copies material to model material. (Model material is the material id in models.) + +- Failure return false +- Success return true */ int lmodelsSetModelMaterial( lua_State *L ) { Model *model = uluaGetModel( L, 1 ); @@ -584,25 +587,31 @@ int lmodelsSetModelMaterial( lua_State *L ) { //TODO Could maybe return old shader and textures for storage or get garbage collected? - /* Copy material data instead of using pointer. Pointer would result in double free error. */ - 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]; + if ( 0 <= modelMaterialId && modelMaterialId < model->materialCount ) { + /* Copy material data instead of using pointer. Pointer would result in double free error. */ + 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 ); } - - return 0; + else { + TraceLog( LOG_WARNING, "SetModelMaterial modelMaterialId %d out of bounds", modelMaterialId ); + lua_pushboolean( L, false ); + } + return 1; } /* -- cgit v1.2.3