NL3D::CCameraCol Class Reference

#include <camera_col.h>


Detailed Description

A tool class used to compute differents info for camera collision
Author:
Lionel Berenguier

Nevrax France

Date:
2003

Definition at line 44 of file camera_col.h.

Public Member Functions

void build (const CVector &start, const CVector &end, float radius, bool cone)
 CCameraCol ()
void minimizeDistanceAgainstTri (const CVector &p0, const CVector &p1, const CVector &p2, float &sqrMinDist)

Data Fields

NLMISC::CAABBox BBox
bool Cone
CVector End
float Radius
CVector Start

Private Types

enum  { MaxNPlanes = 6 }

Private Attributes

CVector _ArrayIn [3+MaxNPlanes]
CVector _ArrayOut [3+MaxNPlanes]
float _MaxRadius
float _MaxRadiusProj
float _MinRadiusProj
uint _NPlanes
float _OODeltaRadiusProj
NLMISC::CPlane _Pyramid [MaxNPlanes]
float _RayLen
CVector _RayNorm


Member Enumeration Documentation

anonymous enum [private]
 

Enumeration values:
MaxNPlanes 

Definition at line 70 of file camera_col.h.

00070 {MaxNPlanes=6};


Constructor & Destructor Documentation

NL3D::CCameraCol::CCameraCol  ) 
 

Definition at line 43 of file camera_col.cpp.

00044 {
00045 }


Member Function Documentation

void NL3D::CCameraCol::build const CVector start,
const CVector end,
float  radius,
bool  cone
 

Definition at line 48 of file camera_col.cpp.

References _MaxRadius, _MaxRadiusProj, _MinRadiusProj, _NPlanes, _OODeltaRadiusProj, _Pyramid, _RayLen, _RayNorm, BBox, Cone, End, NLMISC::CAABBox::extend(), NLMISC::CAABBox::getHalfSize(), NLMISC::CPlane::make(), NL3D::NL3D_CameraSmoothRadiusFactor, NLMISC::CMatrix::normalize(), NLMISC::CVector::normed(), Radius, NLMISC::CAABBox::setCenter(), NLMISC::CAABBox::setHalfSize(), NLMISC::CMatrix::setPos(), NLMISC::CMatrix::setRot(), and Start.

Referenced by NL3D::CVisualCollisionManager::getCameraCollision(), and NL3D::CShadowPolyReceiver::getCameraCollision().

