# 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  

ps_face_look_at.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/ps_face_look_at.h"
00029 #include "3d/ps_macro.h"
00030 #include "3d/driver.h"
00031 #include "3d/fast_floor.h"
00032 #include "3d/ps_iterator.h"
00033 
00034 
00035 namespace NL3D 
00036 {
00037 
00038 
00039 
00041 // CPSFaceLookAt implementation //
00043 
00044 
00050 class CPSFaceLookAtHelper
00051 {
00052 public:
00053         template <class T>      
00054         static void drawLookAt(T it, T speedIt, CPSFaceLookAt &la, uint size, uint32 srcStep)
00055         {
00056                 PARTICLES_CHECK_MEM;    
00057                 nlassert(la._Owner);                    
00058                 IDriver *driver = la.getDriver();
00059 
00060                 la.updateMatBeforeRendering(driver);
00061                 
00062                 CVertexBuffer &vb = la.getNeededVB();
00063                 la._Owner->incrementNbDrawnParticles(size); // for benchmark purpose    
00064                 la.setupDriverModelMatrix();
00065                 driver->activeVertexBuffer(vb); 
00066                 const CVector I = la.computeI();
00067                 const CVector J = la.computeJ();
00068                 const CVector K = la.computeK();                
00069                 const float *rotTable = CPSRotated2DParticle::getRotTable();    
00070                 // for each the particle can be constantly rotated or have an independant rotation for each particle
00071                 // number of face left, and number of face to process at once
00072                 uint32 leftToDo = size, toProcess;
00073                 float pSizes[CPSQuad::quadBufSize]; // the sizes to use 
00074                 float pSecondSizes[CPSQuad::quadBufSize]; // the second sizes to use
00075                 float *currentSize; 
00076                 uint32 currentSizeStep = la._SizeScheme ? 1 : 0;
00077                 // point the vector part in the current vertex
00078                 uint8 *ptPos;
00079                 // strides to go from one vertex to another one
00080                 const uint32 stride = vb.getVertexSize(), stride2 = stride << 1, stride3 = stride + stride2, stride4 = stride << 2;     
00081                 if (!la._Angle2DScheme)
00082                 {
00083                         // constant rotation case
00084                         do
00085                         {                       
00086                                 // restart at the beginning of the vertex buffer
00087                                 ptPos = (uint8 *) vb.getVertexCoordPointer();
00088                                 toProcess = leftToDo <= CPSQuad::quadBufSize ? leftToDo : CPSQuad::quadBufSize;
00089 
00090                                 if (la._SizeScheme)
00091                                 {
00092                                         currentSize = (float *) la._SizeScheme->make(la._Owner, size- leftToDo, pSizes, sizeof(float), toProcess, true, srcStep);
00093                                 }
00094                                 else
00095                                 {
00096                                         currentSize = &la._ParticleSize;
00097                                 }
00098                                 
00099                                 la.updateVbColNUVForRender(vb, size - leftToDo, toProcess, srcStep);                                    
00100                                 T endIt = it + toProcess;
00101                                 if (la._MotionBlurCoeff == 0.f)
00102                                 {
00103                                         if (!la._IndependantSizes)
00104                                         {                                               
00105                                                 const uint32 tabIndex = (((uint32) la._Angle2D) & 0xff) << 2;
00106                                                 const CVector v1 = rotTable[tabIndex] * I + rotTable[tabIndex + 1] * K;
00107                                                 const CVector v2 = rotTable[tabIndex + 2] * I + rotTable[tabIndex + 3] * K;
00108                                                 if (currentSizeStep)
00109                                                 {
00110                                                         while (it != endIt)
00111                                                         {
00112                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00113                                                                 ((CVector *) ptPos)->x = (*it).x  + *currentSize * v1.x;                        
00114                                                                 ((CVector *) ptPos)->y = (*it).y  + *currentSize * v1.y;                        
00115                                                                 ((CVector *) ptPos)->z = (*it).z  + *currentSize * v1.z;                        
00116                                                                 ptPos += stride;
00117 
00118                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00119                                                                 ((CVector *) ptPos)->x = (*it).x  + *currentSize * v2.x;                        
00120                                                                 ((CVector *) ptPos)->y = (*it).y  + *currentSize * v2.y;                        
00121                                                                 ((CVector *) ptPos)->z = (*it).z  + *currentSize * v2.z;                        
00122                                                                 ptPos += stride;
00123 
00124                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00125                                                                 ((CVector *) ptPos)->x = (*it).x  - *currentSize * v1.x;                        
00126                                                                 ((CVector *) ptPos)->y = (*it).y  - *currentSize * v1.y;                        
00127                                                                 ((CVector *) ptPos)->z = (*it).z  - *currentSize * v1.z;                        
00128                                                                 ptPos += stride;
00129 
00130                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00131                                                                 ((CVector *) ptPos)->x = (*it).x  - *currentSize * v2.x;                        
00132                                                                 ((CVector *) ptPos)->y = (*it).y  - *currentSize * v2.y;                        
00133                                                                 ((CVector *) ptPos)->z = (*it).z  - *currentSize * v2.z;                        
00134                                                                 ptPos += stride;                                                        
00135 
00136                                                                 ++it;
00137                                                                 currentSize += currentSizeStep;                                 
00138                                                         }
00139                                                 }
00140                                                 else
00141                                                 {
00142                                                         // constant size
00143                                                         const CVector myV1 = *currentSize * v1;
00144                                                         const CVector myV2 = *currentSize * v2;
00145 
00146                                                         while (it != endIt)
00147                                                         {
00148                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00149                                                                 ((CVector *) ptPos)->x = (*it).x  + myV1.x;                     
00150                                                                 ((CVector *) ptPos)->y = (*it).y  + myV1.y;                     
00151                                                                 ((CVector *) ptPos)->z = (*it).z  + myV1.z;                     
00152                                                                 ptPos += stride;
00153 
00154                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00155                                                                 ((CVector *) ptPos)->x = (*it).x  + myV2.x;                     
00156                                                                 ((CVector *) ptPos)->y = (*it).y  + myV2.y;                     
00157                                                                 ((CVector *) ptPos)->z = (*it).z  + myV2.z;                     
00158                                                                 ptPos += stride;
00159 
00160                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00161                                                                 ((CVector *) ptPos)->x = (*it).x  - myV1.x;                     
00162                                                                 ((CVector *) ptPos)->y = (*it).y  - myV1.y;                     
00163                                                                 ((CVector *) ptPos)->z = (*it).z  - myV1.z;                     
00164                                                                 ptPos += stride;
00165 
00166                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00167                                                                 ((CVector *) ptPos)->x = (*it).x  - myV2.x;                     
00168                                                                 ((CVector *) ptPos)->y = (*it).y  - myV2.y;                     
00169                                                                 ((CVector *) ptPos)->z = (*it).z  - myV2.z;                     
00170                                                                 ptPos += stride;                                                        
00171                                                                 ++it;                                                                                   
00172                                                         }
00173                                                 }
00174                                         }
00175                                         else // independant sizes
00176                                         {                       
00177                                                 const CVector v1 = CPSUtil::getCos((sint32) la._Angle2D) * I  + CPSUtil::getSin((sint32) la._Angle2D) * K;
00178                                                 const CVector v2 = - CPSUtil::getSin((sint32) la._Angle2D) * I + CPSUtil::getCos((sint32) la._Angle2D) * K;
00179 
00180                                                 float *currentSize2;
00181                                                 float secondSize;
00182                                                 uint32 currentSizeStep2;
00183                                                 if (la._SecondSize.getSizeScheme())
00184                                                 {
00185                                                         currentSize2 = (float *) la._SecondSize.getSizeScheme()->make(la._Owner, size- leftToDo, pSecondSizes, sizeof(float), toProcess, true, srcStep);
00186                                                         currentSizeStep2 = 1;
00187                                                 }
00188                                                 else
00189                                                 {       
00190                                                         secondSize = la._SecondSize.getSize();
00191                                                         currentSize2 = &secondSize;
00192                                                         currentSizeStep2 = 0;
00193                                                 }
00194                                                  
00195 
00196                                                 while (it != endIt)
00197                                                 {
00198                                                         CHECK_VERTEX_BUFFER(vb, ptPos);
00199                                                         ((CVector *) ptPos)->x = (*it).x  - *currentSize * v1.x + *currentSize2 * v2.x;                         
00200                                                         ((CVector *) ptPos)->y = (*it).y  - *currentSize * v1.y + *currentSize2 * v2.y;                         
00201                                                         ((CVector *) ptPos)->z = (*it).z  - *currentSize * v1.z + *currentSize2 * v2.z;
00202                                                         ptPos += stride;
00203 
00204                                                         CHECK_VERTEX_BUFFER(vb, ptPos);
00205                                                         ((CVector *) ptPos)->x = (*it).x  + *currentSize * v1.x + *currentSize2 * v2.x;                         
00206                                                         ((CVector *) ptPos)->y = (*it).y  + *currentSize * v1.y + *currentSize2 * v2.y;                         
00207                                                         ((CVector *) ptPos)->z = (*it).z  + *currentSize * v1.z + *currentSize2 * v2.z;
00208                                                         ptPos += stride;
00209 
00210                                                         CHECK_VERTEX_BUFFER(vb, ptPos);
00211                                                         ((CVector *) ptPos)->x = (*it).x  + *currentSize * v1.x - *currentSize2 * v2.x;                         
00212                                                         ((CVector *) ptPos)->y = (*it).y  + *currentSize * v1.y - *currentSize2 * v2.y;                         
00213                                                         ((CVector *) ptPos)->z = (*it).z  + *currentSize * v1.z - *currentSize2 * v2.z;
00214                                                         ptPos += stride;
00215 
00216                                                         CHECK_VERTEX_BUFFER(vb, ptPos);
00217                                                         ((CVector *) ptPos)->x = (*it).x  - *currentSize * v1.x - *currentSize2 * v2.x;                         
00218                                                         ((CVector *) ptPos)->y = (*it).y  - *currentSize * v1.y - *currentSize2 * v2.y;                         
00219                                                         ((CVector *) ptPos)->z = (*it).z  - *currentSize * v1.z - *currentSize2 * v2.z;
00220                                                         ptPos += stride;
00221                                                         ++it;
00222                                                         currentSize += currentSizeStep;
00223                                                         currentSize2 += currentSizeStep2;
00224                                                 }                                       
00225                                         }
00226                                 }
00227                                 else
00228                                 {
00229                                         // perform motion, blur, we need an iterator on speed
00230                                         // independant sizes and rotation not supported for now with motion blur                                
00231                                         const CVector v1 = I + K;
00232                                         const CVector v2 = K - I;                                                               
00233                                         CVector startV, endV, mbv1, mbv1n, mbv12, mbv2;
00234                                         // norme of the v1 vect
00235                                         float n;
00236                                         const float epsilon  = 10E-5f;
00237                                         const float normEpsilon  = 10E-6f;
00238                                         
00239                                         CMatrix tMat =  la._Owner->isInSystemBasis() ? la.getViewMat()  *  la.getSysMat()
00240                                                                                                                           : la.getViewMat();
00241                         
00242                                         while (it != endIt)
00243                                         {
00244                                                 // project the speed in the projection plane
00245                                                 // this give us the v1 vect
00246                                                 startV = tMat * *it ;                                           
00247                                                 endV = tMat * (*it + *speedIt);                                                                                                 
00248                                                 if (startV.y > epsilon || endV.y > epsilon)                                                                                                                                                                                                                                                                             
00249                                                 {       
00250                                                         if (startV.y < epsilon)
00251                                                         {
00252                                                                 if (fabsf(endV.y - startV.y) > normEpsilon)
00253                                                                 {
00254                                                                         startV = endV + (endV.y - epsilon) / (endV.y - startV.y) * (startV - endV);
00255                                                                 }
00256                                                                 startV.y = epsilon;
00257                                                         }
00258                                                         else if (endV.y < epsilon)
00259                                                         {       
00260                                                                 if (fabsf(endV.y - startV.y) > normEpsilon)
00261                                                                 {
00262                                                                         endV = startV + (startV.y - epsilon) / (startV.y - endV.y) * (endV - startV);
00263                                                                 }
00264                                                                 endV.y = epsilon;
00265                                                         }                                                                                                               
00266 
00267                                                         mbv1 = (startV.x / startV.y - endV.x / endV.y) * I
00268                                                                                         + (startV.z / startV.y - endV.z / endV.y) * K ;                                         
00269                                                 
00270                                                         n = mbv1.norm();
00271                                                         if (n > la._Threshold)
00272                                                         {
00273                                                                 mbv1 *= la._Threshold / n;
00274                                                                 n = la._Threshold;                                                              
00275                                                         }                                                                                                                                                                                                               
00276                                                         if (n > normEpsilon)                                                                                            
00277                                                         {                                                                                                                                                                                       
00278                                                                 mbv1n = mbv1 / n;                                                                                                               
00279                                                                 mbv2 = *currentSize * (J ^ mbv1n);
00280                                                                 mbv12 = -*currentSize * mbv1n;                                                  
00281                                                                 mbv1 *= *currentSize * (1 + la._MotionBlurCoeff * n * n) / n;
00282                                                         
00283                                                                 *(CVector *) ptPos = *it - mbv2;                                                                                                
00284                                                                 *(CVector *) (ptPos + stride) = *it  + mbv1;                    
00285                                                                 *(CVector *) (ptPos + stride2) = *it + mbv2;    
00286                                                                 *(CVector *) (ptPos + stride3) = *it + mbv12;
00287                                                         
00288                                                         
00289                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00290                                                                 ((CVector *) ptPos)->x = (*it).x  - mbv2.x;                     
00291                                                                 ((CVector *) ptPos)->y = (*it).y  - mbv2.y;
00292                                                                 ((CVector *) ptPos)->z = (*it).z  - mbv2.z;
00293                                                                 
00294                                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride);
00295                                                                 ((CVector *) (ptPos + stride))->x = (*it).x  + mbv1.x;                          
00296                                                                 ((CVector *) (ptPos + stride))->y = (*it).y  + mbv1.y;                          
00297                                                                 ((CVector *) (ptPos + stride))->z = (*it).z  + mbv1.z;                          
00298 
00299                                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride2);
00300                                                                 ((CVector *) (ptPos + stride2))->x = (*it).x  + mbv2.x;                         
00301                                                                 ((CVector *) (ptPos + stride2))->y = (*it).y  + mbv2.y;                         
00302                                                                 ((CVector *) (ptPos + stride2))->z = (*it).z  + mbv2.z;                         
00303 
00304 
00305                                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride3);
00306                                                                 ((CVector *) (ptPos + stride3))->x = (*it).x  + mbv12.x;                        
00307                                                                 ((CVector *) (ptPos + stride3))->y = (*it).y  + mbv12.y;                        
00308                                                                 ((CVector *) (ptPos + stride3))->z = (*it).z  + mbv12.z;                                                                                                
00309                                                                 
00310                                                         }
00311                                                         else // speed too small, we must avoid imprecision
00312                                                         {
00313                                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00314                                                                 ((CVector *) ptPos)->x = (*it).x  - *currentSize * v2.x;                        
00315                                                                 ((CVector *) ptPos)->y = (*it).y  - *currentSize * v2.y;                        
00316                                                                 ((CVector *) ptPos)->z = (*it).z  - *currentSize * v2.z;                        
00317                                                                 
00318                                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride);
00319                                                                 ((CVector *) (ptPos + stride))->x = (*it).x  + *currentSize * v1.x;                     
00320                                                                 ((CVector *) (ptPos + stride))->y = (*it).y  + *currentSize * v1.y;                     
00321                                                                 ((CVector *) (ptPos + stride))->z = (*it).z  + *currentSize * v1.z;                     
00322 
00323                                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride2);
00324                                                                 ((CVector *) (ptPos + stride2))->x = (*it).x  + *currentSize * v2.x;                    
00325                                                                 ((CVector *) (ptPos + stride2))->y = (*it).y  + *currentSize * v2.y;                    
00326                                                                 ((CVector *) (ptPos + stride2))->z = (*it).z  + *currentSize * v2.z;                    
00327 
00328 
00329                                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride3);
00330                                                                 ((CVector *) (ptPos + stride3))->x = (*it).x  - *currentSize * v1.x;                    
00331                                                                 ((CVector *) (ptPos + stride3))->y = (*it).y  - *currentSize * v1.y;                    
00332                                                                 ((CVector *) (ptPos + stride3))->z = (*it).z  - *currentSize * v1.z;                                                    
00333                                                         }
00334                                                 }
00335                                                 else
00336                                                 {
00337 
00338                                                         CHECK_VERTEX_BUFFER(vb, ptPos);
00339                                                         ((CVector *) ptPos)->x = (*it).x  - *currentSize * v2.x;                        
00340                                                         ((CVector *) ptPos)->y = (*it).y  - *currentSize * v2.y;                        
00341                                                         ((CVector *) ptPos)->z = (*it).z  - *currentSize * v2.z;                        
00342                                                         
00343                                                         CHECK_VERTEX_BUFFER(vb, ptPos + stride);
00344                                                         ((CVector *) (ptPos + stride))->x = (*it).x  + *currentSize * v1.x;                     
00345                                                         ((CVector *) (ptPos + stride))->y = (*it).y  + *currentSize * v1.y;                     
00346                                                         ((CVector *) (ptPos + stride))->z = (*it).z  + *currentSize * v1.z;                     
00347 
00348                                                         CHECK_VERTEX_BUFFER(vb, ptPos + stride2);
00349                                                         ((CVector *) (ptPos + stride2))->x = (*it).x  + *currentSize * v2.x;                    
00350                                                         ((CVector *) (ptPos + stride2))->y = (*it).y  + *currentSize * v2.y;                    
00351                                                         ((CVector *) (ptPos + stride2))->z = (*it).z  + *currentSize * v2.z;                    
00352 
00353 
00354                                                         CHECK_VERTEX_BUFFER(vb, ptPos + stride3);
00355                                                         ((CVector *) (ptPos + stride3))->x = (*it).x  - *currentSize * v1.x;                    
00356                                                         ((CVector *) (ptPos + stride3))->y = (*it).y  - *currentSize * v1.y;                    
00357                                                         ((CVector *) (ptPos + stride3))->z = (*it).z  - *currentSize * v1.z;                                                                                                    
00358                                                 }
00359                                         
00360                                                 ptPos += stride4;
00361                                                 ++it;
00362                                                 ++speedIt;
00363                                                 currentSize += currentSizeStep;                                 
00364                                         }
00365 
00366                                 }                       
00367                                 driver->renderQuads(la._Mat, 0, toProcess);                     
00368                                 leftToDo -= toProcess;                          
00369                         }
00370                         while (leftToDo);
00371                 }
00372                 else
00373                 {               
00374                         float pAngles[CPSQuad::quadBufSize]; // the angles to use
00375                         float *currentAngle;            
00376                         do
00377                         {                       
00378                                 // restart at the beginning of the vertex buffer
00379                                 ptPos = (uint8 *) vb.getVertexCoordPointer();
00380                                 toProcess = leftToDo <= CPSQuad::quadBufSize ? leftToDo : CPSQuad::quadBufSize;
00381                                 if (la._SizeScheme)
00382                                 {
00383                                         currentSize = (float *) la._SizeScheme->make(la._Owner, size - leftToDo, pSizes, sizeof(float), toProcess, true, srcStep);
00384                                 }
00385                                 else
00386                                 {
00387                                         currentSize = &la._ParticleSize;
00388                                 }
00389                                 currentAngle = (float *) la._Angle2DScheme->make(la._Owner, size - leftToDo, pAngles, sizeof(float), toProcess, true, srcStep);
00390                                 la.updateVbColNUVForRender(vb, size - leftToDo, toProcess, srcStep);                                    
00391                                 T endIt = it + toProcess;
00392                                 CVector v1, v2;
00393                                 OptFastFloorBegin();
00394                                 if (!la._IndependantSizes)
00395                                 {                               
00396                                         while (it != endIt)
00397                                         {
00398                                                 const uint32 tabIndex = ((OptFastFloor(*currentAngle)) & 0xff) << 2;                    
00399                                                 // lets avoid some ctor calls
00400                                                 v1.x = *currentSize * (rotTable[tabIndex] * I.x + rotTable[tabIndex + 1] * K.x);
00401                                                 v1.y = *currentSize * (rotTable[tabIndex] * I.y + rotTable[tabIndex + 1] * K.y);
00402                                                 v1.z = *currentSize * (rotTable[tabIndex] * I.z + rotTable[tabIndex + 1] * K.z);
00403 
00404                                                 v2.x = *currentSize * (rotTable[tabIndex + 2] * I.x + rotTable[tabIndex + 3] * K.x);
00405                                                 v2.y = *currentSize * (rotTable[tabIndex + 2] * I.y + rotTable[tabIndex + 3] * K.y);
00406                                                 v2.z = *currentSize * (rotTable[tabIndex + 2] * I.z + rotTable[tabIndex + 3] * K.z);
00407                                                 
00408                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00409                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride);
00410                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride2);
00411                                                 CHECK_VERTEX_BUFFER(vb, ptPos + stride3);                               
00412                                         
00413                                                 ((CVector *) ptPos)->x  = (*it).x  + v1.x;              
00414                                                 ((CVector *) ptPos)->y  = (*it).y  + v1.y;
00415                                                 ((CVector *) ptPos)->z = (*it).z  + v1.z;                       
00416                                                 ptPos += stride;
00417 
00418                                                 ((CVector *) ptPos)->x  = (*it).x  + v2.x;              
00419                                                 ((CVector *) ptPos)->y  = (*it).y  + v2.y;
00420                                                 ((CVector *) ptPos)->z = (*it).z  + v2.z;                       
00421                                                 ptPos += stride;
00422 
00423                                                 ((CVector *) ptPos)->x  = (*it).x  - v1.x;              
00424                                                 ((CVector *) ptPos)->y  = (*it).y  - v1.y;
00425                                                 ((CVector *) ptPos)->z = (*it).z  - v1.z;                       
00426                                                 ptPos += stride;
00427 
00428                                                 ((CVector *) ptPos)->x  = (*it).x  - v2.x;              
00429                                                 ((CVector *) ptPos)->y  = (*it).y  - v2.y;
00430                                                 ((CVector *) ptPos)->z = (*it).z  - v2.z;                                       
00431                                                 ptPos += stride;
00432                                                 
00433                                                 ++it;
00434                                                 currentSize += currentSizeStep;
00435                                                 ++currentAngle;                                 
00436                                         }
00437                                 }
00438                                 else // independant size, and non-constant rotation
00439                                 {
00440                                         
00441                                         float *currentSize2;
00442                                         float secondSize;
00443                                         uint32 currentSizeStep2;
00444                                         if (la._SecondSize.getSizeScheme())
00445                                         {
00446                                                 currentSize2 = (float *) la._SecondSize.getSizeScheme()->make(la._Owner, size- leftToDo, pSecondSizes, sizeof(float), toProcess, true, srcStep);
00447                                                 currentSizeStep2 = 1;
00448                                         }
00449                                         else
00450                                         {       
00451                                                 secondSize = la._SecondSize.getSize();
00452                                                 currentSize2 = &secondSize;
00453                                                 currentSizeStep2 = 0;
00454                                         }
00455 
00456                                         float cosAngle, sinAngle;
00457                                         while (it != endIt)
00458                                         {
00459                                                 cosAngle = CPSUtil::getCos((sint32) *currentAngle);
00460                                                 sinAngle = CPSUtil::getSin((sint32) *currentAngle);
00461                                                 v1 = cosAngle * I  + sinAngle * K;
00462                                                 v2 = - sinAngle * I + cosAngle * K;
00463 
00464                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00465                                                 ((CVector *) ptPos)->x = (*it).x  - *currentSize * v1.x + *currentSize2 * v2.x;                         
00466                                                 ((CVector *) ptPos)->y = (*it).y  - *currentSize * v1.y + *currentSize2 * v2.y;                         
00467                                                 ((CVector *) ptPos)->z = (*it).z  - *currentSize * v1.z + *currentSize2 * v2.z;
00468                                                 ptPos += stride;
00469 
00470                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00471                                                 ((CVector *) ptPos)->x = (*it).x  + *currentSize * v1.x + *currentSize2 * v2.x;                         
00472                                                 ((CVector *) ptPos)->y = (*it).y  + *currentSize * v1.y + *currentSize2 * v2.y;                         
00473                                                 ((CVector *) ptPos)->z = (*it).z  + *currentSize * v1.z + *currentSize2 * v2.z;
00474                                                 ptPos += stride;
00475 
00476                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00477                                                 ((CVector *) ptPos)->x = (*it).x  + *currentSize * v1.x - *currentSize2 * v2.x;                         
00478                                                 ((CVector *) ptPos)->y = (*it).y  + *currentSize * v1.y - *currentSize2 * v2.y;                         
00479                                                 ((CVector *) ptPos)->z = (*it).z  + *currentSize * v1.z - *currentSize2 * v2.z;
00480                                                 ptPos += stride;
00481 
00482                                                 CHECK_VERTEX_BUFFER(vb, ptPos);
00483                                                 ((CVector *) ptPos)->x = (*it).x  - *currentSize * v1.x - *currentSize2 * v2.x;                         
00484                                                 ((CVector *) ptPos)->y = (*it).y  - *currentSize * v1.y - *currentSize2 * v2.y;                         
00485                                                 ((CVector *) ptPos)->z = (*it).z  - *currentSize * v1.z - *currentSize2 * v2.z;
00486                                                 ptPos += stride;
00487                                                 ++it;
00488                                                 ++currentAngle;
00489                                                 currentSize  += currentSizeStep;
00490                                                 currentSize2 += currentSizeStep2;                       
00491                                         }
00492                                 }                               
00493                                 OptFastFloorEnd();                                                      
00494                                 driver->renderQuads(la._Mat, 0, toProcess);                     
00495                                 leftToDo -= toProcess;
00496                         }
00497                         while (leftToDo);
00498                 }
00499                 PARTICLES_CHECK_MEM;
00500         }
00501 };
00502 
00504 void CPSFaceLookAt::draw(bool opaque)
00505 {
00506         PARTICLES_CHECK_MEM;    
00507         if (!_Owner->getSize()) return; 
00508 
00509         uint32 step;
00510         uint   numToProcess;
00511         computeSrcStep(step, numToProcess);     
00512         if (!numToProcess) return;
00513         
00514 
00515         if (step == (1 << 16))
00516         {
00517                 CPSFaceLookAtHelper::drawLookAt(_Owner->getPos().begin(),
00518                                    _Owner->getSpeed().begin(),
00519                                    *this,
00520                                     numToProcess,
00521                                         step
00522                            );
00523         }
00524         else
00525         {               
00526                 CPSFaceLookAtHelper::drawLookAt(TIteratorVectStep1616(_Owner->getPos().begin(), 0, step),
00527                                    TIteratorVectStep1616(_Owner->getSpeed().begin(), 0, step),
00528                                    *this,
00529                                    numToProcess,
00530                                    step                         
00531                                   );
00532         }
00533         
00534         PARTICLES_CHECK_MEM;
00535 }
00536 
00538 CPSFaceLookAt::CPSFaceLookAt(CSmartPtr<ITexture> tex) : CPSQuad(tex), _MotionBlurCoeff(0.f)
00539                                                                                                                 , _Threshold(0.5f), _IndependantSizes(false)
00540 {       
00541         _SecondSize.Owner = this;
00542         _Name = std::string("LookAt");
00543 }
00544 
00546 void CPSFaceLookAt::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
00547 {
00548         CPSQuad::newElement(emitterLocated, emitterIndex);
00549         newAngle2DElement(emitterLocated, emitterIndex);
00550 }
00551 
00553 void CPSFaceLookAt::deleteElement(uint32 index)
00554 {
00555         CPSQuad::deleteElement(index);
00556         deleteAngle2DElement(index);
00557 }
00558 
00560 void CPSFaceLookAt::resize(uint32 capacity)
00561 {
00562         nlassert(capacity < (1 << 16));
00563         CPSQuad::resize(capacity);
00564         resizeAngle2D(capacity);
00565 }
00566 
00567 
00569 void CPSFaceLookAt::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00570 {
00571         sint ver = f.serialVersion(2);
00572         CPSQuad::serial(f);
00573         CPSRotated2DParticle::serialAngle2DScheme(f);   
00574         f.serial(_MotionBlurCoeff);
00575         if (_MotionBlurCoeff != 0)
00576         {
00577                 f.serial(_Threshold);
00578         }
00579         if (ver > 1)
00580         {
00581                 f.serial(_IndependantSizes);
00582                 if (_IndependantSizes)
00583                 {
00584                         _SecondSize.serialSizeScheme(f);
00585                 }
00586         }
00587         if (f.isReading())
00588         {
00589                 init();         
00590         }
00591 }
00592 
00593 } // NL3D