#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(). |