00049 {
00050         // copy
00051         Start= start;
00052         End= end;
00053         Radius= radius;
00054         Cone= cone;
00055         
00056         // For camera smoothing
00057         float   maxRadiusFactor= NL3D_CameraSmoothRadiusFactor;
00058         
00059         // not a Cone? => no smoothing
00060         if(!Cone)
00061                 maxRadiusFactor= 1;
00062 
00063         // **** Compute Camera smooth infos
00064         _MaxRadius= radius * maxRadiusFactor;
00065         _MinRadiusProj= Radius / (end-start).norm();
00066         _MaxRadiusProj= _MaxRadius / (end-start).norm();
00067         _RayNorm= (end-start).normed();
00068         _RayLen= (end-start).norm();
00069         _OODeltaRadiusProj= 0;
00070         if(_MaxRadiusProj>_MinRadiusProj)
00071                 _OODeltaRadiusProj= 1.f / (_MaxRadiusProj-_MinRadiusProj);
00072 
00073         // **** build the pyramid, with MaxRadius
00074         // approximate with a box
00075         CMatrix         mat;
00076         // Precision note: make the pyramid local to Start
00077         mat.setRot(CVector::I, (start-end).normed(), CVector::K);
00078         mat.normalize(CMatrix::YZX);
00079         // build the start 4 points
00080         CVector         ps[4];
00081         // cone or cylinder?
00082         if(cone)
00083         {
00084                 _NPlanes= 5;
00085                 // local to start!
00086                 ps[0]= CVector::Null;
00087                 ps[1]= CVector::Null;
00088                 ps[2]= CVector::Null;
00089                 ps[3]= CVector::Null;
00090         }
00091         else
00092         {
00093                 _NPlanes= 6;
00094                 // local to start!
00095                 ps[0]= mat * CVector(_MaxRadius, 0, -_MaxRadius);
00096                 ps[1]= mat * CVector(_MaxRadius, 0, _MaxRadius);
00097                 ps[2]= mat * CVector(-_MaxRadius, 0, _MaxRadius);
00098                 ps[3]= mat * CVector(-_MaxRadius, 0, -_MaxRadius);
00099         }
00100         // build the end 4 points
00101         CVector         pe[4];
00102         // local to start!
00103         mat.setPos(end-start);
00104         pe[0]= mat * CVector(_MaxRadius, 0, -_MaxRadius);
00105         pe[1]= mat * CVector(_MaxRadius, 0, _MaxRadius);
00106         pe[2]= mat * CVector(-_MaxRadius, 0, _MaxRadius);
00107         pe[3]= mat * CVector(-_MaxRadius, 0, -_MaxRadius);
00108         // try to roder for optimisation
00109         // left/right
00110         _Pyramid[0].make(ps[3], pe[3], pe[2]);
00111         _Pyramid[1].make(ps[1], pe[1], pe[0]);
00112         // back
00113         _Pyramid[2].make(pe[0], pe[1], pe[2]);
00114         // top-bottom
00115         _Pyramid[3].make(ps[2], pe[2], pe[1]);
00116         _Pyramid[4].make(ps[0], pe[0], pe[3]);
00117         // front if not cone
00118         if(!cone)
00119                 _Pyramid[5].make(ps[0], ps[2], ps[1]);
00120         
00121         // **** build the bbox
00122         BBox.setCenter(start);
00123         BBox.extend(end);
00124         // enlarge a bit for radius
00125         BBox.setHalfSize(BBox.getHalfSize()+CVector(_MaxRadius, _MaxRadius, _MaxRadius));
00126         
00127 }

void NL3D::CCameraCol::minimizeDistanceAgainstTri const CVector p0,
const CVector p1,
const CVector p2,
float &  sqrMinDist
 

compute the intersection of the Camera Volume against the triangle, and minimize minDist (actual square of distance) with min sqr distance of the poly.

Definition at line 131 of file camera_col.cpp.

References _ArrayIn, _ArrayOut, _MaxRadiusProj, _MinRadiusProj, _NPlanes, _OODeltaRadiusProj, _Pyramid, _RayLen, _RayNorm, NLMISC::clamp(), NLMISC::CPlane::clipPolygonBack(), NLMISC::CPlane::d, NLMISC::CPlane::getNormal(), NLMISC::CPlane::make(), MaxNPlanes, min, NL3D::NL3D_CameraSmoothNumAngleSample, NL3D::NL3D_CameraSmoothNumZSample, NLMISC::CVector::norm(), sint, NLMISC::sqr(), NLMISC::CVector::sqrnorm(), Start, uint, and z.

Referenced by NL3D::CVisualCollisionManager::CMeshCol::getCameraCollision(), and NL3D::CShadowPolyReceiver::getCameraCollision().

