Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / 3d / animation_set.cpp
bloba3b210fed3455ad5156e4b0e8480572ac19ed1a9
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include "nel/3d/animation_set.h"
23 #include "nel/3d/driver.h"
24 #include "nel/3d/shape_bank.h"
25 #include "nel/misc/stream.h"
26 #include "nel/misc/path.h"
27 #include "nel/misc/file.h"
28 #include "nel/misc/algo.h"
32 using namespace std;
33 using namespace NLMISC;
35 #ifdef DEBUG_NEW
36 #define new DEBUG_NEW
37 #endif
39 namespace NL3D
42 // ***************************************************************************
43 CAnimationSet::CAnimationSet (bool headerOptim)
45 _SampleDivisor= 1;
46 _AnimHeaderOptimisation= headerOptim;
47 _Built= false;
50 // ***************************************************************************
51 CAnimationSet::~CAnimationSet ()
53 // Erase all animations.
54 for (uint a=0; a<_Animation.size(); a++)
55 delete _Animation[a];
56 for (uint s=0; s<_SkeletonWeight.size(); s++)
57 delete _SkeletonWeight[s];
60 // ***************************************************************************
61 uint CAnimationSet::getNumChannelId () const
63 return (uint)_ChannelIdByName.size ();
66 // ***************************************************************************
67 uint CAnimationSet::addAnimation (const char* name, CAnimation* animation)
69 // error to add an animation after a build() if the animation set is in HeaderCompress mode
70 nlassert(! (_Built && _AnimHeaderOptimisation) );
72 // if sampleDivisor, apply to the animation
73 if(_SampleDivisor>1)
74 animation->applySampleDivisor(_SampleDivisor);
76 // compress CTrackSampledQuat header
77 if(_AnimHeaderOptimisation)
78 animation->applyTrackQuatHeaderCompression();
80 // Add an animation
81 _Animation.push_back (animation);
82 _AnimationName.push_back (name);
84 // Add an entry name / animation
85 _AnimationIdByName.insert (std::map <std::string, uint32>::value_type (name, (uint32)_Animation.size()-1));
87 // Return animation id
88 return (uint)_Animation.size()-1;
91 // ***************************************************************************
92 uint CAnimationSet::addSkeletonWeight (const char* name, CSkeletonWeight* skeletonWeight)
94 // Add an animation
95 _SkeletonWeight.push_back (skeletonWeight);
96 _SkeletonWeightName.push_back (name);
98 // Add an entry name / animation
99 _SkeletonWeightIdByName.insert (std::map <std::string, uint32>::value_type (name, (uint32)_SkeletonWeight.size()-1));
101 // Return animation id
102 return (uint)_SkeletonWeight.size()-1;
105 // ***************************************************************************
106 void CAnimationSet::reset ()
108 _Animation.clear();
109 _SkeletonWeight.clear();
110 _ChannelName.clear();
111 _AnimationName.clear();
112 _SkeletonWeightName.clear();
113 _ChannelIdByName.clear();
114 _AnimationIdByName.clear();
115 _SkeletonWeightIdByName.clear();
116 _SSSShapes.clear();
119 // ***************************************************************************
120 void CAnimationSet::build ()
122 // error to rebuild in if already done while _AnimHeaderOptimisation,
123 // cause applyAnimHeaderCompression() won't work
124 if(_Built && _AnimHeaderOptimisation)
125 return;
126 _Built= true;
128 // Clear the channel map
129 _ChannelName.clear();
130 _ChannelIdByName.clear ();
132 // Set of names
133 std::set<std::string> channelNames;
135 // For each animation in the set
136 uint a;
137 for (a=0; a<_Animation.size(); a++)
139 // Fill the set of channel names
140 getAnimation (a)->getTrackNames (channelNames);
143 // Add this name in the map with there iD
144 uint id=0;
145 std::set<std::string>::iterator ite=channelNames.begin ();
146 while (ite!=channelNames.end ())
148 // Insert an entry
149 _ChannelIdByName.insert (std::map <std::string, uint32>::value_type (*ite, id++));
151 // Next entry
152 ite++;
155 // build ChannelName From Map
156 buildChannelNameFromMap();
158 // If the animation set is in HeaderOptim mode, reduce memory load by removing map<string, trackId>
159 if(_AnimHeaderOptimisation)
161 for (uint a=0; a<_Animation.size(); a++)
163 _Animation[a]->applyAnimHeaderCompression (this, _ChannelIdByName);
167 // Build the set of SSS Shapes from each animation
168 for (a=0; a<_Animation.size(); a++)
170 const std::vector<std::string> &shapes= _Animation[a]->getSSSShapes();
171 for(uint s=0;s<shapes.size();s++)
173 // insert (may be already done)
174 _SSSShapes.insert(shapes[s]);
179 // TestYoyo
180 /*nlinfo("ANIMYOYO: %d channels", _ChannelIdByName.size());
181 std::map <std::string, uint32>::iterator it;
182 for(it= _ChannelIdByName.begin();it!=_ChannelIdByName.end();it++)
184 nlinfo("ANIMYOYO: %3d: %s", it->second, it->first.c_str());
188 // ***************************************************************************
189 void CAnimationSet::serial (NLMISC::IStream& f)
191 // serial not possible if header optimisation enabled
192 nlassert(!_AnimHeaderOptimisation);
194 // Serial an header
195 f.serialCheck (NELID("_LEN"));
196 f.serialCheck (NELID("MINA"));
197 f.serialCheck (NELID("TES_"));
199 // Serial a version
200 uint ver= f.serialVersion (1);
202 // Serial the class
203 f.serialContPtr (_Animation);
204 f.serialContPtr (_SkeletonWeight);
205 f.serialCont (_AnimationName);
206 f.serialCont (_SkeletonWeightName);
207 f.serialCont(_ChannelIdByName);
208 f.serialCont(_AnimationIdByName);
209 f.serialCont(_SkeletonWeightIdByName);
210 if(ver>=1)
211 f.serialCont(_ChannelName);
212 else
213 buildChannelNameFromMap();
216 // ***************************************************************************
217 bool CAnimationSet::loadFromFiles(const std::string &path, bool recurse /* = true*/, const char *ext /*= "anim"*/, bool wantWarningMessage /*= true*/)
219 bool everythingOk = true;
220 std::vector<std::string> anims;
221 NLMISC::CPath::getPathContent(path, recurse, false, true, anims);
222 for (uint k = 0; k < anims.size(); ++k)
224 std::string fileExt = NLMISC::CFile::getExtension(anims[k]);
225 if (fileExt == ext) // an animation file ?
229 NLMISC::CIFile iFile;
230 iFile.open(anims[k]);
231 CUniquePtr<CAnimation> anim(new CAnimation);
232 anim->serial(iFile);
233 addAnimation(NLMISC::CFile::getFilenameWithoutExtension(anims[k]).c_str(), anim.release());
234 iFile.close();
237 catch (const NLMISC::EStream &e)
239 if (wantWarningMessage)
241 nlinfo("Unable to load an automatic animation : %s", e.what());
243 everythingOk = false;
247 build();
248 return everythingOk;
251 // ***************************************************************************
252 void CAnimationSet::setAnimationSampleDivisor(uint sampleDivisor)
254 _SampleDivisor= sampleDivisor;
255 // 0 is invalid
256 if(_SampleDivisor==0)
257 _SampleDivisor= 1;
260 // ***************************************************************************
261 uint CAnimationSet::getAnimationSampleDivisor() const
263 return _SampleDivisor;
266 // ***************************************************************************
267 void CAnimationSet::buildChannelNameFromMap()
269 contReset(_ChannelName);
270 _ChannelName.resize(_ChannelIdByName.size());
271 std::map <std::string, uint32>::iterator it;
272 for(it= _ChannelIdByName.begin();it!=_ChannelIdByName.end();it++)
274 _ChannelName[it->second]= it->first;
278 // ***************************************************************************
279 void CAnimationSet::preloadSSSShapes(IDriver &drv, CShapeBank &shapeBank)
281 const std::string shapeCacheName= "SSS_PreLoad";
283 // Create the Animation Set Shape cache if do not exist
284 if(!shapeBank.isShapeCache(shapeCacheName))
286 // allow "inifinite" number of preloaded shapes
287 shapeBank.addShapeCache(shapeCacheName);
288 shapeBank.setShapeCacheSize(shapeCacheName, 1000000);
291 // For all files
292 std::set<std::string>::iterator it;
293 for(it=_SSSShapes.begin();it!=_SSSShapes.end();it++)
295 string fileName= toLowerAscii(*it);
297 // link the shape to the shapeCache
298 shapeBank.linkShapeToShapeCache(fileName, shapeCacheName);
300 // If !present in the shapeBank
301 if( shapeBank.getPresentState(fileName)==CShapeBank::NotPresent )
303 // Don't load it if no more space in the cache
304 if( shapeBank.getShapeCacheFreeSpace(shapeCacheName)>0 )
306 // load it.
307 shapeBank.load(fileName);
309 // If success
310 if( shapeBank.getPresentState(fileName)==CShapeBank::Present )
312 // When a shape is first added to the bank, it is not in the cache.
313 // add it and release it to force it to be in the cache.
314 IShape *shp= shapeBank.addRef(fileName);
315 if(shp)
317 //nlinfo("Loading %s", CPath::lookup(fileName.c_str(), false, false).c_str());
318 shp->flushTextures(drv, 0);
319 shapeBank.release(shp);
328 } // NL3D