00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/skeleton_shape.h"
00029 #include "3d/skeleton_model.h"
00030 #include "3d/scene.h"
00031 #include "nel/misc/bsphere.h"
00032
00033 using namespace std;
00034 using namespace NLMISC;
00035
00036 namespace NL3D
00037 {
00038
00039
00040
00041 void CSkeletonShape::CLod::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00042 {
00043 (void)f.serialVersion(0);
00044
00045 f.serial(Distance);
00046 f.serialCont(ActiveBones);
00047 }
00048
00049
00050
00051 CSkeletonShape::CSkeletonShape()
00052 {
00053
00054
00055 _BBox.setCenter(CVector(0,0,1.5));
00056 _BBox.setSize(CVector(3,3,3));
00057 }
00058
00059
00060
00061 sint32 CSkeletonShape::getBoneIdByName(const std::string &name) const
00062 {
00063 std::map<std::string, uint32>::const_iterator it= _BoneMap.find(name);
00064 if(it==_BoneMap.end())
00065 return -1;
00066 else
00067 return it->second;
00068 }
00069
00070
00071
00072 void CSkeletonShape::build(const std::vector<CBoneBase> &bones)
00073 {
00074 uint i;
00075
00076
00077 _Bones= bones;
00078
00079
00080 for(i=0;i<_Bones.size();i++)
00081 {
00082
00083 _BoneMap[_Bones[i].Name]= i;
00084
00085 _Bones[i].LodDisableDistance= max(0.f, _Bones[i].LodDisableDistance);
00086
00087
00088 sint32 fatherId= _Bones[i].FatherId;
00089
00090 if(fatherId>=0 && _Bones[fatherId].LodDisableDistance!=0)
00091 {
00092 float fatherDist= _Bones[fatherId].LodDisableDistance;
00093
00094 if(_Bones[i].LodDisableDistance==0)
00095 _Bones[i].LodDisableDistance= fatherDist;
00096 else
00097 _Bones[i].LodDisableDistance= min(_Bones[i].LodDisableDistance, fatherDist);
00098 }
00099 }
00100
00101
00102
00103 _Lods.clear();
00104
00105
00106 set<float> distSet;
00107 for(i=0;i<_Bones.size();i++)
00108 {
00109 float dist= _Bones[i].LodDisableDistance;
00110
00111 if(dist>0)
00112 distSet.insert(dist);
00113 }
00114
00115
00116 _Lods.resize(distSet.size() + 1);
00117
00118 _Lods[0].Distance=0;
00119 _Lods[0].ActiveBones.resize(_Bones.size(), 0xFF);
00120
00121
00122 set<float>::iterator it= distSet.begin();
00123 for(uint j=1; j<_Lods.size(); j++, it++)
00124 {
00125 float lodDist= *it;
00126
00127 _Lods[j].Distance= lodDist;
00128
00129 _Lods[j].ActiveBones.resize(_Bones.size(), 0xFF);
00130
00131
00132 for(i=0;i<_Bones.size();i++)
00133 {
00134 float dist= _Bones[i].LodDisableDistance;
00135
00136
00137 if(lodDist>=dist && dist!=0 )
00138 _Lods[j].ActiveBones[i]= 0;
00139 }
00140
00141 }
00142
00143 }
00144
00145
00146
00147 void CSkeletonShape::retrieve(std::vector<CBoneBase> &bones) const
00148 {
00149 bones= _Bones;
00150 }
00151
00152
00153
00154 CTransformShape *CSkeletonShape::createInstance(CScene &scene)
00155 {
00156
00157
00158 CSkeletonModel *sm= (CSkeletonModel*)scene.createModel(NL3D::SkeletonModelId);
00159 sm->Shape= this;
00160
00161
00162
00163 sm->Bones.reserve(_Bones.size());
00164 for(sint i=0;i<(sint)_Bones.size();i++)
00165 {
00166
00167 sm->Bones.push_back( CBone(&_Bones[i]) );
00168
00169
00170 sm->Bones[i].setFather(sm, CSkeletonModel::OwnerBit);
00171 }
00172
00173
00174 sm->initBoneUsages();
00175
00176
00177 sm->setLoadBalancingGroup("Skin");
00178
00179 return sm;
00180 }
00181
00182
00183 void CSkeletonShape::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00184 {
00185
00186
00187
00188
00189 sint ver= f.serialVersion(1);
00190
00191 f.serialCont(_Bones);
00192 f.serialCont(_BoneMap);
00193
00194 if(ver>=1)
00195 f.serialCont(_Lods);
00196 else
00197 {
00198
00199 _Lods.resize(1);
00200
00201 _Lods[0].Distance=0;
00202 _Lods[0].ActiveBones.resize(_Bones.size(), 0xFF);
00203 }
00204 }
00205
00206
00207
00208 float CSkeletonShape::getNumTriangles (float distance)
00209 {
00210
00211 return 0;
00212 }
00213
00214
00215
00216 bool CSkeletonShape::clip(const std::vector<CPlane> &pyramid, const CMatrix &worldMatrix)
00217 {
00218
00219 CBSphere localSphere(_BBox.getCenter(), _BBox.getRadius());
00220 CBSphere worldSphere;
00221
00222
00223 localSphere.applyTransform(worldMatrix, worldSphere);
00224
00225
00226 for(sint i=0;i<(sint)pyramid.size();i++)
00227 {
00228
00229
00230 float d= pyramid[i]*worldSphere.Center;
00231 if(d>worldSphere.Radius)
00232 return false;
00233 }
00234
00235 return true;
00236 }
00237
00238
00239
00240 void CSkeletonShape::getAABBox(NLMISC::CAABBox &bbox) const
00241 {
00242 bbox= _BBox;
00243 }
00244
00245
00246
00247 uint CSkeletonShape::getLodForDistance(float dist) const
00248 {
00249 uint start=0;
00250 uint end= _Lods.size();
00251
00252 while(end-1>start)
00253 {
00254 uint pivot= (end+start)/2;
00255
00256 if(_Lods[pivot].Distance <= dist)
00257 start= pivot;
00258 else
00259 end= pivot;
00260 }
00261
00262 return start;
00263 }
00264
00265
00266 }