Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include "RAS_MaterialBucket.h" 00034 00035 #if defined(WIN32) && !defined(FREE_WINDOWS) 00036 #pragma warning (disable:4786) 00037 #endif 00038 00039 #ifdef WIN32 00040 #include <windows.h> 00041 #endif // WIN32 00042 00043 #include "RAS_Polygon.h" 00044 #include "RAS_TexVert.h" 00045 #include "RAS_IRasterizer.h" 00046 #include "RAS_IRenderTools.h" 00047 #include "RAS_MeshObject.h" 00048 #include "RAS_Deformer.h" // __NLA 00049 00050 /* mesh slot */ 00051 00052 RAS_MeshSlot::RAS_MeshSlot() : SG_QList() 00053 { 00054 m_clientObj = NULL; 00055 m_pDeformer = NULL; 00056 m_OpenGLMatrix = NULL; 00057 m_mesh = NULL; 00058 m_bucket = NULL; 00059 m_bVisible = false; 00060 m_bCulled = true; 00061 m_bObjectColor = false; 00062 m_RGBAcolor = MT_Vector4(0.0, 0.0, 0.0, 0.0); 00063 m_DisplayList = NULL; 00064 m_bDisplayList = true; 00065 m_joinSlot = NULL; 00066 m_pDerivedMesh = NULL; 00067 } 00068 00069 RAS_MeshSlot::~RAS_MeshSlot() 00070 { 00071 RAS_DisplayArrayList::iterator it; 00072 00073 #ifdef USE_SPLIT 00074 Split(true); 00075 00076 while(m_joinedSlots.size()) 00077 m_joinedSlots.front()->Split(true); 00078 #endif 00079 00080 for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { 00081 (*it)->m_users--; 00082 if((*it)->m_users == 0) 00083 delete *it; 00084 } 00085 00086 if (m_DisplayList) { 00087 m_DisplayList->Release(); 00088 m_DisplayList = NULL; 00089 } 00090 } 00091 00092 RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) : SG_QList() 00093 { 00094 RAS_DisplayArrayList::iterator it; 00095 00096 m_clientObj = NULL; 00097 m_pDeformer = NULL; 00098 m_pDerivedMesh = NULL; 00099 m_OpenGLMatrix = NULL; 00100 m_mesh = slot.m_mesh; 00101 m_bucket = slot.m_bucket; 00102 m_bVisible = slot.m_bVisible; 00103 m_bCulled = slot.m_bCulled; 00104 m_bObjectColor = slot.m_bObjectColor; 00105 m_RGBAcolor = slot.m_RGBAcolor; 00106 m_DisplayList = NULL; 00107 m_bDisplayList = slot.m_bDisplayList; 00108 m_joinSlot = NULL; 00109 m_currentArray = slot.m_currentArray; 00110 m_displayArrays = slot.m_displayArrays; 00111 m_joinedSlots = slot.m_joinedSlots; 00112 00113 m_startarray = slot.m_startarray; 00114 m_startvertex = slot.m_startvertex; 00115 m_startindex = slot.m_startindex; 00116 m_endarray = slot.m_endarray; 00117 m_endvertex = slot.m_endvertex; 00118 m_endindex = slot.m_endindex; 00119 00120 for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { 00121 // don't copy display arrays for now because it breaks python 00122 // access to vertices, but we'll need a solution if we want to 00123 // join display arrays for reducing draw calls. 00124 //*it = new RAS_DisplayArray(**it); 00125 //(*it)->m_users = 1; 00126 00127 (*it)->m_users++; 00128 } 00129 } 00130 00131 void RAS_MeshSlot::init(RAS_MaterialBucket *bucket, int numverts) 00132 { 00133 m_bucket = bucket; 00134 00135 SetDisplayArray(numverts); 00136 00137 m_startarray = 0; 00138 m_startvertex = 0; 00139 m_startindex = 0; 00140 m_endarray = 0; 00141 m_endvertex = 0; 00142 m_endindex = 0; 00143 } 00144 00145 void RAS_MeshSlot::begin(RAS_MeshSlot::iterator& it) 00146 { 00147 int startvertex, endvertex; 00148 int startindex, endindex; 00149 00150 it.array = (m_displayArrays.size() > 0)? m_displayArrays[m_startarray]: NULL; 00151 00152 if(it.array == NULL || it.array->m_index.size() == 0 || it.array->m_vertex.size() == 0) { 00153 it.array = NULL; 00154 it.vertex = NULL; 00155 it.index = NULL; 00156 it.startvertex = 0; 00157 it.endvertex = 0; 00158 it.totindex = 0; 00159 } 00160 else { 00161 startvertex = m_startvertex; 00162 endvertex = (m_startarray == m_endarray)? m_endvertex: it.array->m_vertex.size(); 00163 startindex = m_startindex; 00164 endindex = (m_startarray == m_endarray)? m_endindex: it.array->m_index.size(); 00165 00166 it.vertex = &it.array->m_vertex[0]; 00167 it.index = &it.array->m_index[startindex]; 00168 it.startvertex = startvertex; 00169 it.endvertex = endvertex; 00170 it.totindex = endindex-startindex; 00171 it.arraynum = m_startarray; 00172 } 00173 } 00174 00175 void RAS_MeshSlot::next(RAS_MeshSlot::iterator& it) 00176 { 00177 int startvertex, endvertex; 00178 int startindex, endindex; 00179 00180 if(it.arraynum == (size_t)m_endarray) { 00181 it.array = NULL; 00182 it.vertex = NULL; 00183 it.index = NULL; 00184 it.startvertex = 0; 00185 it.endvertex = 0; 00186 it.totindex = 0; 00187 } 00188 else { 00189 it.arraynum++; 00190 it.array = m_displayArrays[it.arraynum]; 00191 00192 startindex = 0; 00193 endindex = (it.arraynum == (size_t)m_endarray)? m_endindex: it.array->m_index.size(); 00194 startvertex = 0; 00195 endvertex = (it.arraynum == (size_t)m_endarray)? m_endvertex: it.array->m_vertex.size(); 00196 00197 it.vertex = &it.array->m_vertex[0]; 00198 it.index = &it.array->m_index[startindex]; 00199 it.startvertex = startvertex; 00200 it.endvertex = endvertex; 00201 it.totindex = endindex-startindex; 00202 } 00203 } 00204 00205 bool RAS_MeshSlot::end(RAS_MeshSlot::iterator& it) 00206 { 00207 return (it.array == NULL); 00208 } 00209 00210 RAS_DisplayArray *RAS_MeshSlot::CurrentDisplayArray() 00211 { 00212 return m_currentArray; 00213 } 00214 00215 void RAS_MeshSlot::SetDisplayArray(int numverts) 00216 { 00217 RAS_DisplayArrayList::iterator it; 00218 RAS_DisplayArray *darray = NULL; 00219 00220 for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { 00221 darray = *it; 00222 00223 if(darray->m_type == numverts) { 00224 if(darray->m_index.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_INDEX) 00225 darray = NULL; 00226 else if(darray->m_vertex.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_VERTEX) 00227 darray = NULL; 00228 else 00229 break; 00230 } 00231 else 00232 darray = NULL; 00233 } 00234 00235 if(!darray) { 00236 darray = new RAS_DisplayArray(); 00237 darray->m_users = 1; 00238 00239 if(numverts == 2) darray->m_type = RAS_DisplayArray::LINE; 00240 else if(numverts == 3) darray->m_type = RAS_DisplayArray::TRIANGLE; 00241 else darray->m_type = RAS_DisplayArray::QUAD; 00242 00243 m_displayArrays.push_back(darray); 00244 00245 if(numverts == 2) 00246 darray->m_type = RAS_DisplayArray::LINE; 00247 else if(numverts == 3) 00248 darray->m_type = RAS_DisplayArray::TRIANGLE; 00249 else if(numverts == 4) 00250 darray->m_type = RAS_DisplayArray::QUAD; 00251 00252 m_endarray = m_displayArrays.size()-1; 00253 m_endvertex = 0; 00254 m_endindex = 0; 00255 } 00256 00257 m_currentArray = darray; 00258 } 00259 00260 void RAS_MeshSlot::AddPolygon(int numverts) 00261 { 00262 SetDisplayArray(numverts); 00263 } 00264 00265 int RAS_MeshSlot::AddVertex(const RAS_TexVert& tv) 00266 { 00267 RAS_DisplayArray *darray; 00268 int offset; 00269 00270 darray = m_currentArray; 00271 darray->m_vertex.push_back(tv); 00272 offset = darray->m_vertex.size()-1; 00273 00274 if(darray == m_displayArrays[m_endarray]) 00275 m_endvertex++; 00276 00277 return offset; 00278 } 00279 00280 void RAS_MeshSlot::AddPolygonVertex(int offset) 00281 { 00282 RAS_DisplayArray *darray; 00283 00284 darray = m_currentArray; 00285 darray->m_index.push_back(offset); 00286 00287 if(darray == m_displayArrays[m_endarray]) 00288 m_endindex++; 00289 } 00290 00291 void RAS_MeshSlot::SetDeformer(RAS_Deformer* deformer) 00292 { 00293 if (deformer && m_pDeformer != deformer) { 00294 RAS_DisplayArrayList::iterator it; 00295 if (deformer->ShareVertexArray()) { 00296 // this deformer uses the base vertex array, first release the current ones 00297 for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { 00298 (*it)->m_users--; 00299 if((*it)->m_users == 0) 00300 delete *it; 00301 } 00302 m_displayArrays.clear(); 00303 // then hook to the base ones 00304 RAS_MeshMaterial *mmat = m_mesh->GetMeshMaterial(m_bucket->GetPolyMaterial()); 00305 if (mmat && mmat->m_baseslot) { 00306 m_displayArrays = mmat->m_baseslot->m_displayArrays; 00307 for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { 00308 (*it)->m_users++; 00309 } 00310 } 00311 } 00312 else { 00313 // no sharing 00314 // we create local copy of RAS_DisplayArray when we have a deformer: 00315 // this way we can avoid conflict between the vertex cache of duplicates 00316 for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { 00317 if (deformer->UseVertexArray()) { 00318 // the deformer makes use of vertex array, make sure we have our local copy 00319 if ((*it)->m_users > 1) { 00320 // only need to copy if there are other users 00321 // note that this is the usual case as vertex arrays are held by the material base slot 00322 RAS_DisplayArray *newarray = new RAS_DisplayArray(*(*it)); 00323 newarray->m_users = 1; 00324 (*it)->m_users--; 00325 *it = newarray; 00326 } 00327 } else { 00328 // the deformer is not using vertex array (Modifier), release them 00329 (*it)->m_users--; 00330 if((*it)->m_users == 0) 00331 delete *it; 00332 } 00333 } 00334 if (!deformer->UseVertexArray()) { 00335 m_displayArrays.clear(); 00336 m_startarray = 0; 00337 m_startvertex = 0; 00338 m_startindex = 0; 00339 m_endarray = 0; 00340 m_endvertex = 0; 00341 m_endindex = 0; 00342 } 00343 } 00344 } 00345 m_pDeformer = deformer; 00346 } 00347 00348 bool RAS_MeshSlot::Equals(RAS_MeshSlot *target) 00349 { 00350 if(!m_OpenGLMatrix || !target->m_OpenGLMatrix) 00351 return false; 00352 if(m_pDeformer || target->m_pDeformer) 00353 return false; 00354 if(m_bVisible != target->m_bVisible) 00355 return false; 00356 if(m_bObjectColor != target->m_bObjectColor) 00357 return false; 00358 if(m_bObjectColor && !(m_RGBAcolor == target->m_RGBAcolor)) 00359 return false; 00360 00361 return true; 00362 } 00363 00364 bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance) 00365 { 00366 RAS_DisplayArrayList::iterator it; 00367 iterator mit; 00368 size_t i; 00369 00370 // verify if we can join 00371 if(m_joinSlot || m_joinedSlots.size() || target->m_joinSlot) 00372 return false; 00373 00374 if(!Equals(target)) 00375 return false; 00376 00377 MT_Vector3 co(&m_OpenGLMatrix[12]); 00378 MT_Vector3 targetco(&target->m_OpenGLMatrix[12]); 00379 00380 if((co - targetco).length() > distance) 00381 return false; 00382 00383 MT_Matrix4x4 mat(m_OpenGLMatrix); 00384 MT_Matrix4x4 targetmat(target->m_OpenGLMatrix); 00385 targetmat.invert(); 00386 00387 MT_Matrix4x4 transform = targetmat*mat; 00388 00389 // m_mesh, clientobj 00390 m_joinSlot = target; 00391 m_joinInvTransform = transform; 00392 m_joinInvTransform.invert(); 00393 target->m_joinedSlots.push_back(this); 00394 00395 MT_Matrix4x4 ntransform = m_joinInvTransform.transposed(); 00396 ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; 00397 00398 for(begin(mit); !end(mit); next(mit)) 00399 for(i=mit.startvertex; i<mit.endvertex; i++) 00400 mit.vertex[i].Transform(transform, ntransform); 00401 00402 /* We know we'll need a list at least this big, reserve in advance */ 00403 target->m_displayArrays.reserve(target->m_displayArrays.size() + m_displayArrays.size()); 00404 00405 for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { 00406 target->m_displayArrays.push_back(*it); 00407 target->m_endarray++; 00408 target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); 00409 target->m_endindex = target->m_displayArrays.back()->m_index.size(); 00410 } 00411 00412 if (m_DisplayList) { 00413 m_DisplayList->Release(); 00414 m_DisplayList = NULL; 00415 } 00416 if (target->m_DisplayList) { 00417 target->m_DisplayList->Release(); 00418 target->m_DisplayList = NULL; 00419 } 00420 00421 return true; 00422 #if 0 00423 return false; 00424 #endif 00425 } 00426 00427 bool RAS_MeshSlot::Split(bool force) 00428 { 00429 list<RAS_MeshSlot*>::iterator jit; 00430 RAS_MeshSlot *target = m_joinSlot; 00431 RAS_DisplayArrayList::iterator it, jt; 00432 iterator mit; 00433 size_t i, found0 = 0, found1 = 0; 00434 00435 if(target && (force || !Equals(target))) { 00436 m_joinSlot = NULL; 00437 00438 for(jit=target->m_joinedSlots.begin(); jit!=target->m_joinedSlots.end(); jit++) { 00439 if(*jit == this) { 00440 target->m_joinedSlots.erase(jit); 00441 found0 = 1; 00442 break; 00443 } 00444 } 00445 00446 if(!found0) 00447 abort(); 00448 00449 for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { 00450 found1 = 0; 00451 for(jt=target->m_displayArrays.begin(); jt!=target->m_displayArrays.end(); jt++) { 00452 if(*jt == *it) { 00453 target->m_displayArrays.erase(jt); 00454 target->m_endarray--; 00455 found1 = 1; 00456 break; 00457 } 00458 } 00459 00460 if(!found1) 00461 abort(); 00462 } 00463 00464 if(target->m_displayArrays.size()) { 00465 target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); 00466 target->m_endindex = target->m_displayArrays.back()->m_index.size(); 00467 } 00468 else { 00469 target->m_endvertex = 0; 00470 target->m_endindex = 0; 00471 } 00472 00473 MT_Matrix4x4 ntransform = m_joinInvTransform.inverse().transposed(); 00474 ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; 00475 00476 for(begin(mit); !end(mit); next(mit)) 00477 for(i=mit.startvertex; i<mit.endvertex; i++) 00478 mit.vertex[i].Transform(m_joinInvTransform, ntransform); 00479 00480 if (target->m_DisplayList) { 00481 target->m_DisplayList->Release(); 00482 target->m_DisplayList = NULL; 00483 } 00484 00485 return true; 00486 } 00487 00488 return false; 00489 } 00490 00491 00492 #ifdef USE_SPLIT 00493 bool RAS_MeshSlot::IsCulled() 00494 { 00495 if(m_joinSlot) 00496 return true; 00497 if(!m_bCulled) 00498 return false; 00499 list<RAS_MeshSlot*>::iterator it; 00500 for(it=m_joinedSlots.begin(); it!=m_joinedSlots.end(); it++) 00501 if(!(*it)->m_bCulled) 00502 return false; 00503 return true; 00504 } 00505 #endif 00506 00507 /* material bucket sorting */ 00508 00509 struct RAS_MaterialBucket::less 00510 { 00511 bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const 00512 { 00513 return *x->GetPolyMaterial() < *y->GetPolyMaterial(); 00514 } 00515 }; 00516 00517 /* material bucket */ 00518 00519 RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat) 00520 { 00521 m_material = mat; 00522 } 00523 00524 RAS_MaterialBucket::~RAS_MaterialBucket() 00525 { 00526 } 00527 00528 RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const 00529 { 00530 return m_material; 00531 } 00532 00533 bool RAS_MaterialBucket::IsAlpha() const 00534 { 00535 return (m_material->IsAlpha()); 00536 } 00537 00538 bool RAS_MaterialBucket::IsZSort() const 00539 { 00540 return (m_material->IsZSort()); 00541 } 00542 00543 RAS_MeshSlot* RAS_MaterialBucket::AddMesh(int numverts) 00544 { 00545 RAS_MeshSlot *ms; 00546 00547 m_meshSlots.push_back(RAS_MeshSlot()); 00548 00549 ms = &m_meshSlots.back(); 00550 ms->init(this, numverts); 00551 00552 return ms; 00553 } 00554 00555 RAS_MeshSlot* RAS_MaterialBucket::CopyMesh(RAS_MeshSlot *ms) 00556 { 00557 m_meshSlots.push_back(RAS_MeshSlot(*ms)); 00558 00559 return &m_meshSlots.back(); 00560 } 00561 00562 void RAS_MaterialBucket::RemoveMesh(RAS_MeshSlot* ms) 00563 { 00564 list<RAS_MeshSlot>::iterator it; 00565 00566 for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) { 00567 if(&*it == ms) { 00568 m_meshSlots.erase(it); 00569 return; 00570 } 00571 } 00572 } 00573 00574 list<RAS_MeshSlot>::iterator RAS_MaterialBucket::msBegin() 00575 { 00576 return m_meshSlots.begin(); 00577 } 00578 00579 list<RAS_MeshSlot>::iterator RAS_MaterialBucket::msEnd() 00580 { 00581 return m_meshSlots.end(); 00582 } 00583 00584 bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, 00585 RAS_IRenderTools *rendertools) 00586 { 00587 bool uselights; 00588 00589 if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && !m_material->CastsShadows()) 00590 return false; 00591 00592 if(!rasty->SetMaterial(*m_material)) 00593 return false; 00594 00595 uselights= m_material->UsesLighting(rasty); 00596 rendertools->ProcessLighting(rasty, uselights, cameratrans); 00597 00598 return true; 00599 } 00600 00601 void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, 00602 RAS_IRenderTools* rendertools, RAS_MeshSlot &ms) 00603 { 00604 m_material->ActivateMeshSlot(ms, rasty); 00605 00606 if (ms.m_pDeformer) 00607 { 00608 ms.m_pDeformer->Apply(m_material); 00609 // KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_) 00610 } 00611 00612 if(IsZSort() && rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) 00613 ms.m_mesh->SortPolygons(ms, cameratrans*MT_Transform(ms.m_OpenGLMatrix)); 00614 00615 rendertools->PushMatrix(); 00616 if (!ms.m_pDeformer || !ms.m_pDeformer->SkipVertexTransform()) 00617 { 00618 rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode()); 00619 } 00620 00621 if(rasty->QueryLists()) 00622 if(ms.m_DisplayList) 00623 ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified()); 00624 00625 // verify if we can use display list, not for deformed object, and 00626 // also don't create a new display list when drawing shadow buffers, 00627 // then it won't have texture coordinates for actual drawing. also 00628 // for zsort we can't make a display list, since the polygon order 00629 // changes all the time. 00630 if(ms.m_pDeformer && ms.m_pDeformer->IsDynamic()) 00631 ms.m_bDisplayList = false; 00632 else if(!ms.m_DisplayList && rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW) 00633 ms.m_bDisplayList = false; 00634 else if (IsZSort()) 00635 ms.m_bDisplayList = false; 00636 else if(m_material->UsesObjectColor() && ms.m_bObjectColor) 00637 ms.m_bDisplayList = false; 00638 else 00639 ms.m_bDisplayList = true; 00640 00641 // for text drawing using faces 00642 if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) 00643 rasty->IndexPrimitives_3DText(ms, m_material, rendertools); 00644 // for multitexturing 00645 else if((m_material->GetFlag() & (RAS_MULTITEX|RAS_BLENDERGLSL))) 00646 rasty->IndexPrimitivesMulti(ms); 00647 // use normal IndexPrimitives 00648 else 00649 rasty->IndexPrimitives(ms); 00650 00651 if(rasty->QueryLists()) 00652 if(ms.m_DisplayList) 00653 ms.m_mesh->SetMeshModified(false); 00654 00655 rendertools->PopMatrix(); 00656 } 00657 00658 void RAS_MaterialBucket::Optimize(MT_Scalar distance) 00659 { 00660 /* TODO: still have to check before this works correct: 00661 * - lightlayer, frontface, text, billboard 00662 * - make it work with physics */ 00663 00664 #if 0 00665 list<RAS_MeshSlot>::iterator it; 00666 list<RAS_MeshSlot>::iterator jt; 00667 00668 // greed joining on all following buckets 00669 for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) 00670 for(jt=it, jt++; jt!=m_meshSlots.end(); jt++) 00671 jt->Join(&*it, distance); 00672 #endif 00673 } 00674