mirror of
https://github.com/minetest/minetest.git
synced 2025-01-03 20:07:30 +01:00
Refactor: Merge [IC]SkinnedMesh
into SkinnedMesh
(#15511)
This commit is contained in:
parent
810f39767c
commit
3e10d9ccf5
@ -48,7 +48,7 @@ const c8 *const BoneAnimationModeNames[] = {
|
||||
};
|
||||
|
||||
//! Interface for bones used for skeletal animation.
|
||||
/** Used with ISkinnedMesh and IAnimatedMeshSceneNode. */
|
||||
/** Used with SkinnedMesh and IAnimatedMeshSceneNode. */
|
||||
class IBoneSceneNode : public ISceneNode
|
||||
{
|
||||
public:
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "SColor.h"
|
||||
#include "ESceneNodeTypes.h"
|
||||
#include "SceneParameters.h" // IWYU pragma: export
|
||||
#include "ISkinnedMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -93,6 +92,7 @@ class IBillboardSceneNode;
|
||||
class ICameraSceneNode;
|
||||
class IDummyTransformationSceneNode;
|
||||
class IMesh;
|
||||
class SkinnedMesh;
|
||||
class IMeshBuffer;
|
||||
class IMeshCache;
|
||||
class ISceneCollisionManager;
|
||||
@ -121,189 +121,6 @@ public:
|
||||
//! Get pointer to an animatable mesh. Loads the file if not loaded already.
|
||||
/**
|
||||
* If you want to remove a loaded mesh from the cache again, use removeMesh().
|
||||
* Currently there are the following mesh formats supported:
|
||||
* <TABLE border="1" cellpadding="2" cellspacing="0">
|
||||
* <TR>
|
||||
* <TD>Format</TD>
|
||||
* <TD>Description</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>3D Studio (.3ds)</TD>
|
||||
* <TD>Loader for 3D-Studio files which lots of 3D packages
|
||||
* are able to export. Only static meshes are currently
|
||||
* supported by this importer.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>3D World Studio (.smf)</TD>
|
||||
* <TD>Loader for Leadwerks SMF mesh files, a simple mesh format
|
||||
* containing static geometry for games. The proprietary .STF texture format
|
||||
* is not supported yet. This loader was originally written by Joseph Ellis. </TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Bliz Basic B3D (.b3d)</TD>
|
||||
* <TD>Loader for blitz basic files, developed by Mark
|
||||
* Sibly. This is the ideal animated mesh format for game
|
||||
* characters as it is both rigidly defined and widely
|
||||
* supported by modeling and animation software.
|
||||
* As this format supports skeletal animations, an
|
||||
* ISkinnedMesh will be returned by this importer.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Cartography shop 4 (.csm)</TD>
|
||||
* <TD>Cartography Shop is a modeling program for creating
|
||||
* architecture and calculating lighting. Irrlicht can
|
||||
* directly import .csm files thanks to the IrrCSM library
|
||||
* created by Saurav Mohapatra which is now integrated
|
||||
* directly in Irrlicht.
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Delgine DeleD (.dmf)</TD>
|
||||
* <TD>DeleD (delgine.com) is a 3D editor and level-editor
|
||||
* combined into one and is specifically designed for 3D
|
||||
* game-development. With this loader, it is possible to
|
||||
* directly load all geometry is as well as textures and
|
||||
* lightmaps from .dmf files. To set texture and
|
||||
* material paths, see scene::DMF_USE_MATERIALS_DIRS.
|
||||
* It is also possible to flip the alpha texture by setting
|
||||
* scene::DMF_FLIP_ALPHA_TEXTURES to true and to set the
|
||||
* material transparent reference value by setting
|
||||
* scene::DMF_ALPHA_CHANNEL_REF to a float between 0 and
|
||||
* 1. The loader is based on Salvatore Russo's .dmf
|
||||
* loader, I just changed some parts of it. Thanks to
|
||||
* Salvatore for his work and for allowing me to use his
|
||||
* code in Irrlicht and put it under Irrlicht's license.
|
||||
* For newer and more enhanced versions of the loader,
|
||||
* take a look at delgine.com.
|
||||
* </TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>DirectX (.x)</TD>
|
||||
* <TD>Platform independent importer (so not D3D-only) for
|
||||
* .x files. Most 3D packages can export these natively
|
||||
* and there are several tools for them available, e.g.
|
||||
* the Maya exporter included in the DX SDK.
|
||||
* .x files can include skeletal animations and Irrlicht
|
||||
* is able to play and display them, users can manipulate
|
||||
* the joints via the ISkinnedMesh interface. Currently,
|
||||
* Irrlicht only supports uncompressed .x files.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Half-Life model (.mdl)</TD>
|
||||
* <TD>This loader opens Half-life 1 models, it was contributed
|
||||
* by Fabio Concas and adapted by Thomas Alten.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>LightWave (.lwo)</TD>
|
||||
* <TD>Native to NewTek's LightWave 3D, the LWO format is well
|
||||
* known and supported by many exporters. This loader will
|
||||
* import LWO2 models including lightmaps, bumpmaps and
|
||||
* reflection textures.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Maya (.obj)</TD>
|
||||
* <TD>Most 3D software can create .obj files which contain
|
||||
* static geometry without material data. The material
|
||||
* files .mtl are also supported. This importer for
|
||||
* Irrlicht can load them directly. </TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Milkshape (.ms3d)</TD>
|
||||
* <TD>.MS3D files contain models and sometimes skeletal
|
||||
* animations from the Milkshape 3D modeling and animation
|
||||
* software. Like the other skeletal mesh loaders, joints
|
||||
* are exposed via the ISkinnedMesh animated mesh type.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>My3D (.my3d)</TD>
|
||||
* <TD>.my3D is a flexible 3D file format. The My3DTools
|
||||
* contains plug-ins to export .my3D files from several
|
||||
* 3D packages. With this built-in importer, Irrlicht
|
||||
* can read and display those files directly. This
|
||||
* loader was written by Zhuck Dimitry who also created
|
||||
* the whole My3DTools package.
|
||||
* </TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>OCT (.oct)</TD>
|
||||
* <TD>The oct file format contains 3D geometry and
|
||||
* lightmaps and can be loaded directly by Irrlicht. OCT
|
||||
* files<br> can be created by FSRad, Paul Nette's
|
||||
* radiosity processor or exported from Blender using
|
||||
* OCTTools which can be found in the exporters/OCTTools
|
||||
* directory of the SDK. Thanks to Murphy McCauley for
|
||||
* creating all this.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>OGRE Meshes (.mesh)</TD>
|
||||
* <TD>Ogre .mesh files contain 3D data for the OGRE 3D
|
||||
* engine. Irrlicht can read and display them directly
|
||||
* with this importer. To define materials for the mesh,
|
||||
* copy a .material file named like the corresponding
|
||||
* .mesh file where the .mesh file is. (For example
|
||||
* ogrehead.material for ogrehead.mesh). Thanks to
|
||||
* Christian Stehno who wrote and contributed this
|
||||
* loader.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Pulsar LMTools (.lmts)</TD>
|
||||
* <TD>LMTools is a set of tools (Windows & Linux) for
|
||||
* creating lightmaps. Irrlicht can directly read .lmts
|
||||
* files thanks to<br> the importer created by Jonas
|
||||
* Petersen.
|
||||
* Notes for<br> this version of the loader:<br>
|
||||
* - It does not recognize/support user data in the
|
||||
* *.lmts files.<br>
|
||||
* - The TGAs generated by LMTools don't work in
|
||||
* Irrlicht for some reason (the textures are upside
|
||||
* down). Opening and resaving them in a graphics app
|
||||
* will solve the problem.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Quake 3 levels (.bsp)</TD>
|
||||
* <TD>Quake 3 is a popular game by IDSoftware, and .pk3
|
||||
* files contain .bsp files and textures/lightmaps
|
||||
* describing huge prelighted levels. Irrlicht can read
|
||||
* .pk3 and .bsp files directly and thus render Quake 3
|
||||
* levels directly. Written by Nikolaus Gebhardt
|
||||
* enhanced by Dean P. Macri with the curved surfaces
|
||||
* feature. </TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Quake 2 models (.md2)</TD>
|
||||
* <TD>Quake 2 models are characters with morph target
|
||||
* animation. Irrlicht can read, display and animate
|
||||
* them directly with this importer. </TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Quake 3 models (.md3)</TD>
|
||||
* <TD>Quake 3 models are characters with morph target
|
||||
* animation, they contain mount points for weapons and body
|
||||
* parts and are typically made of several sections which are
|
||||
* manually joined together.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Stanford Triangle (.ply)</TD>
|
||||
* <TD>Invented by Stanford University and known as the native
|
||||
* format of the infamous "Stanford Bunny" model, this is a
|
||||
* popular static mesh format used by 3D scanning hardware
|
||||
* and software. This loader supports extremely large models
|
||||
* in both ASCII and binary format, but only has rudimentary
|
||||
* material support in the form of vertex colors and texture
|
||||
* coordinates.</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>Stereolithography (.stl)</TD>
|
||||
* <TD>The STL format is used for rapid prototyping and
|
||||
* computer-aided manufacturing, thus has no support for
|
||||
* materials.</TD>
|
||||
* </TR>
|
||||
* </TABLE>
|
||||
*
|
||||
* To load and display a mesh quickly, just do this:
|
||||
* \code
|
||||
* SceneManager->addAnimatedMeshSceneNode(
|
||||
* SceneManager->getMesh("yourmesh.3ds"));
|
||||
* \endcode
|
||||
* If you would like to implement and add your own file format loader to Irrlicht,
|
||||
* see addExternalMeshLoader().
|
||||
* \param file File handle of the mesh to load.
|
||||
@ -594,7 +411,7 @@ public:
|
||||
//! Get a skinned mesh, which is not available as header-only code
|
||||
/** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop()
|
||||
for details. */
|
||||
virtual ISkinnedMesh *createSkinnedMesh() = 0;
|
||||
virtual SkinnedMesh *createSkinnedMesh() = 0;
|
||||
|
||||
//! Get current render pass.
|
||||
virtual E_SCENE_NODE_RENDER_PASS getCurrentRenderPass() const = 0;
|
||||
|
@ -1,226 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrArray.h"
|
||||
#include "IAnimatedMesh.h"
|
||||
#include "SSkinMeshBuffer.h"
|
||||
#include "quaternion.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
enum E_INTERPOLATION_MODE
|
||||
{
|
||||
// constant does use the current key-values without interpolation
|
||||
EIM_CONSTANT = 0,
|
||||
|
||||
// linear interpolation
|
||||
EIM_LINEAR,
|
||||
|
||||
//! count of all available interpolation modes
|
||||
EIM_COUNT
|
||||
};
|
||||
|
||||
//! Interface for using some special functions of Skinned meshes
|
||||
class ISkinnedMesh : public IAnimatedMesh
|
||||
{
|
||||
public:
|
||||
//! Gets joint count.
|
||||
/** \return Amount of joints in the skeletal animated mesh. */
|
||||
virtual u32 getJointCount() const = 0;
|
||||
|
||||
//! Gets the name of a joint.
|
||||
/** \param number: Zero based index of joint. The last joint
|
||||
has the number getJointCount()-1;
|
||||
\return Name of joint and null if an error happened. */
|
||||
virtual const std::optional<std::string> &getJointName(u32 number) const = 0;
|
||||
|
||||
//! Gets a joint number from its name
|
||||
/** \param name: Name of the joint.
|
||||
\return Number of the joint or std::nullopt if not found. */
|
||||
virtual std::optional<u32> getJointNumber(const std::string &name) const = 0;
|
||||
|
||||
//! Use animation from another mesh
|
||||
/** The animation is linked (not copied) based on joint names
|
||||
so make sure they are unique.
|
||||
\return True if all joints in this mesh were
|
||||
matched up (empty names will not be matched, and it's case
|
||||
sensitive). Unmatched joints will not be animated. */
|
||||
virtual bool useAnimationFrom(const ISkinnedMesh *mesh) = 0;
|
||||
|
||||
//! Update Normals when Animating
|
||||
/** \param on If false don't animate, which is faster.
|
||||
Else update normals, which allows for proper lighting of
|
||||
animated meshes. */
|
||||
virtual void updateNormalsWhenAnimating(bool on) = 0;
|
||||
|
||||
//! Sets Interpolation Mode
|
||||
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode) = 0;
|
||||
|
||||
//! Animates this mesh's joints based on frame input
|
||||
virtual void animateMesh(f32 frame, f32 blend) = 0;
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
virtual void skinMesh() = 0;
|
||||
|
||||
//! converts the vertex type of all meshbuffers to tangents.
|
||||
/** E.g. used for bump mapping. */
|
||||
virtual void convertMeshToTangents() = 0;
|
||||
|
||||
//! Allows to enable hardware skinning.
|
||||
/* This feature is not implemented in Irrlicht yet */
|
||||
virtual bool setHardwareSkinning(bool on) = 0;
|
||||
|
||||
//! Refreshes vertex data cached in joints such as positions and normals
|
||||
virtual void refreshJointCache() = 0;
|
||||
|
||||
//! Moves the mesh into static position.
|
||||
virtual void resetAnimation() = 0;
|
||||
|
||||
//! A vertex weight
|
||||
struct SWeight
|
||||
{
|
||||
//! Index of the mesh buffer
|
||||
u16 buffer_id; // I doubt 32bits is needed
|
||||
|
||||
//! Index of the vertex
|
||||
u32 vertex_id; // Store global ID here
|
||||
|
||||
//! Weight Strength/Percentage (0-1)
|
||||
f32 strength;
|
||||
|
||||
private:
|
||||
//! Internal members used by CSkinnedMesh
|
||||
friend class CSkinnedMesh;
|
||||
char *Moved;
|
||||
core::vector3df StaticPos;
|
||||
core::vector3df StaticNormal;
|
||||
};
|
||||
|
||||
//! Animation keyframe which describes a new position
|
||||
struct SPositionKey
|
||||
{
|
||||
f32 frame;
|
||||
core::vector3df position;
|
||||
};
|
||||
|
||||
//! Animation keyframe which describes a new scale
|
||||
struct SScaleKey
|
||||
{
|
||||
f32 frame;
|
||||
core::vector3df scale;
|
||||
};
|
||||
|
||||
//! Animation keyframe which describes a new rotation
|
||||
struct SRotationKey
|
||||
{
|
||||
f32 frame;
|
||||
core::quaternion rotation;
|
||||
};
|
||||
|
||||
//! Joints
|
||||
struct SJoint
|
||||
{
|
||||
SJoint() :
|
||||
UseAnimationFrom(0), GlobalSkinningSpace(false),
|
||||
positionHint(-1), scaleHint(-1), rotationHint(-1)
|
||||
{
|
||||
}
|
||||
|
||||
//! The name of this joint
|
||||
std::optional<std::string> Name;
|
||||
|
||||
//! Local matrix of this joint
|
||||
core::matrix4 LocalMatrix;
|
||||
|
||||
//! List of child joints
|
||||
core::array<SJoint *> Children;
|
||||
|
||||
//! List of attached meshes
|
||||
core::array<u32> AttachedMeshes;
|
||||
|
||||
//! Animation keys causing translation change
|
||||
core::array<SPositionKey> PositionKeys;
|
||||
|
||||
//! Animation keys causing scale change
|
||||
core::array<SScaleKey> ScaleKeys;
|
||||
|
||||
//! Animation keys causing rotation change
|
||||
core::array<SRotationKey> RotationKeys;
|
||||
|
||||
//! Skin weights
|
||||
core::array<SWeight> Weights;
|
||||
|
||||
//! Unnecessary for loaders, will be overwritten on finalize
|
||||
core::matrix4 GlobalMatrix; // loaders may still choose to set this (temporarily) to calculate absolute vertex data.
|
||||
core::matrix4 GlobalAnimatedMatrix;
|
||||
core::matrix4 LocalAnimatedMatrix;
|
||||
|
||||
//! These should be set by loaders.
|
||||
core::vector3df Animatedposition;
|
||||
core::vector3df Animatedscale;
|
||||
core::quaternion Animatedrotation;
|
||||
|
||||
// The .x and .gltf formats pre-calculate this
|
||||
std::optional<core::matrix4> GlobalInversedMatrix;
|
||||
private:
|
||||
//! Internal members used by CSkinnedMesh
|
||||
friend class CSkinnedMesh;
|
||||
|
||||
SJoint *UseAnimationFrom;
|
||||
bool GlobalSkinningSpace;
|
||||
|
||||
s32 positionHint;
|
||||
s32 scaleHint;
|
||||
s32 rotationHint;
|
||||
};
|
||||
|
||||
// Interface for the mesh loaders (finalize should lock these functions, and they should have some prefix like loader_
|
||||
|
||||
// these functions will use the needed arrays, set values, etc to help the loaders
|
||||
|
||||
//! exposed for loaders: to add mesh buffers
|
||||
virtual core::array<SSkinMeshBuffer *> &getMeshBuffers() = 0;
|
||||
|
||||
//! exposed for loaders: joints list
|
||||
virtual core::array<SJoint *> &getAllJoints() = 0;
|
||||
|
||||
//! exposed for loaders: joints list
|
||||
virtual const core::array<SJoint *> &getAllJoints() const = 0;
|
||||
|
||||
//! loaders should call this after populating the mesh
|
||||
virtual void finalize() = 0;
|
||||
|
||||
//! Adds a new meshbuffer to the mesh, access it as last one
|
||||
virtual SSkinMeshBuffer *addMeshBuffer() = 0;
|
||||
|
||||
//! Adds a new meshbuffer to the mesh, access it as last one
|
||||
virtual void addMeshBuffer(SSkinMeshBuffer *meshbuf) = 0;
|
||||
|
||||
//! Adds a new joint to the mesh, access it as last one
|
||||
virtual SJoint *addJoint(SJoint *parent = 0) = 0;
|
||||
|
||||
//! Adds a new weight to the mesh, access it as last one
|
||||
virtual SWeight *addWeight(SJoint *joint) = 0;
|
||||
|
||||
//! Adds a new position key to the mesh, access it as last one
|
||||
virtual SPositionKey *addPositionKey(SJoint *joint) = 0;
|
||||
//! Adds a new scale key to the mesh, access it as last one
|
||||
virtual SScaleKey *addScaleKey(SJoint *joint) = 0;
|
||||
//! Adds a new rotation key to the mesh, access it as last one
|
||||
virtual SRotationKey *addRotationKey(SJoint *joint) = 0;
|
||||
|
||||
//! Check if the mesh is non-animated
|
||||
virtual bool isStatic() = 0;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
@ -2,32 +2,46 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// New skinned mesh
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IAnimatedMesh.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ISkinnedMesh.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "SSkinMeshBuffer.h"
|
||||
#include "quaternion.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
enum E_INTERPOLATION_MODE
|
||||
{
|
||||
// constant does use the current key-values without interpolation
|
||||
EIM_CONSTANT = 0,
|
||||
|
||||
// linear interpolation
|
||||
EIM_LINEAR,
|
||||
|
||||
//! count of all available interpolation modes
|
||||
EIM_COUNT
|
||||
};
|
||||
|
||||
class IAnimatedMeshSceneNode;
|
||||
class IBoneSceneNode;
|
||||
class ISceneManager;
|
||||
|
||||
class CSkinnedMesh : public ISkinnedMesh
|
||||
class SkinnedMesh : public IAnimatedMesh
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CSkinnedMesh();
|
||||
SkinnedMesh();
|
||||
|
||||
//! destructor
|
||||
virtual ~CSkinnedMesh();
|
||||
virtual ~SkinnedMesh();
|
||||
|
||||
//! If the duration is 0, it is a static (=non animated) mesh.
|
||||
f32 getMaxFrameNumber() const override;
|
||||
@ -46,10 +60,10 @@ public:
|
||||
|
||||
//! Animates this mesh's joints based on frame input
|
||||
//! blend: {0-old position, 1-New position}
|
||||
void animateMesh(f32 frame, f32 blend) override;
|
||||
void animateMesh(f32 frame, f32 blend);
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
void skinMesh() override;
|
||||
//! Performs a software skin on this mesh based of joint positions
|
||||
void skinMesh();
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
u32 getMeshBufferCount() const override;
|
||||
@ -83,83 +97,53 @@ public:
|
||||
E_ANIMATED_MESH_TYPE getMeshType() const override;
|
||||
|
||||
//! Gets joint count.
|
||||
u32 getJointCount() const override;
|
||||
u32 getJointCount() const;
|
||||
|
||||
//! Gets the name of a joint.
|
||||
const std::optional<std::string> &getJointName(u32 number) const override;
|
||||
/** \param number: Zero based index of joint.
|
||||
\return Name of joint and null if an error happened. */
|
||||
const std::optional<std::string> &getJointName(u32 number) const;
|
||||
|
||||
//! Gets a joint number from its name
|
||||
std::optional<u32> getJointNumber(const std::string &name) const override;
|
||||
|
||||
//! uses animation from another mesh
|
||||
bool useAnimationFrom(const ISkinnedMesh *mesh) override;
|
||||
/** \param name: Name of the joint.
|
||||
\return Number of the joint or std::nullopt if not found. */
|
||||
std::optional<u32> getJointNumber(const std::string &name) const;
|
||||
|
||||
//! Update Normals when Animating
|
||||
//! False= Don't (default)
|
||||
//! True = Update normals, slower
|
||||
void updateNormalsWhenAnimating(bool on) override;
|
||||
/** \param on If false don't animate, which is faster.
|
||||
Else update normals, which allows for proper lighting of
|
||||
animated meshes. */
|
||||
void updateNormalsWhenAnimating(bool on);
|
||||
|
||||
//! Sets Interpolation Mode
|
||||
void setInterpolationMode(E_INTERPOLATION_MODE mode) override;
|
||||
void setInterpolationMode(E_INTERPOLATION_MODE mode);
|
||||
|
||||
//! Convertes the mesh to contain tangent information
|
||||
void convertMeshToTangents() override;
|
||||
//! converts the vertex type of all meshbuffers to tangents.
|
||||
/** E.g. used for bump mapping. */
|
||||
void convertMeshToTangents();
|
||||
|
||||
//! Does the mesh have no animation
|
||||
bool isStatic() override;
|
||||
bool isStatic() const;
|
||||
|
||||
//! (This feature is not implemented in irrlicht yet)
|
||||
bool setHardwareSkinning(bool on) override;
|
||||
//! Allows to enable hardware skinning.
|
||||
/* This feature is not implemented in Irrlicht yet */
|
||||
bool setHardwareSkinning(bool on);
|
||||
|
||||
//! Refreshes vertex data cached in joints such as positions and normals
|
||||
void refreshJointCache() override;
|
||||
void refreshJointCache();
|
||||
|
||||
//! Moves the mesh into static position.
|
||||
void resetAnimation() override;
|
||||
void resetAnimation();
|
||||
|
||||
// Interface for the mesh loaders (finalize should lock these functions, and they should have some prefix like loader_
|
||||
// these functions will use the needed arrays, set values, etc to help the loaders
|
||||
|
||||
//! exposed for loaders to add mesh buffers
|
||||
core::array<SSkinMeshBuffer *> &getMeshBuffers() override;
|
||||
|
||||
//! alternative method for adding joints
|
||||
core::array<SJoint *> &getAllJoints() override;
|
||||
|
||||
//! alternative method for adding joints
|
||||
const core::array<SJoint *> &getAllJoints() const override;
|
||||
|
||||
//! loaders should call this after populating the mesh
|
||||
void finalize() override;
|
||||
|
||||
//! Adds a new meshbuffer to the mesh, access it as last one
|
||||
SSkinMeshBuffer *addMeshBuffer() override;
|
||||
|
||||
//! Adds a new meshbuffer to the mesh, access it as last one
|
||||
void addMeshBuffer(SSkinMeshBuffer *meshbuf) override;
|
||||
|
||||
//! Adds a new joint to the mesh, access it as last one
|
||||
SJoint *addJoint(SJoint *parent = 0) override;
|
||||
|
||||
//! Adds a new position key to the mesh, access it as last one
|
||||
SPositionKey *addPositionKey(SJoint *joint) override;
|
||||
//! Adds a new rotation key to the mesh, access it as last one
|
||||
SRotationKey *addRotationKey(SJoint *joint) override;
|
||||
//! Adds a new scale key to the mesh, access it as last one
|
||||
SScaleKey *addScaleKey(SJoint *joint) override;
|
||||
|
||||
//! Adds a new weight to the mesh, access it as last one
|
||||
SWeight *addWeight(SJoint *joint) override;
|
||||
|
||||
virtual void updateBoundingBox(void);
|
||||
virtual void updateBoundingBox();
|
||||
|
||||
//! Recovers the joints from the mesh
|
||||
void recoverJointsFromMesh(core::array<IBoneSceneNode *> &jointChildSceneNodes);
|
||||
|
||||
//! Tranfers the joint data to the mesh
|
||||
//! Transfers the joint data to the mesh
|
||||
void transferJointsToMesh(const core::array<IBoneSceneNode *> &jointChildSceneNodes);
|
||||
|
||||
//! Tranfers the joint hints to the mesh
|
||||
//! Transfers the joint hints to the mesh
|
||||
void transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNode *> &jointChildSceneNodes);
|
||||
|
||||
//! Creates an array of joints from this mesh as children of node
|
||||
@ -167,6 +151,138 @@ public:
|
||||
IAnimatedMeshSceneNode *node,
|
||||
ISceneManager *smgr);
|
||||
|
||||
//! A vertex weight
|
||||
struct SWeight
|
||||
{
|
||||
//! Index of the mesh buffer
|
||||
u16 buffer_id; // I doubt 32bits is needed
|
||||
|
||||
//! Index of the vertex
|
||||
u32 vertex_id; // Store global ID here
|
||||
|
||||
//! Weight Strength/Percentage (0-1)
|
||||
f32 strength;
|
||||
|
||||
private:
|
||||
//! Internal members used by SkinnedMesh
|
||||
friend class SkinnedMesh;
|
||||
char *Moved;
|
||||
core::vector3df StaticPos;
|
||||
core::vector3df StaticNormal;
|
||||
};
|
||||
|
||||
//! Animation keyframe which describes a new position
|
||||
struct SPositionKey
|
||||
{
|
||||
f32 frame;
|
||||
core::vector3df position;
|
||||
};
|
||||
|
||||
//! Animation keyframe which describes a new scale
|
||||
struct SScaleKey
|
||||
{
|
||||
f32 frame;
|
||||
core::vector3df scale;
|
||||
};
|
||||
|
||||
//! Animation keyframe which describes a new rotation
|
||||
struct SRotationKey
|
||||
{
|
||||
f32 frame;
|
||||
core::quaternion rotation;
|
||||
};
|
||||
|
||||
//! Joints
|
||||
struct SJoint
|
||||
{
|
||||
SJoint() :
|
||||
UseAnimationFrom(0), GlobalSkinningSpace(false),
|
||||
positionHint(-1), scaleHint(-1), rotationHint(-1)
|
||||
{
|
||||
}
|
||||
|
||||
//! The name of this joint
|
||||
std::optional<std::string> Name;
|
||||
|
||||
//! Local matrix of this joint
|
||||
core::matrix4 LocalMatrix;
|
||||
|
||||
//! List of child joints
|
||||
core::array<SJoint *> Children;
|
||||
|
||||
//! List of attached meshes
|
||||
core::array<u32> AttachedMeshes;
|
||||
|
||||
//! Animation keys causing translation change
|
||||
core::array<SPositionKey> PositionKeys;
|
||||
|
||||
//! Animation keys causing scale change
|
||||
core::array<SScaleKey> ScaleKeys;
|
||||
|
||||
//! Animation keys causing rotation change
|
||||
core::array<SRotationKey> RotationKeys;
|
||||
|
||||
//! Skin weights
|
||||
core::array<SWeight> Weights;
|
||||
|
||||
//! Unnecessary for loaders, will be overwritten on finalize
|
||||
core::matrix4 GlobalMatrix; // loaders may still choose to set this (temporarily) to calculate absolute vertex data.
|
||||
core::matrix4 GlobalAnimatedMatrix;
|
||||
core::matrix4 LocalAnimatedMatrix;
|
||||
|
||||
//! These should be set by loaders.
|
||||
core::vector3df Animatedposition;
|
||||
core::vector3df Animatedscale;
|
||||
core::quaternion Animatedrotation;
|
||||
|
||||
// The .x and .gltf formats pre-calculate this
|
||||
std::optional<core::matrix4> GlobalInversedMatrix;
|
||||
private:
|
||||
//! Internal members used by SkinnedMesh
|
||||
friend class SkinnedMesh;
|
||||
|
||||
SJoint *UseAnimationFrom;
|
||||
bool GlobalSkinningSpace;
|
||||
|
||||
s32 positionHint;
|
||||
s32 scaleHint;
|
||||
s32 rotationHint;
|
||||
};
|
||||
|
||||
// Interface for the mesh loaders (finalize should lock these functions, and they should have some prefix like loader_
|
||||
// these functions will use the needed arrays, set values, etc to help the loaders
|
||||
|
||||
//! exposed for loaders to add mesh buffers
|
||||
core::array<SSkinMeshBuffer *> &getMeshBuffers();
|
||||
|
||||
//! alternative method for adding joints
|
||||
core::array<SJoint *> &getAllJoints();
|
||||
|
||||
//! alternative method for reading joints
|
||||
const core::array<SJoint *> &getAllJoints() const;
|
||||
|
||||
//! loaders should call this after populating the mesh
|
||||
void finalize();
|
||||
|
||||
//! Adds a new meshbuffer to the mesh, access it as last one
|
||||
SSkinMeshBuffer *addMeshBuffer();
|
||||
|
||||
//! Adds a new meshbuffer to the mesh, access it as last one
|
||||
void addMeshBuffer(SSkinMeshBuffer *meshbuf);
|
||||
|
||||
//! Adds a new joint to the mesh, access it as last one
|
||||
SJoint *addJoint(SJoint *parent = 0);
|
||||
|
||||
//! Adds a new position key to the mesh, access it as last one
|
||||
SPositionKey *addPositionKey(SJoint *joint);
|
||||
//! Adds a new rotation key to the mesh, access it as last one
|
||||
SRotationKey *addRotationKey(SJoint *joint);
|
||||
//! Adds a new scale key to the mesh, access it as last one
|
||||
SScaleKey *addScaleKey(SJoint *joint);
|
||||
|
||||
//! Adds a new weight to the mesh, access it as last one
|
||||
SWeight *addWeight(SJoint *joint);
|
||||
|
||||
private:
|
||||
void checkForAnimation();
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "ISceneManager.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "os.h"
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "SkinnedMesh.h"
|
||||
#include "IDummyTransformationSceneNode.h"
|
||||
#include "IBoneSceneNode.h"
|
||||
#include "IMaterialRenderer.h"
|
||||
@ -165,7 +165,7 @@ IMesh *CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||
// As multiple scene nodes may be sharing the same skinned mesh, we have to
|
||||
// re-animate it every frame to ensure that this node gets the mesh that it needs.
|
||||
|
||||
CSkinnedMesh *skinnedMesh = static_cast<CSkinnedMesh *>(Mesh);
|
||||
SkinnedMesh *skinnedMesh = static_cast<SkinnedMesh *>(Mesh);
|
||||
|
||||
if (JointMode == EJUOR_CONTROL) // write to mesh
|
||||
skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
|
||||
@ -299,8 +299,8 @@ void CAnimatedMeshSceneNode::render()
|
||||
if (Mesh->getMeshType() == EAMT_SKINNED) {
|
||||
// draw skeleton
|
||||
|
||||
for (u32 g = 0; g < ((ISkinnedMesh *)Mesh)->getAllJoints().size(); ++g) {
|
||||
ISkinnedMesh::SJoint *joint = ((ISkinnedMesh *)Mesh)->getAllJoints()[g];
|
||||
for (u32 g = 0; g < ((SkinnedMesh *)Mesh)->getAllJoints().size(); ++g) {
|
||||
auto *joint = ((SkinnedMesh *)Mesh)->getAllJoints()[g];
|
||||
|
||||
for (u32 n = 0; n < joint->Children.size(); ++n) {
|
||||
driver->draw3DLine(joint->GlobalAnimatedMatrix.getTranslation(),
|
||||
@ -404,7 +404,7 @@ IBoneSceneNode *CAnimatedMeshSceneNode::getJointNode(const c8 *jointName)
|
||||
|
||||
checkJoints();
|
||||
|
||||
ISkinnedMesh *skinnedMesh = (ISkinnedMesh *)Mesh;
|
||||
auto *skinnedMesh = (SkinnedMesh *)Mesh;
|
||||
|
||||
const std::optional<u32> number = skinnedMesh->getJointNumber(jointName);
|
||||
|
||||
@ -446,7 +446,7 @@ u32 CAnimatedMeshSceneNode::getJointCount() const
|
||||
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
|
||||
return 0;
|
||||
|
||||
ISkinnedMesh *skinnedMesh = (ISkinnedMesh *)Mesh;
|
||||
auto *skinnedMesh = (SkinnedMesh *)Mesh;
|
||||
|
||||
return skinnedMesh->getJointCount();
|
||||
}
|
||||
@ -596,7 +596,7 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
|
||||
checkJoints();
|
||||
const f32 frame = getFrameNr(); // old?
|
||||
|
||||
CSkinnedMesh *skinnedMesh = static_cast<CSkinnedMesh *>(Mesh);
|
||||
SkinnedMesh *skinnedMesh = static_cast<SkinnedMesh *>(Mesh);
|
||||
|
||||
skinnedMesh->transferOnlyJointsHintsToMesh(JointChildSceneNodes);
|
||||
skinnedMesh->animateMesh(frame, 1.0f);
|
||||
@ -671,8 +671,8 @@ void CAnimatedMeshSceneNode::checkJoints()
|
||||
JointChildSceneNodes.clear();
|
||||
|
||||
// Create joints for SkinnedMesh
|
||||
((CSkinnedMesh *)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager);
|
||||
((CSkinnedMesh *)Mesh)->recoverJointsFromMesh(JointChildSceneNodes);
|
||||
((SkinnedMesh *)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager);
|
||||
((SkinnedMesh *)Mesh)->recoverJointsFromMesh(JointChildSceneNodes);
|
||||
|
||||
JointsUsed = true;
|
||||
JointMode = EJUOR_READ;
|
||||
|
@ -51,7 +51,7 @@ IAnimatedMesh *CB3DMeshFileLoader::createMesh(io::IReadFile *file)
|
||||
return 0;
|
||||
|
||||
B3DFile = file;
|
||||
AnimatedMesh = new scene::CSkinnedMesh();
|
||||
AnimatedMesh = new scene::SkinnedMesh();
|
||||
ShowWarning = true; // If true a warning is issued if too many textures are used
|
||||
VerticesStart = 0;
|
||||
|
||||
@ -111,7 +111,7 @@ bool CB3DMeshFileLoader::load()
|
||||
if (!readChunkBRUS())
|
||||
return false;
|
||||
} else if (strncmp(B3dStack.getLast().name, "NODE", 4) == 0) {
|
||||
if (!readChunkNODE((CSkinnedMesh::SJoint *)0))
|
||||
if (!readChunkNODE((SkinnedMesh::SJoint *)0))
|
||||
return false;
|
||||
} else {
|
||||
os::Printer::log("Unknown chunk found in mesh base - skipping");
|
||||
@ -133,9 +133,9 @@ bool CB3DMeshFileLoader::load()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *inJoint)
|
||||
bool CB3DMeshFileLoader::readChunkNODE(SkinnedMesh::SJoint *inJoint)
|
||||
{
|
||||
CSkinnedMesh::SJoint *joint = AnimatedMesh->addJoint(inJoint);
|
||||
SkinnedMesh::SJoint *joint = AnimatedMesh->addJoint(inJoint);
|
||||
joint->Name = readString();
|
||||
|
||||
#ifdef _B3D_READER_DEBUG
|
||||
@ -211,7 +211,7 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *inJoint)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *inJoint)
|
||||
bool CB3DMeshFileLoader::readChunkMESH(SkinnedMesh::SJoint *inJoint)
|
||||
{
|
||||
#ifdef _B3D_READER_DEBUG
|
||||
core::stringc logStr;
|
||||
@ -302,7 +302,7 @@ VRTS:
|
||||
float tex_coords[tex_coord_sets][tex_coord_set_size] ;tex coords
|
||||
}
|
||||
*/
|
||||
bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *inJoint)
|
||||
bool CB3DMeshFileLoader::readChunkVRTS(SkinnedMesh::SJoint *inJoint)
|
||||
{
|
||||
#ifdef _B3D_READER_DEBUG
|
||||
core::stringc logStr;
|
||||
@ -521,7 +521,7 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *meshBuffer, u32 m
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *inJoint)
|
||||
bool CB3DMeshFileLoader::readChunkBONE(SkinnedMesh::SJoint *inJoint)
|
||||
{
|
||||
#ifdef _B3D_READER_DEBUG
|
||||
core::stringc logStr;
|
||||
@ -552,7 +552,7 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *inJoint)
|
||||
if (AnimatedVertices_VertexID[globalVertexID] == -1) {
|
||||
os::Printer::log("B3dMeshLoader: Weight has bad vertex id (no link to meshbuffer index found)");
|
||||
} else if (strength > 0) {
|
||||
CSkinnedMesh::SWeight *weight = AnimatedMesh->addWeight(inJoint);
|
||||
SkinnedMesh::SWeight *weight = AnimatedMesh->addWeight(inJoint);
|
||||
weight->strength = strength;
|
||||
// Find the meshbuffer and Vertex index from the Global Vertex ID:
|
||||
weight->vertex_id = AnimatedVertices_VertexID[globalVertexID];
|
||||
@ -565,7 +565,7 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *inJoint)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *inJoint)
|
||||
bool CB3DMeshFileLoader::readChunkKEYS(SkinnedMesh::SJoint *inJoint)
|
||||
{
|
||||
#ifdef _B3D_READER_DEBUG
|
||||
// Only print first, that's just too much output otherwise
|
||||
@ -584,11 +584,11 @@ bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *inJoint)
|
||||
flags = os::Byteswap::byteswap(flags);
|
||||
#endif
|
||||
|
||||
CSkinnedMesh::SPositionKey *oldPosKey = 0;
|
||||
SkinnedMesh::SPositionKey *oldPosKey = 0;
|
||||
core::vector3df oldPos[2];
|
||||
CSkinnedMesh::SScaleKey *oldScaleKey = 0;
|
||||
SkinnedMesh::SScaleKey *oldScaleKey = 0;
|
||||
core::vector3df oldScale[2];
|
||||
CSkinnedMesh::SRotationKey *oldRotKey = 0;
|
||||
SkinnedMesh::SRotationKey *oldRotKey = 0;
|
||||
core::quaternion oldRot[2];
|
||||
bool isFirst[3] = {true, true, true};
|
||||
while ((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "SkinnedMesh.h"
|
||||
#include "SB3DStructs.h"
|
||||
#include "IReadFile.h"
|
||||
|
||||
@ -39,12 +39,12 @@ public:
|
||||
|
||||
private:
|
||||
bool load();
|
||||
bool readChunkNODE(CSkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkMESH(CSkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkVRTS(CSkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkNODE(SkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkMESH(SkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkVRTS(SkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 Vertices_Start);
|
||||
bool readChunkBONE(CSkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkKEYS(CSkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkBONE(SkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkKEYS(SkinnedMesh::SJoint *InJoint);
|
||||
bool readChunkANIM();
|
||||
bool readChunkTEXS();
|
||||
bool readChunkBRUS();
|
||||
@ -63,7 +63,7 @@ private:
|
||||
|
||||
core::array<video::S3DVertex2TCoords> BaseVertices;
|
||||
|
||||
CSkinnedMesh *AnimatedMesh;
|
||||
SkinnedMesh *AnimatedMesh;
|
||||
io::IReadFile *B3DFile;
|
||||
|
||||
// B3Ds have Vertex ID's local within the mesh I don't want this
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "SMaterialLayer.h"
|
||||
#include "coreutil.h"
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "SkinnedMesh.h"
|
||||
#include "IAnimatedMesh.h"
|
||||
#include "IReadFile.h"
|
||||
#include "irrTypes.h"
|
||||
@ -344,7 +344,7 @@ IAnimatedMesh* SelfType::createMesh(io::IReadFile* file)
|
||||
const char *filename = file->getFileName().c_str();
|
||||
try {
|
||||
tiniergltf::GlTF model = parseGLTF(file);
|
||||
irr_ptr<CSkinnedMesh> mesh(new CSkinnedMesh());
|
||||
irr_ptr<SkinnedMesh> mesh(new SkinnedMesh());
|
||||
MeshExtractor extractor(std::move(model), mesh.get());
|
||||
try {
|
||||
extractor.load();
|
||||
@ -410,7 +410,7 @@ static video::E_TEXTURE_CLAMP convertTextureWrap(const Wrap wrap) {
|
||||
void SelfType::MeshExtractor::addPrimitive(
|
||||
const tiniergltf::MeshPrimitive &primitive,
|
||||
const std::optional<std::size_t> skinIdx,
|
||||
CSkinnedMesh::SJoint *parent)
|
||||
SkinnedMesh::SJoint *parent)
|
||||
{
|
||||
auto vertices = getVertices(primitive);
|
||||
if (!vertices.has_value())
|
||||
@ -510,7 +510,7 @@ void SelfType::MeshExtractor::addPrimitive(
|
||||
if (strength == 0)
|
||||
continue;
|
||||
|
||||
CSkinnedMesh::SWeight *weight = m_irr_model->addWeight(m_loaded_nodes.at(skin.joints.at(jointIdx)));
|
||||
SkinnedMesh::SWeight *weight = m_irr_model->addWeight(m_loaded_nodes.at(skin.joints.at(jointIdx)));
|
||||
weight->buffer_id = meshbufNr;
|
||||
weight->vertex_id = v;
|
||||
weight->strength = strength;
|
||||
@ -527,7 +527,7 @@ void SelfType::MeshExtractor::addPrimitive(
|
||||
void SelfType::MeshExtractor::deferAddMesh(
|
||||
const std::size_t meshIdx,
|
||||
const std::optional<std::size_t> skinIdx,
|
||||
CSkinnedMesh::SJoint *parent)
|
||||
SkinnedMesh::SJoint *parent)
|
||||
{
|
||||
m_mesh_loaders.emplace_back([=] {
|
||||
for (std::size_t pi = 0; pi < getPrimitiveCount(meshIdx); ++pi) {
|
||||
@ -547,7 +547,7 @@ static const core::matrix4 leftToRight = core::matrix4(
|
||||
);
|
||||
static const core::matrix4 rightToLeft = leftToRight;
|
||||
|
||||
static core::matrix4 loadTransform(const tiniergltf::Node::Matrix &m, CSkinnedMesh::SJoint *joint)
|
||||
static core::matrix4 loadTransform(const tiniergltf::Node::Matrix &m, SkinnedMesh::SJoint *joint)
|
||||
{
|
||||
// Note: Under the hood, this casts these doubles to floats.
|
||||
core::matrix4 mat = convertHandedness(core::matrix4(
|
||||
@ -576,7 +576,7 @@ static core::matrix4 loadTransform(const tiniergltf::Node::Matrix &m, CSkinnedMe
|
||||
return mat;
|
||||
}
|
||||
|
||||
static core::matrix4 loadTransform(const tiniergltf::Node::TRS &trs, CSkinnedMesh::SJoint *joint)
|
||||
static core::matrix4 loadTransform(const tiniergltf::Node::TRS &trs, SkinnedMesh::SJoint *joint)
|
||||
{
|
||||
const auto &trans = trs.translation;
|
||||
const auto &rot = trs.rotation;
|
||||
@ -594,7 +594,7 @@ static core::matrix4 loadTransform(const tiniergltf::Node::TRS &trs, CSkinnedMes
|
||||
}
|
||||
|
||||
static core::matrix4 loadTransform(std::optional<std::variant<tiniergltf::Node::Matrix, tiniergltf::Node::TRS>> transform,
|
||||
CSkinnedMesh::SJoint *joint) {
|
||||
SkinnedMesh::SJoint *joint) {
|
||||
if (!transform.has_value()) {
|
||||
return core::matrix4();
|
||||
}
|
||||
@ -603,7 +603,7 @@ static core::matrix4 loadTransform(std::optional<std::variant<tiniergltf::Node::
|
||||
|
||||
void SelfType::MeshExtractor::loadNode(
|
||||
const std::size_t nodeIdx,
|
||||
CSkinnedMesh::SJoint *parent)
|
||||
SkinnedMesh::SJoint *parent)
|
||||
{
|
||||
const auto &node = m_gltf_model.nodes->at(nodeIdx);
|
||||
auto *joint = m_irr_model->addJoint(parent);
|
||||
@ -626,7 +626,7 @@ void SelfType::MeshExtractor::loadNode(
|
||||
|
||||
void SelfType::MeshExtractor::loadNodes()
|
||||
{
|
||||
m_loaded_nodes = std::vector<CSkinnedMesh::SJoint *>(m_gltf_model.nodes->size());
|
||||
m_loaded_nodes = std::vector<SkinnedMesh::SJoint *>(m_gltf_model.nodes->size());
|
||||
|
||||
std::vector<bool> isChild(m_gltf_model.nodes->size());
|
||||
for (const auto &node : *m_gltf_model.nodes) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "SkinnedMesh.h"
|
||||
#include "IMeshLoader.h"
|
||||
#include "IReadFile.h"
|
||||
#include "irrTypes.h"
|
||||
@ -100,7 +100,7 @@ private:
|
||||
{
|
||||
public:
|
||||
MeshExtractor(tiniergltf::GlTF &&model,
|
||||
CSkinnedMesh *mesh) noexcept
|
||||
SkinnedMesh *mesh) noexcept
|
||||
: m_gltf_model(std::move(model)), m_irr_model(mesh) {};
|
||||
|
||||
/* Gets indices for the given mesh/primitive.
|
||||
@ -124,10 +124,10 @@ private:
|
||||
|
||||
private:
|
||||
const tiniergltf::GlTF m_gltf_model;
|
||||
CSkinnedMesh *m_irr_model;
|
||||
SkinnedMesh *m_irr_model;
|
||||
|
||||
std::vector<std::function<void()>> m_mesh_loaders;
|
||||
std::vector<CSkinnedMesh::SJoint *> m_loaded_nodes;
|
||||
std::vector<SkinnedMesh::SJoint *> m_loaded_nodes;
|
||||
|
||||
std::vector<std::string> warnings;
|
||||
void warn(const std::string &warning) {
|
||||
@ -145,13 +145,13 @@ private:
|
||||
|
||||
void addPrimitive(const tiniergltf::MeshPrimitive &primitive,
|
||||
const std::optional<std::size_t> skinIdx,
|
||||
CSkinnedMesh::SJoint *parent);
|
||||
SkinnedMesh::SJoint *parent);
|
||||
|
||||
void deferAddMesh(const std::size_t meshIdx,
|
||||
const std::optional<std::size_t> skinIdx,
|
||||
CSkinnedMesh::SJoint *parentJoint);
|
||||
SkinnedMesh::SJoint *parentJoint);
|
||||
|
||||
void loadNode(const std::size_t nodeIdx, CSkinnedMesh::SJoint *parentJoint);
|
||||
void loadNode(const std::size_t nodeIdx, SkinnedMesh::SJoint *parentJoint);
|
||||
|
||||
void loadNodes();
|
||||
|
||||
|
@ -308,7 +308,7 @@ set(IRRMESHLOADER
|
||||
)
|
||||
|
||||
add_library(IRRMESHOBJ OBJECT
|
||||
CSkinnedMesh.cpp
|
||||
SkinnedMesh.cpp
|
||||
CBoneSceneNode.cpp
|
||||
CMeshSceneNode.cpp
|
||||
CAnimatedMeshSceneNode.cpp
|
||||
|
@ -3,7 +3,7 @@
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CMeshManipulator.h"
|
||||
#include "ISkinnedMesh.h"
|
||||
#include "SkinnedMesh.h"
|
||||
#include "SMesh.h"
|
||||
#include "CMeshBuffer.h"
|
||||
#include "SAnimatedMesh.h"
|
||||
@ -101,7 +101,7 @@ void CMeshManipulator::recalculateNormals(scene::IMesh *mesh, bool smooth, bool
|
||||
return;
|
||||
|
||||
if (mesh->getMeshType() == EAMT_SKINNED) {
|
||||
ISkinnedMesh *smesh = (ISkinnedMesh *)mesh;
|
||||
auto *smesh = (SkinnedMesh *)mesh;
|
||||
smesh->resetAnimation();
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ void CMeshManipulator::recalculateNormals(scene::IMesh *mesh, bool smooth, bool
|
||||
recalculateNormals(mesh->getMeshBuffer(b), smooth, angleWeighted);
|
||||
|
||||
if (mesh->getMeshType() == EAMT_SKINNED) {
|
||||
ISkinnedMesh *smesh = (ISkinnedMesh *)mesh;
|
||||
auto *smesh = (SkinnedMesh *)mesh;
|
||||
smesh->refreshJointCache();
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,8 @@
|
||||
#include "CMeshSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "IMeshCache.h"
|
||||
#include "IAnimatedMesh.h"
|
||||
#include "IMeshBuffer.h"
|
||||
#include "IMaterialRenderer.h"
|
||||
#include "IFileSystem.h"
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "SkinnedMesh.h"
|
||||
#include "CXMeshFileLoader.h"
|
||||
#include "COBJMeshFileLoader.h"
|
||||
#include "CB3DMeshFileLoader.h"
|
||||
@ -771,9 +771,9 @@ ISceneManager *CSceneManager::createNewSceneManager(bool cloneContent)
|
||||
}
|
||||
|
||||
//! Get a skinned mesh, which is not available as header-only code
|
||||
ISkinnedMesh *CSceneManager::createSkinnedMesh()
|
||||
SkinnedMesh *CSceneManager::createSkinnedMesh()
|
||||
{
|
||||
return new CSkinnedMesh();
|
||||
return new SkinnedMesh();
|
||||
}
|
||||
|
||||
// creates a scenemanager
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SkinnedMesh.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ISceneNode.h"
|
||||
#include "ICursorControl.h"
|
||||
@ -22,6 +23,8 @@ namespace scene
|
||||
{
|
||||
class IMeshCache;
|
||||
|
||||
class SkinnedMesh;
|
||||
|
||||
/*!
|
||||
The Scene Manager manages scene nodes, mesh resources, cameras and all the other stuff.
|
||||
*/
|
||||
@ -167,8 +170,8 @@ public:
|
||||
//! Returns type of the scene node
|
||||
ESCENE_NODE_TYPE getType() const override { return ESNT_SCENE_MANAGER; }
|
||||
|
||||
//! Get a skinned mesh, which is not available as header-only code
|
||||
ISkinnedMesh *createSkinnedMesh() override;
|
||||
//! Get a skinned mesh
|
||||
SkinnedMesh *createSkinnedMesh() override;
|
||||
|
||||
//! Get current render time.
|
||||
E_SCENE_NODE_RENDER_PASS getCurrentRenderPass() const override { return CurrentRenderPass; }
|
||||
|
@ -57,7 +57,7 @@ IAnimatedMesh *CXMeshFileLoader::createMesh(io::IReadFile *file)
|
||||
u32 time = os::Timer::getRealTime();
|
||||
#endif
|
||||
|
||||
AnimatedMesh = new CSkinnedMesh();
|
||||
AnimatedMesh = new SkinnedMesh();
|
||||
|
||||
if (load(file)) {
|
||||
AnimatedMesh->finalize();
|
||||
@ -203,8 +203,8 @@ bool CXMeshFileLoader::load(io::IReadFile *file)
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < mesh->WeightJoint.size(); ++j) {
|
||||
ISkinnedMesh::SJoint *joint = AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]];
|
||||
ISkinnedMesh::SWeight &weight = joint->Weights[mesh->WeightNum[j]];
|
||||
SkinnedMesh::SJoint *joint = AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]];
|
||||
SkinnedMesh::SWeight &weight = joint->Weights[mesh->WeightNum[j]];
|
||||
|
||||
u32 id = weight.vertex_id;
|
||||
|
||||
@ -219,7 +219,7 @@ bool CXMeshFileLoader::load(io::IReadFile *file)
|
||||
weight.buffer_id = verticesLinkBuffer[id][0];
|
||||
} else if (verticesLinkBuffer[id].size() != 0) {
|
||||
for (u32 k = 1; k < verticesLinkBuffer[id].size(); ++k) {
|
||||
ISkinnedMesh::SWeight *WeightClone = AnimatedMesh->addWeight(joint);
|
||||
SkinnedMesh::SWeight *WeightClone = AnimatedMesh->addWeight(joint);
|
||||
WeightClone->strength = weight.strength;
|
||||
WeightClone->vertex_id = verticesLinkIndex[id][k];
|
||||
WeightClone->buffer_id = verticesLinkBuffer[id][k];
|
||||
@ -314,7 +314,7 @@ bool CXMeshFileLoader::load(io::IReadFile *file)
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < mesh->WeightJoint.size(); ++j) {
|
||||
ISkinnedMesh::SWeight &weight = (AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]->Weights[mesh->WeightNum[j]]);
|
||||
SkinnedMesh::SWeight &weight = (AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]->Weights[mesh->WeightNum[j]]);
|
||||
|
||||
u32 id = weight.vertex_id;
|
||||
|
||||
@ -486,7 +486,7 @@ bool CXMeshFileLoader::parseDataObjectTemplate()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent)
|
||||
bool CXMeshFileLoader::parseDataObjectFrame(SkinnedMesh::SJoint *Parent)
|
||||
{
|
||||
#ifdef _XREADER_DEBUG
|
||||
os::Printer::log("CXFileReader: Reading frame", ELL_DEBUG);
|
||||
@ -508,7 +508,7 @@ bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent)
|
||||
SET_ERR_AND_RETURN();
|
||||
}
|
||||
|
||||
CSkinnedMesh::SJoint *joint = 0;
|
||||
SkinnedMesh::SJoint *joint = 0;
|
||||
|
||||
if (name.size()) {
|
||||
auto n = AnimatedMesh->getJointNumber(name.c_str());
|
||||
@ -947,7 +947,7 @@ bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh)
|
||||
mesh.HasSkinning = true;
|
||||
|
||||
auto n = AnimatedMesh->getJointNumber(TransformNodeName.c_str());
|
||||
CSkinnedMesh::SJoint *joint = n.has_value() ? AnimatedMesh->getAllJoints()[*n] : nullptr;
|
||||
SkinnedMesh::SJoint *joint = n.has_value() ? AnimatedMesh->getAllJoints()[*n] : nullptr;
|
||||
|
||||
if (!joint) {
|
||||
#ifdef _XREADER_DEBUG
|
||||
@ -974,7 +974,7 @@ bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh)
|
||||
mesh.WeightJoint.push_back(*n);
|
||||
mesh.WeightNum.push_back(joint->Weights.size());
|
||||
|
||||
CSkinnedMesh::SWeight *weight = AnimatedMesh->addWeight(joint);
|
||||
SkinnedMesh::SWeight *weight = AnimatedMesh->addWeight(joint);
|
||||
|
||||
weight->buffer_id = 0;
|
||||
weight->vertex_id = readInt();
|
||||
@ -1358,7 +1358,7 @@ bool CXMeshFileLoader::parseDataObjectAnimation()
|
||||
|
||||
// anim.closed = true;
|
||||
// anim.linearPositionQuality = true;
|
||||
CSkinnedMesh::SJoint animationDump;
|
||||
SkinnedMesh::SJoint animationDump;
|
||||
|
||||
core::stringc FrameName;
|
||||
|
||||
@ -1400,7 +1400,7 @@ bool CXMeshFileLoader::parseDataObjectAnimation()
|
||||
#endif
|
||||
auto n = AnimatedMesh->getJointNumber(FrameName.c_str());
|
||||
|
||||
CSkinnedMesh::SJoint *joint;
|
||||
SkinnedMesh::SJoint *joint;
|
||||
if (n.has_value()) {
|
||||
joint = AnimatedMesh->getAllJoints()[*n];
|
||||
} else {
|
||||
@ -1431,7 +1431,7 @@ bool CXMeshFileLoader::parseDataObjectAnimation()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint)
|
||||
bool CXMeshFileLoader::parseDataObjectAnimationKey(SkinnedMesh::SJoint *joint)
|
||||
{
|
||||
#ifdef _XREADER_DEBUG
|
||||
os::Printer::log("CXFileReader: reading animation key", ELL_DEBUG);
|
||||
@ -1488,7 +1488,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint)
|
||||
os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING);
|
||||
}
|
||||
|
||||
ISkinnedMesh::SRotationKey *key = AnimatedMesh->addRotationKey(joint);
|
||||
SkinnedMesh::SRotationKey *key = AnimatedMesh->addRotationKey(joint);
|
||||
key->frame = time;
|
||||
key->rotation.set(X, Y, Z, W);
|
||||
key->rotation.normalize();
|
||||
@ -1514,11 +1514,11 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint)
|
||||
}
|
||||
|
||||
if (keyType == 2) {
|
||||
ISkinnedMesh::SPositionKey *key = AnimatedMesh->addPositionKey(joint);
|
||||
SkinnedMesh::SPositionKey *key = AnimatedMesh->addPositionKey(joint);
|
||||
key->frame = time;
|
||||
key->position = vector;
|
||||
} else {
|
||||
ISkinnedMesh::SScaleKey *key = AnimatedMesh->addScaleKey(joint);
|
||||
SkinnedMesh::SScaleKey *key = AnimatedMesh->addScaleKey(joint);
|
||||
key->frame = time;
|
||||
key->scale = vector;
|
||||
}
|
||||
@ -1547,14 +1547,14 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint)
|
||||
|
||||
// core::vector3df rotation = mat.getRotationDegrees();
|
||||
|
||||
ISkinnedMesh::SRotationKey *keyR = AnimatedMesh->addRotationKey(joint);
|
||||
SkinnedMesh::SRotationKey *keyR = AnimatedMesh->addRotationKey(joint);
|
||||
keyR->frame = time;
|
||||
|
||||
// IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from mat to mat.getTransposed() for downward compatibility.
|
||||
// Not tested so far if this was correct or wrong before quaternion fix!
|
||||
keyR->rotation = core::quaternion(mat.getTransposed());
|
||||
|
||||
ISkinnedMesh::SPositionKey *keyP = AnimatedMesh->addPositionKey(joint);
|
||||
SkinnedMesh::SPositionKey *keyP = AnimatedMesh->addPositionKey(joint);
|
||||
keyP->frame = time;
|
||||
keyP->position = mat.getTranslation();
|
||||
|
||||
@ -1567,7 +1567,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint)
|
||||
scale.Y=1;
|
||||
if (scale.Z==0)
|
||||
scale.Z=1;
|
||||
ISkinnedMesh::SScaleKey *keyS=AnimatedMesh->addScaleKey(joint);
|
||||
SkinnedMesh::SScaleKey *keyS=AnimatedMesh->addScaleKey(joint);
|
||||
keyS->frame=time;
|
||||
keyS->scale=scale;
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "irrString.h"
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "SkinnedMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -86,7 +86,7 @@ private:
|
||||
|
||||
bool parseDataObjectTemplate();
|
||||
|
||||
bool parseDataObjectFrame(CSkinnedMesh::SJoint *parent);
|
||||
bool parseDataObjectFrame(SkinnedMesh::SJoint *parent);
|
||||
|
||||
bool parseDataObjectTransformationMatrix(core::matrix4 &mat);
|
||||
|
||||
@ -110,7 +110,7 @@ private:
|
||||
|
||||
bool parseDataObjectAnimation();
|
||||
|
||||
bool parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint);
|
||||
bool parseDataObjectAnimationKey(SkinnedMesh::SJoint *joint);
|
||||
|
||||
bool parseDataObjectTextureFilename(core::stringc &texturename);
|
||||
|
||||
@ -155,7 +155,7 @@ private:
|
||||
bool readRGB(video::SColor &color);
|
||||
bool readRGBA(video::SColor &color);
|
||||
|
||||
CSkinnedMesh *AnimatedMesh;
|
||||
SkinnedMesh *AnimatedMesh;
|
||||
|
||||
c8 *Buffer;
|
||||
const c8 *P;
|
||||
@ -167,7 +167,7 @@ private:
|
||||
|
||||
bool ErrorState;
|
||||
|
||||
CSkinnedMesh::SJoint *CurFrame;
|
||||
SkinnedMesh::SJoint *CurFrame;
|
||||
|
||||
core::array<SXMesh *> Meshes;
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CSkinnedMesh.h"
|
||||
#include <optional>
|
||||
#include "SkinnedMesh.h"
|
||||
#include "IBoneSceneNode.h"
|
||||
#include "CBoneSceneNode.h"
|
||||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "SSkinMeshBuffer.h"
|
||||
@ -63,17 +63,17 @@ irr::u32 dropMiddleKeys(irr::core::array<T> &array, Cmp &cmp)
|
||||
return d;
|
||||
}
|
||||
|
||||
bool identicalPos(const irr::scene::ISkinnedMesh::SPositionKey &a, const irr::scene::ISkinnedMesh::SPositionKey &b)
|
||||
bool identicalPos(const irr::scene::SkinnedMesh::SPositionKey &a, const irr::scene::SkinnedMesh::SPositionKey &b)
|
||||
{
|
||||
return a.position == b.position;
|
||||
}
|
||||
|
||||
bool identicalScale(const irr::scene::ISkinnedMesh::SScaleKey &a, const irr::scene::ISkinnedMesh::SScaleKey &b)
|
||||
bool identicalScale(const irr::scene::SkinnedMesh::SScaleKey &a, const irr::scene::SkinnedMesh::SScaleKey &b)
|
||||
{
|
||||
return a.scale == b.scale;
|
||||
}
|
||||
|
||||
bool identicalRotation(const irr::scene::ISkinnedMesh::SRotationKey &a, const irr::scene::ISkinnedMesh::SRotationKey &b)
|
||||
bool identicalRotation(const irr::scene::SkinnedMesh::SRotationKey &a, const irr::scene::SkinnedMesh::SRotationKey &b)
|
||||
{
|
||||
return a.rotation == b.rotation;
|
||||
}
|
||||
@ -85,7 +85,7 @@ namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CSkinnedMesh::CSkinnedMesh() :
|
||||
SkinnedMesh::SkinnedMesh() :
|
||||
SkinningBuffers(0), EndFrame(0.f), FramesPerSecond(25.f),
|
||||
LastAnimatedFrame(-1), SkinnedLastFrame(false),
|
||||
InterpolationMode(EIM_LINEAR),
|
||||
@ -93,14 +93,14 @@ CSkinnedMesh::CSkinnedMesh() :
|
||||
AnimateNormals(true), HardwareSkinning(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CSkinnedMesh");
|
||||
setDebugName("SkinnedMesh");
|
||||
#endif
|
||||
|
||||
SkinningBuffers = &LocalBuffers;
|
||||
}
|
||||
|
||||
//! destructor
|
||||
CSkinnedMesh::~CSkinnedMesh()
|
||||
SkinnedMesh::~SkinnedMesh()
|
||||
{
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i)
|
||||
delete AllJoints[i];
|
||||
@ -111,14 +111,14 @@ CSkinnedMesh::~CSkinnedMesh()
|
||||
}
|
||||
}
|
||||
|
||||
f32 CSkinnedMesh::getMaxFrameNumber() const
|
||||
f32 SkinnedMesh::getMaxFrameNumber() const
|
||||
{
|
||||
return EndFrame;
|
||||
}
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
f32 CSkinnedMesh::getAnimationSpeed() const
|
||||
f32 SkinnedMesh::getAnimationSpeed() const
|
||||
{
|
||||
return FramesPerSecond;
|
||||
}
|
||||
@ -126,13 +126,13 @@ f32 CSkinnedMesh::getAnimationSpeed() const
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
void CSkinnedMesh::setAnimationSpeed(f32 fps)
|
||||
void SkinnedMesh::setAnimationSpeed(f32 fps)
|
||||
{
|
||||
FramesPerSecond = fps;
|
||||
}
|
||||
|
||||
//! returns the animated mesh based
|
||||
IMesh *CSkinnedMesh::getMesh(f32 frame)
|
||||
IMesh *SkinnedMesh::getMesh(f32 frame)
|
||||
{
|
||||
// animate(frame,startFrameLoop, endFrameLoop);
|
||||
if (frame == -1)
|
||||
@ -149,7 +149,7 @@ IMesh *CSkinnedMesh::getMesh(f32 frame)
|
||||
|
||||
//! Animates this mesh's joints based on frame input
|
||||
//! blend: {0-old position, 1-New position}
|
||||
void CSkinnedMesh::animateMesh(f32 frame, f32 blend)
|
||||
void SkinnedMesh::animateMesh(f32 frame, f32 blend)
|
||||
{
|
||||
if (!HasAnimation || LastAnimatedFrame == frame)
|
||||
return;
|
||||
@ -205,7 +205,7 @@ void CSkinnedMesh::animateMesh(f32 frame, f32 blend)
|
||||
updateBoundingBox();
|
||||
}
|
||||
|
||||
void CSkinnedMesh::buildAllLocalAnimatedMatrices()
|
||||
void SkinnedMesh::buildAllLocalAnimatedMatrices()
|
||||
{
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i) {
|
||||
SJoint *joint = AllJoints[i];
|
||||
@ -270,7 +270,7 @@ void CSkinnedMesh::buildAllLocalAnimatedMatrices()
|
||||
SkinnedLastFrame = false;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::buildAllGlobalAnimatedMatrices(SJoint *joint, SJoint *parentJoint)
|
||||
void SkinnedMesh::buildAllGlobalAnimatedMatrices(SJoint *joint, SJoint *parentJoint)
|
||||
{
|
||||
if (!joint) {
|
||||
for (u32 i = 0; i < RootJoints.size(); ++i)
|
||||
@ -288,7 +288,7 @@ void CSkinnedMesh::buildAllGlobalAnimatedMatrices(SJoint *joint, SJoint *parentJ
|
||||
buildAllGlobalAnimatedMatrices(joint->Children[j], joint);
|
||||
}
|
||||
|
||||
void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
|
||||
void SkinnedMesh::getFrameData(f32 frame, SJoint *joint,
|
||||
core::vector3df &position, s32 &positionHint,
|
||||
core::vector3df &scale, s32 &scaleHint,
|
||||
core::quaternion &rotation, s32 &rotationHint)
|
||||
@ -453,7 +453,7 @@ void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
void CSkinnedMesh::skinMesh()
|
||||
void SkinnedMesh::skinMesh()
|
||||
{
|
||||
if (!HasAnimation || SkinnedLastFrame)
|
||||
return;
|
||||
@ -491,7 +491,7 @@ void CSkinnedMesh::skinMesh()
|
||||
updateBoundingBox();
|
||||
}
|
||||
|
||||
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint)
|
||||
void SkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint)
|
||||
{
|
||||
if (joint->Weights.size()) {
|
||||
// Find this joints pull on vertices...
|
||||
@ -541,19 +541,19 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint)
|
||||
skinJoint(joint->Children[j], joint);
|
||||
}
|
||||
|
||||
E_ANIMATED_MESH_TYPE CSkinnedMesh::getMeshType() const
|
||||
E_ANIMATED_MESH_TYPE SkinnedMesh::getMeshType() const
|
||||
{
|
||||
return EAMT_SKINNED;
|
||||
}
|
||||
|
||||
//! Gets joint count.
|
||||
u32 CSkinnedMesh::getJointCount() const
|
||||
u32 SkinnedMesh::getJointCount() const
|
||||
{
|
||||
return AllJoints.size();
|
||||
}
|
||||
|
||||
//! Gets the name of a joint.
|
||||
const std::optional<std::string> &CSkinnedMesh::getJointName(u32 number) const
|
||||
const std::optional<std::string> &SkinnedMesh::getJointName(u32 number) const
|
||||
{
|
||||
if (number >= getJointCount()) {
|
||||
static const std::optional<std::string> nullopt;
|
||||
@ -563,7 +563,7 @@ const std::optional<std::string> &CSkinnedMesh::getJointName(u32 number) const
|
||||
}
|
||||
|
||||
//! Gets a joint number from its name
|
||||
std::optional<u32> CSkinnedMesh::getJointNumber(const std::string &name) const
|
||||
std::optional<u32> SkinnedMesh::getJointNumber(const std::string &name) const
|
||||
{
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i) {
|
||||
if (AllJoints[i]->Name == name)
|
||||
@ -574,13 +574,13 @@ std::optional<u32> CSkinnedMesh::getJointNumber(const std::string &name) const
|
||||
}
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
u32 CSkinnedMesh::getMeshBufferCount() const
|
||||
u32 SkinnedMesh::getMeshBufferCount() const
|
||||
{
|
||||
return LocalBuffers.size();
|
||||
}
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
IMeshBuffer *CSkinnedMesh::getMeshBuffer(u32 nr) const
|
||||
IMeshBuffer *SkinnedMesh::getMeshBuffer(u32 nr) const
|
||||
{
|
||||
if (nr < LocalBuffers.size())
|
||||
return LocalBuffers[nr];
|
||||
@ -589,7 +589,7 @@ IMeshBuffer *CSkinnedMesh::getMeshBuffer(u32 nr) const
|
||||
}
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
IMeshBuffer *CSkinnedMesh::getMeshBuffer(const video::SMaterial &material) const
|
||||
IMeshBuffer *SkinnedMesh::getMeshBuffer(const video::SMaterial &material) const
|
||||
{
|
||||
for (u32 i = 0; i < LocalBuffers.size(); ++i) {
|
||||
if (LocalBuffers[i]->getMaterial() == material)
|
||||
@ -598,29 +598,29 @@ IMeshBuffer *CSkinnedMesh::getMeshBuffer(const video::SMaterial &material) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 CSkinnedMesh::getTextureSlot(u32 meshbufNr) const
|
||||
u32 SkinnedMesh::getTextureSlot(u32 meshbufNr) const
|
||||
{
|
||||
return TextureSlots.at(meshbufNr);
|
||||
}
|
||||
|
||||
void CSkinnedMesh::setTextureSlot(u32 meshbufNr, u32 textureSlot) {
|
||||
void SkinnedMesh::setTextureSlot(u32 meshbufNr, u32 textureSlot) {
|
||||
TextureSlots.at(meshbufNr) = textureSlot;
|
||||
}
|
||||
|
||||
//! returns an axis aligned bounding box
|
||||
const core::aabbox3d<f32> &CSkinnedMesh::getBoundingBox() const
|
||||
const core::aabbox3d<f32> &SkinnedMesh::getBoundingBox() const
|
||||
{
|
||||
return BoundingBox;
|
||||
}
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
void CSkinnedMesh::setBoundingBox(const core::aabbox3df &box)
|
||||
void SkinnedMesh::setBoundingBox(const core::aabbox3df &box)
|
||||
{
|
||||
BoundingBox = box;
|
||||
}
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
void CSkinnedMesh::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
|
||||
void SkinnedMesh::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
|
||||
E_BUFFER_TYPE buffer)
|
||||
{
|
||||
for (u32 i = 0; i < LocalBuffers.size(); ++i)
|
||||
@ -628,71 +628,43 @@ void CSkinnedMesh::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
|
||||
}
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
void CSkinnedMesh::setDirty(E_BUFFER_TYPE buffer)
|
||||
void SkinnedMesh::setDirty(E_BUFFER_TYPE buffer)
|
||||
{
|
||||
for (u32 i = 0; i < LocalBuffers.size(); ++i)
|
||||
LocalBuffers[i]->setDirty(buffer);
|
||||
}
|
||||
|
||||
//! uses animation from another mesh
|
||||
bool CSkinnedMesh::useAnimationFrom(const ISkinnedMesh *mesh)
|
||||
{
|
||||
bool unmatched = false;
|
||||
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i) {
|
||||
SJoint *joint = AllJoints[i];
|
||||
joint->UseAnimationFrom = 0;
|
||||
|
||||
if (joint->Name == "")
|
||||
unmatched = true;
|
||||
else {
|
||||
for (u32 j = 0; j < mesh->getAllJoints().size(); ++j) {
|
||||
SJoint *otherJoint = mesh->getAllJoints()[j];
|
||||
if (joint->Name == otherJoint->Name) {
|
||||
joint->UseAnimationFrom = otherJoint;
|
||||
}
|
||||
}
|
||||
if (!joint->UseAnimationFrom)
|
||||
unmatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
checkForAnimation();
|
||||
|
||||
return !unmatched;
|
||||
}
|
||||
|
||||
//! Update Normals when Animating
|
||||
//! False= Don't animate them, faster
|
||||
//! True= Update normals (default)
|
||||
void CSkinnedMesh::updateNormalsWhenAnimating(bool on)
|
||||
void SkinnedMesh::updateNormalsWhenAnimating(bool on)
|
||||
{
|
||||
AnimateNormals = on;
|
||||
}
|
||||
|
||||
//! Sets Interpolation Mode
|
||||
void CSkinnedMesh::setInterpolationMode(E_INTERPOLATION_MODE mode)
|
||||
void SkinnedMesh::setInterpolationMode(E_INTERPOLATION_MODE mode)
|
||||
{
|
||||
InterpolationMode = mode;
|
||||
}
|
||||
|
||||
core::array<scene::SSkinMeshBuffer *> &CSkinnedMesh::getMeshBuffers()
|
||||
core::array<scene::SSkinMeshBuffer *> &SkinnedMesh::getMeshBuffers()
|
||||
{
|
||||
return LocalBuffers;
|
||||
}
|
||||
|
||||
core::array<CSkinnedMesh::SJoint *> &CSkinnedMesh::getAllJoints()
|
||||
core::array<SkinnedMesh::SJoint *> &SkinnedMesh::getAllJoints()
|
||||
{
|
||||
return AllJoints;
|
||||
}
|
||||
|
||||
const core::array<CSkinnedMesh::SJoint *> &CSkinnedMesh::getAllJoints() const
|
||||
const core::array<SkinnedMesh::SJoint *> &SkinnedMesh::getAllJoints() const
|
||||
{
|
||||
return AllJoints;
|
||||
}
|
||||
|
||||
//! (This feature is not implemented in irrlicht yet)
|
||||
bool CSkinnedMesh::setHardwareSkinning(bool on)
|
||||
bool SkinnedMesh::setHardwareSkinning(bool on)
|
||||
{
|
||||
if (HardwareSkinning != on) {
|
||||
if (on) {
|
||||
@ -715,7 +687,7 @@ bool CSkinnedMesh::setHardwareSkinning(bool on)
|
||||
return HardwareSkinning;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::refreshJointCache()
|
||||
void SkinnedMesh::refreshJointCache()
|
||||
{
|
||||
// copy cache from the mesh...
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i) {
|
||||
@ -729,7 +701,7 @@ void CSkinnedMesh::refreshJointCache()
|
||||
}
|
||||
}
|
||||
|
||||
void CSkinnedMesh::resetAnimation()
|
||||
void SkinnedMesh::resetAnimation()
|
||||
{
|
||||
// copy from the cache to the mesh...
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i) {
|
||||
@ -745,7 +717,7 @@ void CSkinnedMesh::resetAnimation()
|
||||
LastAnimatedFrame = -1;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::calculateGlobalMatrices(SJoint *joint, SJoint *parentJoint)
|
||||
void SkinnedMesh::calculateGlobalMatrices(SJoint *joint, SJoint *parentJoint)
|
||||
{
|
||||
if (!joint && parentJoint) // bit of protection from endless loops
|
||||
return;
|
||||
@ -775,7 +747,7 @@ void CSkinnedMesh::calculateGlobalMatrices(SJoint *joint, SJoint *parentJoint)
|
||||
SkinnedLastFrame = false;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::checkForAnimation()
|
||||
void SkinnedMesh::checkForAnimation()
|
||||
{
|
||||
u32 i, j;
|
||||
// Check for animation...
|
||||
@ -868,7 +840,7 @@ void CSkinnedMesh::checkForAnimation()
|
||||
}
|
||||
|
||||
//! called by loader after populating with mesh and bone data
|
||||
void CSkinnedMesh::finalize()
|
||||
void SkinnedMesh::finalize()
|
||||
{
|
||||
os::Printer::log("Skinned Mesh - finalize", ELL_DEBUG);
|
||||
u32 i;
|
||||
@ -1046,7 +1018,7 @@ void CSkinnedMesh::finalize()
|
||||
}
|
||||
}
|
||||
|
||||
void CSkinnedMesh::updateBoundingBox(void)
|
||||
void SkinnedMesh::updateBoundingBox(void)
|
||||
{
|
||||
if (!SkinningBuffers)
|
||||
return;
|
||||
@ -1065,7 +1037,7 @@ void CSkinnedMesh::updateBoundingBox(void)
|
||||
}
|
||||
}
|
||||
|
||||
scene::SSkinMeshBuffer *CSkinnedMesh::addMeshBuffer()
|
||||
scene::SSkinMeshBuffer *SkinnedMesh::addMeshBuffer()
|
||||
{
|
||||
scene::SSkinMeshBuffer *buffer = new scene::SSkinMeshBuffer();
|
||||
TextureSlots.push_back(LocalBuffers.size());
|
||||
@ -1073,13 +1045,13 @@ scene::SSkinMeshBuffer *CSkinnedMesh::addMeshBuffer()
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::addMeshBuffer(SSkinMeshBuffer *meshbuf)
|
||||
void SkinnedMesh::addMeshBuffer(SSkinMeshBuffer *meshbuf)
|
||||
{
|
||||
TextureSlots.push_back(LocalBuffers.size());
|
||||
LocalBuffers.push_back(meshbuf);
|
||||
}
|
||||
|
||||
CSkinnedMesh::SJoint *CSkinnedMesh::addJoint(SJoint *parent)
|
||||
SkinnedMesh::SJoint *SkinnedMesh::addJoint(SJoint *parent)
|
||||
{
|
||||
SJoint *joint = new SJoint;
|
||||
|
||||
@ -1094,7 +1066,7 @@ CSkinnedMesh::SJoint *CSkinnedMesh::addJoint(SJoint *parent)
|
||||
return joint;
|
||||
}
|
||||
|
||||
CSkinnedMesh::SPositionKey *CSkinnedMesh::addPositionKey(SJoint *joint)
|
||||
SkinnedMesh::SPositionKey *SkinnedMesh::addPositionKey(SJoint *joint)
|
||||
{
|
||||
if (!joint)
|
||||
return 0;
|
||||
@ -1103,7 +1075,7 @@ CSkinnedMesh::SPositionKey *CSkinnedMesh::addPositionKey(SJoint *joint)
|
||||
return &joint->PositionKeys.getLast();
|
||||
}
|
||||
|
||||
CSkinnedMesh::SScaleKey *CSkinnedMesh::addScaleKey(SJoint *joint)
|
||||
SkinnedMesh::SScaleKey *SkinnedMesh::addScaleKey(SJoint *joint)
|
||||
{
|
||||
if (!joint)
|
||||
return 0;
|
||||
@ -1112,7 +1084,7 @@ CSkinnedMesh::SScaleKey *CSkinnedMesh::addScaleKey(SJoint *joint)
|
||||
return &joint->ScaleKeys.getLast();
|
||||
}
|
||||
|
||||
CSkinnedMesh::SRotationKey *CSkinnedMesh::addRotationKey(SJoint *joint)
|
||||
SkinnedMesh::SRotationKey *SkinnedMesh::addRotationKey(SJoint *joint)
|
||||
{
|
||||
if (!joint)
|
||||
return 0;
|
||||
@ -1121,7 +1093,7 @@ CSkinnedMesh::SRotationKey *CSkinnedMesh::addRotationKey(SJoint *joint)
|
||||
return &joint->RotationKeys.getLast();
|
||||
}
|
||||
|
||||
CSkinnedMesh::SWeight *CSkinnedMesh::addWeight(SJoint *joint)
|
||||
SkinnedMesh::SWeight *SkinnedMesh::addWeight(SJoint *joint)
|
||||
{
|
||||
if (!joint)
|
||||
return 0;
|
||||
@ -1130,12 +1102,12 @@ CSkinnedMesh::SWeight *CSkinnedMesh::addWeight(SJoint *joint)
|
||||
return &joint->Weights.getLast();
|
||||
}
|
||||
|
||||
bool CSkinnedMesh::isStatic()
|
||||
bool SkinnedMesh::isStatic() const
|
||||
{
|
||||
return !HasAnimation;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::normalizeWeights()
|
||||
void SkinnedMesh::normalizeWeights()
|
||||
{
|
||||
// note: unsure if weights ids are going to be used.
|
||||
|
||||
@ -1176,7 +1148,7 @@ void CSkinnedMesh::normalizeWeights()
|
||||
}
|
||||
}
|
||||
|
||||
void CSkinnedMesh::recoverJointsFromMesh(core::array<IBoneSceneNode *> &jointChildSceneNodes)
|
||||
void SkinnedMesh::recoverJointsFromMesh(core::array<IBoneSceneNode *> &jointChildSceneNodes)
|
||||
{
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i) {
|
||||
IBoneSceneNode *node = jointChildSceneNodes[i];
|
||||
@ -1193,7 +1165,7 @@ void CSkinnedMesh::recoverJointsFromMesh(core::array<IBoneSceneNode *> &jointChi
|
||||
}
|
||||
}
|
||||
|
||||
void CSkinnedMesh::transferJointsToMesh(const core::array<IBoneSceneNode *> &jointChildSceneNodes)
|
||||
void SkinnedMesh::transferJointsToMesh(const core::array<IBoneSceneNode *> &jointChildSceneNodes)
|
||||
{
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i) {
|
||||
const IBoneSceneNode *const node = jointChildSceneNodes[i];
|
||||
@ -1214,7 +1186,7 @@ void CSkinnedMesh::transferJointsToMesh(const core::array<IBoneSceneNode *> &joi
|
||||
SkinnedLastFrame = false;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNode *> &jointChildSceneNodes)
|
||||
void SkinnedMesh::transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNode *> &jointChildSceneNodes)
|
||||
{
|
||||
for (u32 i = 0; i < AllJoints.size(); ++i) {
|
||||
const IBoneSceneNode *const node = jointChildSceneNodes[i];
|
||||
@ -1227,7 +1199,7 @@ void CSkinnedMesh::transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNod
|
||||
SkinnedLastFrame = false;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::addJoints(core::array<IBoneSceneNode *> &jointChildSceneNodes,
|
||||
void SkinnedMesh::addJoints(core::array<IBoneSceneNode *> &jointChildSceneNodes,
|
||||
IAnimatedMeshSceneNode *node, ISceneManager *smgr)
|
||||
{
|
||||
// Create new joints
|
||||
@ -1264,7 +1236,7 @@ void CSkinnedMesh::addJoints(core::array<IBoneSceneNode *> &jointChildSceneNodes
|
||||
SkinnedLastFrame = false;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::convertMeshToTangents()
|
||||
void SkinnedMesh::convertMeshToTangents()
|
||||
{
|
||||
// now calculate tangents
|
||||
for (u32 b = 0; b < LocalBuffers.size(); ++b) {
|
||||
@ -1315,7 +1287,7 @@ void CSkinnedMesh::convertMeshToTangents()
|
||||
}
|
||||
}
|
||||
|
||||
void CSkinnedMesh::calculateTangents(
|
||||
void SkinnedMesh::calculateTangents(
|
||||
core::vector3df &normal,
|
||||
core::vector3df &tangent,
|
||||
core::vector3df &binormal,
|
@ -12,7 +12,7 @@
|
||||
#include "IFileSystem.h"
|
||||
#include "IReadFile.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ISkinnedMesh.h"
|
||||
#include "SkinnedMesh.h"
|
||||
#include "irrlicht.h"
|
||||
|
||||
#include "catch.h"
|
||||
@ -379,14 +379,14 @@ SECTION("simple sparse accessor")
|
||||
// https://github.com/KhronosGroup/glTF-Sample-Models/tree/main/2.0/SimpleSkin
|
||||
SECTION("simple skin")
|
||||
{
|
||||
using ISkinnedMesh = irr::scene::ISkinnedMesh;
|
||||
using SkinnedMesh = irr::scene::SkinnedMesh;
|
||||
const auto mesh = loadMesh(model_stem + "simple_skin.gltf");
|
||||
REQUIRE(mesh != nullptr);
|
||||
auto csm = dynamic_cast<const ISkinnedMesh*>(mesh);
|
||||
auto csm = dynamic_cast<const SkinnedMesh*>(mesh);
|
||||
const auto joints = csm->getAllJoints();
|
||||
REQUIRE(joints.size() == 3);
|
||||
|
||||
const auto findJoint = [&](const std::function<bool(ISkinnedMesh::SJoint*)> &predicate) {
|
||||
const auto findJoint = [&](const std::function<bool(SkinnedMesh::SJoint*)> &predicate) {
|
||||
for (std::size_t i = 0; i < joints.size(); ++i) {
|
||||
if (predicate(joints[i])) {
|
||||
return joints[i];
|
||||
@ -420,7 +420,7 @@ SECTION("simple skin")
|
||||
|
||||
SECTION("weights are correct")
|
||||
{
|
||||
const auto weights = [&](const ISkinnedMesh::SJoint *joint) {
|
||||
const auto weights = [&](const SkinnedMesh::SJoint *joint) {
|
||||
std::unordered_map<irr::u32, irr::f32> weights;
|
||||
for (std::size_t i = 0; i < joint->Weights.size(); ++i) {
|
||||
const auto weight = joint->Weights[i];
|
||||
|
Loading…
Reference in New Issue
Block a user