# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

skeleton_shape.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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         // By default for now....
00054         // Temp. Have a huge BBox, so clip badly. 
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         // copy bones.
00077         _Bones= bones;
00078 
00079         // for all bones
00080         for(i=0;i<_Bones.size();i++)
00081         {
00082                 // build the map.
00083                 _BoneMap[_Bones[i].Name]= i;
00084                 // validate distances.
00085                 _Bones[i].LodDisableDistance= max(0.f, _Bones[i].LodDisableDistance);
00086 
00087                 // get fahter dist.
00088                 sint32  fatherId= _Bones[i].FatherId;
00089                 // if father exist and is not "always enabled"
00090                 if(fatherId>=0 && _Bones[fatherId].LodDisableDistance!=0)
00091                 {
00092                         float   fatherDist= _Bones[fatherId].LodDisableDistance;
00093                         // I must disable me at least before my father (never after).
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         // build Lod Information.
00102         //==============
00103         _Lods.clear();
00104 
00105         // build all distances used.
00106         set<float>      distSet;
00107         for(i=0;i<_Bones.size();i++)
00108         {
00109                 float   dist= _Bones[i].LodDisableDistance;
00110                 // if lod enabled for this bone, add a new distance, or do nothing
00111                 if(dist>0)
00112                         distSet.insert(dist);
00113         }
00114 
00115         // create a lod for each distance used + 1 (the "dist==0" distance).
00116         _Lods.resize(distSet.size() + 1);
00117         // create the default lod: all bones activated.
00118         _Lods[0].Distance=0;
00119         _Lods[0].ActiveBones.resize(_Bones.size(), 0xFF);
00120 
00121         // For each lods not 0th.
00122         set<float>::iterator    it= distSet.begin();
00123         for(uint j=1; j<_Lods.size(); j++, it++)
00124         {
00125                 float   lodDist= *it;
00126                 // set the distance of activation
00127                 _Lods[j].Distance= lodDist;
00128                 // resize and default to all enabled.
00129                 _Lods[j].ActiveBones.resize(_Bones.size(), 0xFF);
00130 
00131                 // Search what lod are to be disabled at this distance.
00132                 for(i=0;i<_Bones.size();i++)
00133                 {
00134                         float   dist= _Bones[i].LodDisableDistance;
00135                         // if the dist of the lod is greater (or equal) to the disableDist of the bone, 
00136                         // and if the bone is not "always enabled", disable the bone
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         // Create a CSkeletonModel, an instance of a mesh.
00157         //===============================================
00158         CSkeletonModel          *sm= (CSkeletonModel*)scene.createModel(NL3D::SkeletonModelId);
00159         sm->Shape= this;
00160 
00161         // setup bones.
00162         //=================
00163         sm->Bones.reserve(_Bones.size());
00164         for(sint i=0;i<(sint)_Bones.size();i++)
00165         {
00166                 // Append a new bone.
00167                 sm->Bones.push_back( CBone(&_Bones[i]) );
00168 
00169                 // Must set the Animatable father of the bone (the skeleton model!).
00170                 sm->Bones[i].setFather(sm, CSkeletonModel::OwnerBit);
00171         }
00172 
00173         // Must create and init skeleton bone usage to 0.
00174         sm->initBoneUsages();
00175 
00176         // For skinning: setup skeleton in Skin LoadBalancing group
00177         sm->setLoadBalancingGroup("Skin");
00178 
00179         return sm;
00180 }
00181 
00182 // ***************************************************************************
00183 void                    CSkeletonShape::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00184 {
00185         /*
00186         Version 1:
00187                 - _Lods.
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                 // create a skeleton shape with bones activated all the time
00199                 _Lods.resize(1);
00200                 // create the default lod: all bones activated.
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         // No polygons
00211         return 0;
00212 }
00213 
00214 
00215 // ***************************************************************************
00216 bool    CSkeletonShape::clip(const std::vector<CPlane>  &pyramid, const CMatrix &worldMatrix)
00217 {
00218         // Speed Clip: clip just the sphere.
00219         CBSphere        localSphere(_BBox.getCenter(), _BBox.getRadius());
00220         CBSphere        worldSphere;
00221 
00222         // transform the sphere in WorldMatrix (with nearly good scale info).
00223         localSphere.applyTransform(worldMatrix, worldSphere);
00224 
00225         // if out of only plane, entirely out.
00226         for(sint i=0;i<(sint)pyramid.size();i++)
00227         {
00228                 // We are sure that pyramid has normalized plane normals.
00229                 // if SpherMax OUT return false.
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         // find lower_bound by dichotomy
00252         while(end-1>start)
00253         {
00254                 uint    pivot= (end+start)/2;
00255                 // return the lower_bound, ie return first start with _Lods[pivot].Distance<=dist
00256                 if(_Lods[pivot].Distance <= dist)
00257                         start= pivot;
00258                 else
00259                         end= pivot;
00260         }
00261 
00262         return start;
00263 }
00264 
00265 
00266 } // NL3D