00132 {
00133         CVector         *pIn= _ArrayIn;
00134         CVector         *pOut= _ArrayOut;
00135         
00136         // **** clip triangle against the pyramid
00137         // build the triangle, local to start for precision problems
00138         pIn[0]= p0 - Start;
00139         pIn[1]= p1 - Start;
00140         pIn[2]= p2 - Start;
00141         sint    nVert= 3;
00142         // clip
00143         for(uint i=0;i<_NPlanes;i++)
00144         {
00145                 nVert= _Pyramid[i].clipPolygonBack(pIn, pOut, nVert);
00146                 swap(pIn, pOut);
00147                 if(!nVert)
00148                         break;
00149         }
00150 
00151         // **** if clipped => collision
00152         if(nVert)
00153         {
00154                 /*
00155                         Polygon nearest distance to a point is:
00156                                 - the nearest distance of all vertices
00157                                 - or the nearest distance to the plane (if the project lies in the polygon)
00158                                 - or the nearest distance to each edge
00159 
00160                         NB: testing only points works with low radius, but may fails in general case
00161                 */
00162 
00163                 // compute first the poly min distance
00164                 float   sqrPolyMinDist= FLT_MAX;
00165 
00166                 // **** get the nearest distance for all points (avoid precision problem if doing only edge ones)
00167                 sint    i;
00168                 for(i=0;i<nVert;i++)
00169                 {
00170                         // NB: pIn[i] is already local to start
00171                         float   sqrDist= pIn[i].sqrnorm();
00172                         if(sqrDist<sqrPolyMinDist)
00173                                 sqrPolyMinDist= sqrDist;
00174                 }
00175 
00176                 // **** get the nearest distance of the Start against each edge
00177                 for(i=0;i<nVert;i++)
00178                 {
00179                         const   CVector &v0= pIn[i];
00180                         const   CVector &v1= pIn[(i+1)%nVert];
00181                         CVector vDir= v1-v0;
00182                         // project on line
00183                         float   fLen= vDir.sqrnorm();   // same as  vDir * (v1 - v0)
00184                         // NB: Project CVector::Null, since we are local to start here!
00185                         float   fStart= vDir * (-v0);
00186                         // if start projection in the edge
00187                         if(fStart>0 && fStart<fLen)
00188                         {
00189                                 // compute distance to line
00190                                 CVector proj= v0 + (fStart / fLen) * vDir;
00191                                 // proj is local to Start
00192                                 float   sqrDist= proj.sqrnorm();
00193                                 if(sqrDist<sqrPolyMinDist)
00194                                         sqrPolyMinDist= sqrDist;
00195                         }
00196                 }
00197 
00198                 // **** get the nearest distance of the Start against the plane
00199                 // get the plane local to start
00200                 CPlane  plane;
00201                 plane.make(p0-Start, p1-Start, p2-Start);
00202                 // plane * StartLocalToStart == plane * CVector::Null == plane.d !
00203                 float   planeDist= plane.d;
00204                 // need to do the poly inclusion test only if the plane dist is better than the vertices
00205                 float   sqrPlaneDist= sqr(planeDist);
00206                 if(sqrPlaneDist < sqrPolyMinDist)
00207                 {
00208                         CVector normal= plane.getNormal();
00209 
00210                         // the projection of Start on the plane: StartLocalToStart + 
00211                         CVector proj= planeDist * normal;
00212                         // test poly inclusion
00213                         sint    sign= 0;
00214                         for(i=0;i<nVert;i++)
00215                         {
00216                                 const   CVector &v0= pIn[i];
00217                                 const   CVector &v1= pIn[(i+1)%nVert];
00218                                 float   d = ((v1-v0)^normal)*(proj-v0);
00219                                 if(d<0)
00220                                 {
00221                                         if(sign==1) break;
00222                                         else    sign=-1;
00223                                 }
00224                                 else if(d>0)
00225                                 {
00226                                         if(sign==-1) break;
00227                                         else    sign=1;
00228                                 }
00229                                 else
00230                                         break;
00231                         }
00232 
00233                         // if succeed, minimize
00234                         if(i==nVert)
00235                                 sqrPolyMinDist= sqrPlaneDist;
00236                 }
00237 
00238                 // **** Camera Smoothing: modulate according to angle of poly against cone
00239                 // Camera smooth not enabled?
00240                 if(_MaxRadiusProj<=_MinRadiusProj)
00241                 {
00242                         // then just take minum
00243                         if(sqrPolyMinDist<sqrMinDist)
00244                                 sqrMinDist= sqrPolyMinDist;
00245                 }
00246                 // Camera Smooth mode. if the unmodulated distance is lower than the current minDist, 
00247                 // then this poly may be interesting, else don't have a chance
00248                 else if(sqrPolyMinDist<sqrMinDist)
00249                 {
00250                         float   sampleZSize= _RayLen / NL3D_CameraSmoothNumZSample;
00251                         float   sampleProjSize= 2*_MaxRadiusProj / NL3D_CameraSmoothNumAngleSample;
00252 
00253                         // **** Compute num Subdivision required
00254                         // To compute the number of subdivision, let's take the max of 2 req:
00255                         // the subdivision in Z (for Distance part of the function)
00256                         // the subdivision in Projection (for angle part of the function)
00257 
00258                         // Project all vertices to the plane
00259                         static  CVector pProj[3+MaxNPlanes];
00260                         float   minZ= _RayLen;
00261                         float   maxZ= 0;
00262                         for(i=0;i<nVert;i++)
00263                         {
00264                                 float   z= pIn[i] * _RayNorm;
00265                                 minZ= min(minZ, z);
00266                                 maxZ= max(maxZ, z);
00267                                 // cause of pyramid cliping, z should be >=0
00268                                 if(z>0)
00269                                         pProj[i]= pIn[i] / z;
00270                                 else
00271                                         pProj[i]= CVector::Null;
00272                                 
00273                                 // make local
00274                                 pProj[i]-= _RayNorm;
00275                         }
00276                         // Compute perimeter of projected poly
00277                         float   perimeterProj= 0;
00278                         for(i=0;i<nVert;i++)
00279                         {
00280                                 perimeterProj+= (pProj[(i+1)%nVert]-pProj[i]).norm();
00281                         }
00282 
00283                         // compute the number of subdivision required on Z
00284                         uint    numSubdivZ= (uint)((maxZ-minZ) / sampleZSize);
00285                         // suppose a full projected quad perimeter will require max samples
00286                         uint    numSubdivAngle= (uint)(perimeterProj / (4*sampleProjSize));
00287                         // the number of subdivision
00288                         uint    numSubdiv= max(numSubdivZ, numSubdivAngle);
00289                         numSubdiv= max(numSubdiv, (uint)1);
00290                         float   ooNumSubdiv= 1.f / (float)numSubdiv;
00291                         
00292                         // **** Sample the polygon, to compute the minimum of the function
00293                         // for each tri of the polygon
00294                         for(sint tri=0;tri<nVert-2;tri++)
00295                         {
00296                                 CVector         lp[3];
00297                                 // optim: prediv by numSubdiv
00298                                 lp[0]= pIn[0] * ooNumSubdiv;
00299                                 lp[1]= pIn[tri+1] * ooNumSubdiv;
00300                                 lp[2]= pIn[tri+2] * ooNumSubdiv;
00301                                 
00302                                 // sample using barycentric coordinates
00303                                 for(uint i=0;i<=numSubdiv;i++)
00304                                 {
00305                                         for(uint j=0;j<=numSubdiv-i;j++)
00306                                         {
00307                                                 uint    k= numSubdiv - i - j;
00308                                                 CVector sample= lp[0] * (float)i + lp[1] * (float)j + lp[2] * (float)k;
00309                                                 
00310                                                 // NB: sample is already local to start
00311                                                 float   sqrDist= sample.sqrnorm();
00312                                                 
00313                                                 // **** get the point projection 
00314                                                 float           z= sample * _RayNorm;
00315                                                 CVector         proj;
00316                                                 // cause of pyramid cliping, z should be >=0
00317                                                 if(z>0)
00318                                                         proj= sample / z;
00319                                                 else
00320                                                         proj= CVector::Null;
00321                                                 // make local
00322                                                 proj-= _RayNorm;
00323                                                 
00324                                                 // **** compute the Cone Linear factor (like a spot light)
00325                                                 float   rayDist= proj.norm();
00326                                                 float   angleFactor= (rayDist-_MinRadiusProj) * _OODeltaRadiusProj;
00327                                                 clamp(angleFactor, 0.f, 1.f);
00328                                                 // avoid C1 discontinuity when angleFactor==0
00329                                                 angleFactor= sqr(angleFactor);
00330                                                 
00331                                                 // **** modulate, but to a bigger value! (ie raylen)
00332                                                 sqrDist= _RayLen * angleFactor + sqrtf(sqrDist) * (1-angleFactor);
00333                                                 sqrDist= sqr(sqrDist);
00334                                                 
00335                                                 // if distance is lesser, take it
00336                                                 if(sqrDist<sqrMinDist)
00337                                                         sqrMinDist= sqrDist;
00338                                         }
00339                                 }                       
00340                         }
00341                 }
00342         }
00343 }


