Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / skeleton_shape.cpp
blobafa7701af8ddcd8c09f67a6634371fc037d6dd62
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/skeleton_shape.h"
20 #include "nel/3d/skeleton_model.h"
21 #include "nel/3d/scene.h"
22 #include "nel/misc/bsphere.h"
24 using namespace std;
25 using namespace NLMISC;
27 #ifdef DEBUG_NEW
28 #define new DEBUG_NEW
29 #endif
31 namespace NL3D
35 // ***************************************************************************
36 void CSkeletonShape::CLod::serial(NLMISC::IStream &f)
38 (void)f.serialVersion(0);
40 f.serial(Distance);
41 f.serialCont(ActiveBones);
45 // ***************************************************************************
46 CSkeletonShape::CSkeletonShape()
48 // By default for now....
49 // Temp. Have a huge BBox, so clip badly.
50 _BBox.setCenter(CVector(0,0,1.5));
51 _BBox.setSize(CVector(3,3,3));
55 // ***************************************************************************
56 sint32 CSkeletonShape::getBoneIdByName(const std::string &name) const
58 std::map<std::string, uint32>::const_iterator it= _BoneMap.find(name);
59 if(it==_BoneMap.end())
60 return -1;
61 else
62 return it->second;
66 // ***************************************************************************
67 void CSkeletonShape::build(const std::vector<CBoneBase> &bones)
69 uint i;
71 // copy bones.
72 _Bones= bones;
74 // for all bones
75 for(i=0;i<_Bones.size();i++)
77 // build the map.
78 _BoneMap[_Bones[i].Name]= i;
79 // validate distances.
80 _Bones[i].LodDisableDistance= max(0.f, _Bones[i].LodDisableDistance);
82 // get fahter dist.
83 sint32 fatherId= _Bones[i].FatherId;
84 // if father exist and is not "always enabled"
85 if(fatherId>=0 && _Bones[fatherId].LodDisableDistance!=0)
87 float fatherDist= _Bones[fatherId].LodDisableDistance;
88 // I must disable me at least before my father (never after).
89 if(_Bones[i].LodDisableDistance==0)
90 _Bones[i].LodDisableDistance= fatherDist;
91 else
92 _Bones[i].LodDisableDistance= min(_Bones[i].LodDisableDistance, fatherDist);
96 // build Lod Information.
97 //==============
98 _Lods.clear();
100 // build all distances used.
101 set<float> distSet;
102 for(i=0;i<_Bones.size();i++)
104 float dist= _Bones[i].LodDisableDistance;
105 // if lod enabled for this bone, add a new distance, or do nothing
106 if(dist>0)
107 distSet.insert(dist);
110 // create a lod for each distance used + 1 (the "dist==0" distance).
111 _Lods.resize(distSet.size() + 1);
112 // create the default lod: all bones activated.
113 _Lods[0].Distance=0;
114 _Lods[0].ActiveBones.resize(_Bones.size(), 0xFF);
116 // For each lods not 0th.
117 set<float>::iterator it= distSet.begin();
118 for(uint j=1; j<_Lods.size(); j++, it++)
120 float lodDist= *it;
121 // set the distance of activation
122 _Lods[j].Distance= lodDist;
123 // resize and default to all enabled.
124 _Lods[j].ActiveBones.resize(_Bones.size(), 0xFF);
126 // Search what lod are to be disabled at this distance.
127 for(i=0;i<_Bones.size();i++)
129 float dist= _Bones[i].LodDisableDistance;
130 // if the dist of the lod is greater (or equal) to the disableDist of the bone,
131 // and if the bone is not "always enabled", disable the bone
132 if(lodDist>=dist && dist!=0 )
133 _Lods[j].ActiveBones[i]= 0;
141 // ***************************************************************************
142 void CSkeletonShape::retrieve(std::vector<CBoneBase> &bones) const
144 bones= _Bones;
148 // ***************************************************************************
149 CTransformShape *CSkeletonShape::createInstance(CScene &scene)
151 // Create a CSkeletonModel, an instance of a mesh.
152 //===============================================
153 CSkeletonModel *sm= (CSkeletonModel*)scene.createModel(NL3D::SkeletonModelId);
154 sm->Shape= this;
156 // setup bones.
157 //=================
158 sm->Bones.reserve(_Bones.size());
159 for(sint i=0;i<(sint)_Bones.size();i++)
161 // Append a new bone.
162 sm->Bones.push_back( CBone(&_Bones[i]) );
164 // Must set the Animatable father of the bone (the skeleton model!).
165 sm->Bones[i].setFather(sm, CSkeletonModel::OwnerBit);
168 // Must create and init skeleton bone usage to 0.
169 sm->initBoneUsages();
171 // For skinning: setup skeleton in Skin LoadBalancing group
172 sm->setLoadBalancingGroup("Skin");
174 return sm;
177 // ***************************************************************************
178 void CSkeletonShape::serial(NLMISC::IStream &f)
181 Version 1:
182 - _Lods.
184 sint ver= f.serialVersion(1);
186 f.serialCont(_Bones);
187 f.serialCont(_BoneMap);
189 if(ver>=1)
190 f.serialCont(_Lods);
191 else
193 // create a skeleton shape with bones activated all the time
194 _Lods.resize(1);
195 // create the default lod: all bones activated.
196 _Lods[0].Distance=0;
197 _Lods[0].ActiveBones.resize(_Bones.size(), 0xFF);
201 // ***************************************************************************
203 float CSkeletonShape::getNumTriangles (float distance)
205 // No polygons
206 return 0;
210 // ***************************************************************************
211 bool CSkeletonShape::clip(const std::vector<CPlane> &pyramid, const CMatrix &worldMatrix)
213 // Speed Clip: clip just the sphere.
214 CBSphere localSphere(_BBox.getCenter(), _BBox.getRadius());
215 CBSphere worldSphere;
217 // transform the sphere in WorldMatrix (with nearly good scale info).
218 localSphere.applyTransform(worldMatrix, worldSphere);
220 // if out of only plane, entirely out.
221 for(sint i=0;i<(sint)pyramid.size();i++)
223 // We are sure that pyramid has normalized plane normals.
224 // if SpherMax OUT return false.
225 float d= pyramid[i]*worldSphere.Center;
226 if(d>worldSphere.Radius)
227 return false;
230 return true;
234 // ***************************************************************************
235 void CSkeletonShape::getAABBox(NLMISC::CAABBox &bbox) const
237 bbox= _BBox;
241 // ***************************************************************************
242 uint CSkeletonShape::getLodForDistance(float dist) const
244 uint start=0;
245 uint end= (uint)_Lods.size();
246 // find lower_bound by dichotomy
247 while(end-1>start)
249 uint pivot= (end+start)/2;
250 // return the lower_bound, ie return first start with _Lods[pivot].Distance<=dist
251 if(_Lods[pivot].Distance <= dist)
252 start= pivot;
253 else
254 end= pivot;
257 return start;
261 } // NL3D