#include <camera_col.h>
Nevrax France
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 |
|
|
Definition at line 70 of file camera_col.h.
00070 {MaxNPlanes=6};
|
|
|
Definition at line 43 of file camera_col.cpp.
00044 {
00045 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
Definition at line 73 of file camera_col.h. Referenced by minimizeDistanceAgainstTri(). |
|
|
Definition at line 74 of file camera_col.h. Referenced by minimizeDistanceAgainstTri(). |
|
|
Definition at line 81 of file camera_col.h. Referenced by build(). |
|
|
Definition at line 84 of file camera_col.h. Referenced by build(), and minimizeDistanceAgainstTri(). |
|
|
Definition at line 83 of file camera_col.h. Referenced by build(), and minimizeDistanceAgainstTri(). |
|
|
Definition at line 78 of file camera_col.h. Referenced by build(), and minimizeDistanceAgainstTri(). |
|
|
Definition at line 85 of file camera_col.h. Referenced by build(), and minimizeDistanceAgainstTri(). |
|
|
Definition at line 77 of file camera_col.h. Referenced by build(), and minimizeDistanceAgainstTri(). |
|
|
Definition at line 86 of file camera_col.h. Referenced by build(), and minimizeDistanceAgainstTri(). |
|
|
Definition at line 87 of file camera_col.h. Referenced by build(), and minimizeDistanceAgainstTri(). |
|
|
Definition at line 57 of file camera_col.h. Referenced by build(), NL3D::CVisualCollisionManager::CMeshCol::getCameraCollision(), NL3D::CVisualCollisionManager::getCameraCollision(), and NL3D::CShadowPolyReceiver::getCameraCollision(). |
|
|
Definition at line 54 of file camera_col.h. Referenced by build(). |
|
|
Definition at line 50 of file camera_col.h. Referenced by build(), and NL3D::CVisualCollisionManager::CMeshCol::getCameraCollision(). |
|
|
Definition at line 52 of file camera_col.h. Referenced by build(). |
|
|
Definition at line 48 of file camera_col.h. Referenced by build(), NL3D::CVisualCollisionManager::CMeshCol::getCameraCollision(), and minimizeDistanceAgainstTri(). |
1.3.6