Field Documentation

CVector NL3D::CCameraCol::_ArrayIn[3+MaxNPlanes] [private]
 

Definition at line 73 of file camera_col.h.

Referenced by minimizeDistanceAgainstTri().

CVector NL3D::CCameraCol::_ArrayOut[3+MaxNPlanes] [private]
 

Definition at line 74 of file camera_col.h.

Referenced by minimizeDistanceAgainstTri().

float NL3D::CCameraCol::_MaxRadius [private]
 

Definition at line 81 of file camera_col.h.

Referenced by build().

float NL3D::CCameraCol::_MaxRadiusProj [private]
 

Definition at line 84 of file camera_col.h.

Referenced by build(), and minimizeDistanceAgainstTri().

float NL3D::CCameraCol::_MinRadiusProj [private]
 

Definition at line 83 of file camera_col.h.

Referenced by build(), and minimizeDistanceAgainstTri().

uint NL3D::CCameraCol::_NPlanes [private]
 

Definition at line 78 of file camera_col.h.

Referenced by build(), and minimizeDistanceAgainstTri().

float NL3D::CCameraCol::_OODeltaRadiusProj [private]
 

Definition at line 85 of file camera_col.h.

Referenced by build(), and minimizeDistanceAgainstTri().

NLMISC::CPlane NL3D::CCameraCol::_Pyramid[MaxNPlanes] [private]
 

