1111#include " aabbox3d.h"
1212#include " irrMath.h"
1313#include " irrTypes.h"
14+ #include " irr_ptr.h"
1415#include " matrix4.h"
1516#include " quaternion.h"
1617#include " vector3d.h"
@@ -43,7 +44,6 @@ class SkinnedMesh : public IAnimatedMesh
4344 SkinnedMesh (SourceFormat src_format) :
4445 EndFrame (0 .f), FramesPerSecond(25 .f),
4546 HasAnimation (false ), PreparedForSkinning(false ),
46- AnimateNormals (true ),
4747 SrcFormat (src_format)
4848 {
4949 SkinningBuffers = &LocalBuffers;
@@ -59,15 +59,6 @@ class SkinnedMesh : public IAnimatedMesh
5959 // ! If the duration is 0, it is a static (=non animated) mesh.
6060 f32 getMaxFrameNumber () const override ;
6161
62- // ! Gets the default animation speed of the animated mesh.
63- /* * \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
64- f32 getAnimationSpeed () const override ;
65-
66- // ! Gets the frame count of the animated mesh.
67- /* * \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
68- The actual speed is set in the scene node the mesh is instantiated in.*/
69- void setAnimationSpeed (f32 fps) override ;
70-
7162 // ! Turns the given array of local matrices into an array of global matrices
7263 // ! by multiplying with respective parent matrices.
7364 void calculateGlobalMatrices (std::vector<core::matrix4> &matrices) const ;
@@ -89,8 +80,6 @@ class SkinnedMesh : public IAnimatedMesh
8980
9081 u32 getTextureSlot (u32 meshbufNr) const override ;
9182
92- void setTextureSlot (u32 meshbufNr, u32 textureSlot);
93-
9483 // ! Returns bounding box of the mesh *in static pose*.
9584 const core::aabbox3d<f32 > &getBoundingBox () const override {
9685 // TODO ideally we shouldn't be forced to implement this
@@ -126,14 +115,6 @@ class SkinnedMesh : public IAnimatedMesh
126115 \return Number of the joint or std::nullopt if not found. */
127116 std::optional<u32 > getJointNumber (const std::string &name) const ;
128117
129- // ! Update Normals when Animating
130- /* * \param on If false don't animate, which is faster.
131- Else update normals, which allows for proper lighting of
132- animated meshes (default). */
133- void updateNormalsWhenAnimating (bool on) {
134- AnimateNormals = on;
135- }
136-
137118 // ! converts the vertex type of all meshbuffers to tangents.
138119 /* * E.g. used for bump mapping. */
139120 void convertMeshToTangents ();
@@ -143,8 +124,8 @@ class SkinnedMesh : public IAnimatedMesh
143124 return !HasAnimation;
144125 }
145126
146- // ! Refreshes vertex data cached in joints such as positions and normals
147- void refreshJointCache ();
127+ // ! Back up static pose after local buffers have been modified directly
128+ void updateStaticPose ();
148129
149130 // ! Moves the mesh into static position.
150131 void resetAnimation ();
@@ -153,26 +134,6 @@ class SkinnedMesh : public IAnimatedMesh
153134 std::vector<IBoneSceneNode *> addJoints (
154135 AnimatedMeshSceneNode *node, ISceneManager *smgr);
155136
156- // ! A vertex weight
157- struct SWeight
158- {
159- // ! Index of the mesh buffer
160- u16 buffer_id; // I doubt 32bits is needed
161-
162- // ! Index of the vertex
163- u32 vertex_id; // Store global ID here
164-
165- // ! Weight Strength/Percentage (0-1)
166- f32 strength;
167-
168- private:
169- // ! Internal members used by SkinnedMesh
170- friend class SkinnedMesh ;
171- char *Moved;
172- core::vector3df StaticPos;
173- core::vector3df StaticNormal;
174- };
175-
176137 template <class T >
177138 struct Channel {
178139 struct Frame {
@@ -329,13 +290,11 @@ class SkinnedMesh : public IAnimatedMesh
329290
330291 // ! List of attached meshes
331292 std::vector<u32 > AttachedMeshes;
293+ // TODO ^ should turn this into optional meshbuffer parent field?
332294
333295 // Animation keyframes for translation, rotation, scale
334296 Keys keys;
335297
336- // ! Skin weights
337- std::vector<SWeight> Weights;
338-
339298 // ! Bounding box of all affected vertices, in local space
340299 core::aabbox3df LocalBoundingBox{{0 , 0 , 0 }};
341300
@@ -369,34 +328,29 @@ class SkinnedMesh : public IAnimatedMesh
369328protected:
370329 bool checkForAnimation () const ;
371330
372- void topoSortJoints ();
373-
374331 void prepareForSkinning ();
375332
376333 void calculateStaticBoundingBox ();
377334 void calculateJointBoundingBoxes ();
378335 void calculateBufferBoundingBoxes ();
379336
380- void normalizeWeights ();
381-
382337 void calculateTangents (core::vector3df &normal,
383338 core::vector3df &tangent, core::vector3df &binormal,
384339 const core::vector3df &vt1, const core::vector3df &vt2, const core::vector3df &vt3,
385340 const core::vector2df &tc1, const core::vector2df &tc2, const core::vector2df &tc3);
386341
342+ friend class SkinnedMeshBuilder ;
343+
387344 std::vector<SSkinMeshBuffer *> *SkinningBuffers; // Meshbuffer to skin, default is to skin localBuffers
388345
389346 std::vector<SSkinMeshBuffer *> LocalBuffers;
347+
390348 // ! Mapping from meshbuffer number to bindable texture slot
391349 std::vector<u32 > TextureSlots;
392350
393351 // ! Joints, topologically sorted (parents come before their children).
394352 std::vector<SJoint *> AllJoints;
395353
396- // bool can't be used here because std::vector<bool>
397- // doesn't allow taking a reference to individual elements.
398- std::vector<std::vector<char >> Vertices_Moved;
399-
400354 // ! Bounding box of just the static parts of the mesh
401355 core::aabbox3df StaticPartsBox{{0 , 0 , 0 }};
402356
@@ -408,40 +362,76 @@ class SkinnedMesh : public IAnimatedMesh
408362
409363 bool HasAnimation;
410364 bool PreparedForSkinning;
411- bool AnimateNormals;
412365
413366 SourceFormat SrcFormat;
414367};
415368
416369// Interface for mesh loaders
417- class SkinnedMeshBuilder : public SkinnedMesh {
370+ class SkinnedMeshBuilder {
371+ using SJoint = SkinnedMesh::SJoint;
372+
418373public:
419- SkinnedMeshBuilder (SourceFormat src_format) : SkinnedMesh(src_format) {}
374+
375+ // HACK the .x and .b3d loader do not separate the "loader" class from an "extractor" class
376+ // used and destroyed in a specific loading process (contrast with the .gltf mesh loader).
377+ // This means we need an empty skinned mesh builder.
378+ SkinnedMeshBuilder () {}
379+
380+ SkinnedMeshBuilder (SkinnedMesh::SourceFormat src_format)
381+ : mesh(new SkinnedMesh(src_format))
382+ {}
420383
421384 // ! loaders should call this after populating the mesh
422- // returns *this, so do not try to drop the mesh builder instance
423- SkinnedMesh *finalize ();
385+ SkinnedMesh *finalize () &&;
424386
425387 // ! alternative method for adding joints
426- std::vector<SJoint *> &getAllJoints () {
427- return AllJoints;
428- }
388+ std::vector<SJoint *> &getJoints () { return mesh->AllJoints ; }
429389
430390 // ! Adds a new meshbuffer to the mesh, access it as last one
431391 SSkinMeshBuffer *addMeshBuffer ();
432392
433- // ! Adds a new meshbuffer to the mesh, access it as last one
434- void addMeshBuffer (SSkinMeshBuffer *meshbuf);
393+ // ! Adds a new meshbuffer to the mesh, returns ID
394+ u32 addMeshBuffer (SSkinMeshBuffer *meshbuf);
395+
396+ u32 getMeshBufferCount () { return mesh->getMeshBufferCount (); }
397+
398+ void setTextureSlot (u32 meshbufNr, u32 textureSlot)
399+ {
400+ mesh->TextureSlots .at (meshbufNr) = textureSlot;
401+ }
435402
436403 // ! Adds a new joint to the mesh, access it as last one
437404 SJoint *addJoint (SJoint *parent = nullptr );
438405
406+ std::optional<u32 > getJointNumber (const std::string &name) const
407+ {
408+ return mesh->getJointNumber (name);
409+ }
410+
439411 void addPositionKey (SJoint *joint, f32 frame, core::vector3df pos);
440412 void addRotationKey (SJoint *joint, f32 frame, core::quaternion rotation);
441413 void addScaleKey (SJoint *joint, f32 frame, core::vector3df scale);
442414
443- // ! Adds a new weight to the mesh, access it as last one
444- SWeight *addWeight (SJoint *joint);
415+ // ! Adds a new weight to the mesh
416+ void addWeight (SJoint *joint, u16 buf, u32 vert_id, f32 strength);
417+
418+ private:
419+
420+ void topoSortJoints ();
421+
422+ // ! The mesh that is being built
423+ irr_ptr<SkinnedMesh> mesh;
424+
425+ struct Weight {
426+ u16 joint_id;
427+ u16 buffer_id;
428+ u32 vertex_id;
429+ f32 strength;
430+ };
431+
432+ // ! Weights to be added once all mesh buffers have been loaded
433+ std::vector<Weight> weights;
434+
445435};
446436
447437} // end namespace scene
0 commit comments