nitro-engine/include/NEModel.h
Antonio Niño Díaz 4642bdf982 library: Allow users to specify model transformation matrices
A manual matrix overrides scale, translation and rotation. It can be
removed to switch back to individual scale, translation and rotation.
2024-10-11 13:33:21 +02:00

364 lines
13 KiB
C

// SPDX-License-Identifier: MIT
//
// Copyright (c) 2008-2022 Antonio Niño Díaz
//
// This file is part of Nitro Engine
#ifndef NE_MODEL_H__
#define NE_MODEL_H__
/// @file NEModel.h
/// @brief Functions to draw and handle models.
/// @defgroup model_system Model handling system
///
/// Functions to create and manipulate animated or static models.
///
/// @{
#define NE_NO_TEXTURE -1 ///< Value that represents not having a texture
#define NE_NO_MESH -1 ///< Value that represents not having a mesh
#define NE_DEFAULT_MODELS 512 ///< Default max number of models
/// Possible animation types.
typedef enum {
NE_ANIM_LOOP, ///< When the end is reached it jumps to the start.
NE_ANIM_ONESHOT, ///< When the end is reached it stops.
} NE_AnimationType;
/// Holds information of the animation of a model.
typedef struct {
NE_Animation *animation; ///< Pointer to animation file
NE_AnimationType type; ///< Animation type.
int32_t speed; ///< Animation speed (f32).
int32_t currframe; ///< Current frame. It can be between frames (f32).
int32_t numframes; ///< Number of frames in the animation (int).
} NE_AnimInfo;
/// Possible model types.
typedef enum {
NE_Static, ///< Not animated.
NE_Animated ///< Animated.
} NE_ModelType;
/// Holds information of a model.
typedef struct {
NE_ModelType modeltype; ///< Model type (static or animated)
int meshindex; ///< Index of mesh (static or DSM)
NE_AnimInfo *animinfo[2]; ///< Animation information (two can be blended)
int32_t anim_blend; ///< Animation blend factor
NE_Material *texture; ///< Material used by this model
int x; ///< X position of the model (f32)
int y; ///< Y position of the model (f32)
int z; ///< Z position of the model (f32)
int rx; ///< Rotation of the model by X axis
int ry; ///< Rotation of the model by Y axis
int rz; ///< Rotation of the model by Z axis
int sx; ///< X scale of the model (f32)
int sy; ///< Y scale of the model (f32)
int sz; ///< Z scale of the model (f32)
m4x3 *mat; ///< Transformation matrix assigned by the user.
} NE_Model;
/// Creates a new model object.
///
/// @param type Model type (static or animated).
/// @return Pointer to the newly created camera.
NE_Model *NE_ModelCreate(NE_ModelType type);
/// Deletes a model.
///
/// @param model Pointer to the model.
void NE_ModelDelete(NE_Model *model);
/// Marks the mesh of a model to be freed when the model is deleted.
///
/// When a model is loaded with NE_ModelLoadStaticMeshFAT() or
/// NE_ModelLoadDSMFAT(), the mesh is read from storage into RAM to a buffer
/// allocated witn malloc(). This buffer is freed with free() when
/// NE_ModelDelete() is called.
///
/// If the mesh is loaded using NE_ModelLoadStaticMesh() or NE_ModelLoadDSM(),
/// Nitro Engine can't tell if the user has loaded it from storage, or if it has
/// been included in the NDS file as data. If the user has loaded the mesh into
/// a buffer allocated with malloc(), the user is responsible for calling free()
/// after NE_ModelDelete().
///
/// NE_ModelFreeMeshWhenDeleted() gives you the option of skipping that last
/// free(). After you call this function, NE_ModelDelete() will call free() for
/// you automatically so that you don't have to keep track of the pointer in the
/// logic of your program.
///
/// @param model Pointer to the model.
void NE_ModelFreeMeshWhenDeleted(NE_Model *model);
/// Assign a display list in RAM to a static model.
///
/// @param model Pointer to the model.
/// @param pointer Pointer to the display list.
/// @return It returns 1 on success, 0 on error.
int NE_ModelLoadStaticMesh(NE_Model *model, const void *pointer);
/// Loads a display list from a filesystem and assigns it to a static model.
///
/// @param model Pointer to the model.
/// @param path Path to the display list.
/// @return It returns 1 on success, 0 on error.
int NE_ModelLoadStaticMeshFAT(NE_Model *model, const char *path);
/// Assign a material to a model.
///
/// @param model Pointer to the model.
/// @param material Pointer to the material.
void NE_ModelSetMaterial(NE_Model *model, NE_Material *material);
/// Assign an animation to a model.
///
/// @param model Pointer to the model.
/// @param anim Pointer to the animation.
void NE_ModelSetAnimation(NE_Model *model, NE_Animation *anim);
/// Assign a secondary animation to a model.
///
/// The secondary animation is an animation that is averaged with the main
/// animation. This is useful to do transitions between animations. This takes a
/// bit more of CPU to display, though.
///
/// Whenever you want to go back to having one animation, you have to use
/// NE_ModelAnimSecondaryClear(). This function lets you stop blending
/// animations, and it gives you the option to preserve the main or the
/// secondary animation.
///
/// Function NE_ModelAnimSecondarySetFactor() lets you specify a value to
/// specify the blending factor, where 0.0 means "display the main animation
/// only" and 1.0 means "display the secondary animation only". The initial
/// value after calling NE_ModelAnimSecondaryStart() is 0.0.
///
/// @param model Pointer to the model.
/// @param anim Pointer to the animation.
void NE_ModelSetAnimationSecondary(NE_Model *model, NE_Animation *anim);
/// Draw a model.
///
/// @param model Pointer to the model.
void NE_ModelDraw(const NE_Model *model);
/// Clone model.
///
/// This clones the mesh, including the animation, the material it uses. It
/// doesn't actually duplicate the memory used in RAM to store the mesh, and it
/// keeps track of how many models use the same mesh. NE_ModelDelete() only
/// frees the mesh when the user deletes the last model that uses it.
///
/// @param dest Pointer to the destination model.
/// @param source Pointer to the source model.
void NE_ModelClone(NE_Model *dest, NE_Model *source);
/// Set position of a model.
///
/// @param model Pointer to the model.
/// @param x (x, y, z) Coordinates (f32).
/// @param y (x, y, z) Coordinates (f32).
/// @param z (x, y, z) Coordinates (f32).
void NE_ModelSetCoordI(NE_Model *model, int x, int y, int z);
/// Set position of a model.
///
/// @param m Pointer to the model.
/// @param x (x, y, z) Coordinates (float).
/// @param y (x, y, z) Coordinates (float).
/// @param z (x, y, z) Coordinates (float).
#define NE_ModelSetCoord(m, x, y, z) \
NE_ModelSetCoordI(m, floattof32(x), floattof32(y), floattof32(z))
/// Set scale of a model.
///
/// @param model Pointer to the model.
/// @param x (x, y, z) Scale (f32).
/// @param y (x, y, z) Scale (f32).
/// @param z (x, y, z) Scale (f32).
void NE_ModelScaleI(NE_Model *model, int x, int y, int z);
/// Set scale of a model.
///
/// @param m Pointer to the model.
/// @param x (x, y, z) Scale (float).
/// @param y (x, y, z) Scale (float).
/// @param z (x, y, z) Scale (float).
#define NE_ModelScale(m, x, y, z) \
NE_ModelScaleI(m, floattof32(x), floattof32(y), floattof32(z))
/// Translate a model.
///
/// @param model Pointer to the model.
/// @param x (x, y, z) Translate vector (f32).
/// @param y (x, y, z) Translate vector (f32).
/// @param z (x, y, z) Translate vector (f32).
void NE_ModelTranslateI(NE_Model *model, int x, int y, int z);
/// Translate a model.
///
/// @param m Pointer to the model.
/// @param x (x, y, z) Translate vector (float).
/// @param y (x, y, z) Translate vector (float).
/// @param z (x, y, z) Translate vector (float).
#define NE_ModelTranslate(m, x, y, z) \
NE_ModelTranslateI(m, floattof32(x), floattof32(y), floattof32(z))
/// Set rotation of a model.
///
/// This function sets the rotation of the model to the provided values.
///
/// @param model Pointer to the model.
/// @param rx Rotation by X axis (0 - 511).
/// @param ry Rotation by Y axis (0 - 511).
/// @param rz Rotation by Z axis (0 - 511).
void NE_ModelSetRot(NE_Model *model, int rx, int ry, int rz);
/// Rotate a model.
///
/// This function adds the values to the current rotation of the model.
///
/// @param model Pointer to the model.
/// @param rx Rotation by X axis (0 - 511).
/// @param ry Rotation by Y axis (0 - 511).
/// @param rz Rotation by Z axis (0 - 511).
void NE_ModelRotate(NE_Model *model, int rx, int ry, int rz);
/// Assigns a 4x3 transformation matrix to a model.
///
/// When a matrix is assigned, the scale, position and rotation of the model
/// will be ignored.
///
/// Note that the provided matrix is copied to the internal state of the model,
/// so the caller of the function doesn't need to keep it in memory.
///
/// @param model Pointer to the model.
/// @param mat Matrix to be used.
/// @return Returns 1 on success, 0 on failure.
int NE_ModelSetMatrix(NE_Model *model, m4x3 *mat);
/// Clears the 4x3 transformation matrix of a model.
///
/// The model will start using the individual scale, translation and rotation
/// values.
///
/// @param model Pointer to the model.
void NE_ModelClearMatrix(NE_Model *model);
/// Update internal state of the animation of all models.
void NE_ModelAnimateAll(void);
/// Starts the animation of an animated model.
///
/// The speed can be positive or negative. A speed of 0 stops the animation, a
/// speed of 1 << 12 means that the model will advance one model frame per NDS
/// frame. Anything in between will advance less than one model frame per NDS
/// frame.
///
/// @param model Pointer to the model.
/// @param type Animation type (NE_ANIM_LOOP / NE_ANIM_ONESHOT).
/// @param speed Animation speed. (f32)
void NE_ModelAnimStart(NE_Model *model, NE_AnimationType type, int32_t speed);
/// Starts the secondary animation of an animated model.
///
/// @param model Pointer to the model.
/// @param type Animation type (NE_ANIM_LOOP / NE_ANIM_ONESHOT).
/// @param speed Animation speed. (f32)
void NE_ModelAnimSecondaryStart(NE_Model *model, NE_AnimationType type,
int32_t speed);
/// Sets animation speed.
///
/// The speed can be positive or negative. A speed of 0 stops the animation, a
/// speed of 1 << 12 means that the model will advance one model frame per NDS
/// frame. Anything in between will advance less than one model frame per NDS
/// frame.
///
/// @param model Pointer to the model.
/// @param speed New speed. (f32)
void NE_ModelAnimSetSpeed(NE_Model *model, int32_t speed);
/// Sets animation speed of the secondary animation.
///
/// @param model Pointer to the model.
/// @param speed New speed. (f32)
void NE_ModelAnimSecondarySetSpeed(NE_Model *model, int32_t speed);
/// Returns the current frame of an animated model.
///
/// @param model Pointer to the model.
/// @return Returns the frame in f32 format.
int32_t NE_ModelAnimGetFrame(const NE_Model *model);
/// Returns the current frame of the secondary animation of an animated model.
///
/// @param model Pointer to the model.
/// @return Returns the frame in f32 format.
int32_t NE_ModelAnimSecondaryGetFrame(const NE_Model *model);
/// Sets the current frame of an animated model.
///
/// @param model Pointer to the model.
/// @param frame Frame to set. (f32)
void NE_ModelAnimSetFrame(NE_Model *model, int32_t frame);
/// Sets the current frame of the secondary animation of an animated model.
///
/// @param model Pointer to the model.
/// @param frame Frame to set. (f32)
void NE_ModelAnimSecondarySetFrame(NE_Model *model, int32_t frame);
/// Sets the current blending factor between animations.
///
/// This is a value between 0.0 and 1.0 where 0.0 means "display the main
/// animation only" and 1.0 means "display the secondary animation only".
///
/// @param model Pointer to the model.
/// @param factor Blending factor to set. (f32)
void NE_ModelAnimSecondarySetFactor(NE_Model *model, int32_t factor);
/// Clears the secondary animation of a model.
///
/// It is possible to replace the main animation by the secondary animation, or
/// to simply remove the secondary animation. In both cases, the secondary
/// animation will be cleared.
///
/// @param model Pointer to the model.
/// @param replace_base_anim Set to true to replace the base animation by the
/// secondary animation.
void NE_ModelAnimSecondaryClear(NE_Model *model, bool replace_base_anim);
/// Loads a DSM file stored in RAM to a model.
///
/// @param model Pointer to the model.
/// @param pointer Pointer to the file.
/// @return It returns 1 on success, 0 on error.
int NE_ModelLoadDSM(NE_Model *model, const void *pointer);
/// Loads a DSM file stored in a filesystem to a model.
///
/// @param model Pointer to the model.
/// @param path Path to the file.
/// @return It returns 1 on success, 0 on error.
int NE_ModelLoadDSMFAT(NE_Model *model, const char *path);
/// Deletes all models and frees all memory used by them.
void NE_ModelDeleteAll(void);
/// Resets the model system and sets the maximun number of models.
///
/// @param max_models Number of models. If it is lower than 1, it will create
/// space for NE_DEFAULT_MODELS.
/// @return Returns 0 on success.
int NE_ModelSystemReset(int max_models);
/// Ends model system and frees all memory used by it.
void NE_ModelSystemEnd(void);
/// @}
#endif // NE_MODEL_H__