Definition at line 77 of file camera_col.h.

Referenced by build(), and minimizeDistanceAgainstTri().

float NL3D::CCameraCol::_RayLen [private]
 

Definition at line 86 of file camera_col.h.

Referenced by build(), and minimizeDistanceAgainstTri().

CVector NL3D::CCameraCol::_RayNorm [private]
 

Definition at line 87 of file camera_col.h.

Referenced by build(), and minimizeDistanceAgainstTri().

NLMISC::CAABBox NL3D::CCameraCol::BBox
 

Definition at line 57 of file camera_col.h.

Referenced by build(), NL3D::CVisualCollisionManager::CMeshCol::getCameraCollision(), NL3D::CVisualCollisionManager::getCameraCollision(), and NL3D::CShadowPolyReceiver::getCameraCollision().

bool NL3D::CCameraCol::Cone
 

Definition at line 54 of file camera_col.h.

Referenced by build().

CVector NL3D::CCameraCol::End
 

Definition at line 50 of file camera_col.h.

Referenced by build(), and NL3D::CVisualCollisionManager::CMeshCol::getCameraCollision().

float NL3D::CCameraCol::Radius
 

Definition at line 52 of file camera_col.h.

Referenced by build().

CVector NL3D::CCameraCol::Start
 

Definition at line 48 of file camera_col.h.

Referenced by build(), NL3D::CVisualCollisionManager::CMeshCol::getCameraCollision(), and minimizeDistanceAgainstTri().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 06:44:52 2004 for NeL by doxygen 1.3.6