|
Blender
V2.59
|
00001 /* 00002 * $Id: RAS_MeshObject.cpp 35174 2011-02-25 13:38:24Z jesterking $ 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00033 #include "MEM_guardedalloc.h" 00034 00035 #include "DNA_object_types.h" 00036 #include "DNA_key_types.h" 00037 #include "DNA_mesh_types.h" 00038 #include "DNA_meshdata_types.h" 00039 00040 #include "RAS_MeshObject.h" 00041 #include "RAS_IRasterizer.h" 00042 #include "MT_MinMax.h" 00043 #include "MT_Point3.h" 00044 00045 #include <algorithm> 00046 00047 /* polygon sorting */ 00048 00049 struct RAS_MeshObject::polygonSlot 00050 { 00051 float m_z; 00052 int m_index[4]; 00053 00054 polygonSlot() {} 00055 00056 /* pnorm is the normal from the plane equation that the distance from is 00057 * used to sort again. */ 00058 void get(const RAS_TexVert *vertexarray, const unsigned short *indexarray, 00059 int offset, int nvert, const MT_Vector3& pnorm) 00060 { 00061 MT_Vector3 center(0, 0, 0); 00062 int i; 00063 00064 for(i=0; i<nvert; i++) { 00065 m_index[i] = indexarray[offset+i]; 00066 center += vertexarray[m_index[i]].getXYZ(); 00067 } 00068 00069 /* note we don't divide center by the number of vertices, since all 00070 * polygons have the same number of vertices, and that we leave out 00071 * the 4-th component of the plane equation since it is constant. */ 00072 m_z = MT_dot(pnorm, center); 00073 } 00074 00075 void set(unsigned short *indexarray, int offset, int nvert) 00076 { 00077 int i; 00078 00079 for(i=0; i<nvert; i++) 00080 indexarray[offset+i] = m_index[i]; 00081 } 00082 }; 00083 00084 struct RAS_MeshObject::backtofront 00085 { 00086 bool operator()(const polygonSlot &a, const polygonSlot &b) const 00087 { 00088 return a.m_z < b.m_z; 00089 } 00090 }; 00091 00092 struct RAS_MeshObject::fronttoback 00093 { 00094 bool operator()(const polygonSlot &a, const polygonSlot &b) const 00095 { 00096 return a.m_z > b.m_z; 00097 } 00098 }; 00099 00100 /* mesh object */ 00101 00102 STR_String RAS_MeshObject::s_emptyname = ""; 00103 00104 RAS_MeshObject::RAS_MeshObject(Mesh* mesh) 00105 : m_bModified(true), 00106 m_bMeshModified(true), 00107 m_mesh(mesh) 00108 { 00109 if (m_mesh && m_mesh->key) 00110 { 00111 KeyBlock *kb; 00112 int count=0; 00113 // initialize weight cache for shape objects 00114 // count how many keys in this mesh 00115 for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) 00116 count++; 00117 m_cacheWeightIndex.resize(count,-1); 00118 } 00119 } 00120 00121 RAS_MeshObject::~RAS_MeshObject() 00122 { 00123 vector<RAS_Polygon*>::iterator it; 00124 00125 if (m_mesh && m_mesh->key) 00126 { 00127 KeyBlock *kb; 00128 // remove the weight cache to avoid memory leak 00129 for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) { 00130 if(kb->weights) 00131 MEM_freeN(kb->weights); 00132 kb->weights= NULL; 00133 } 00134 } 00135 00136 for(it=m_Polygons.begin(); it!=m_Polygons.end(); it++) 00137 delete (*it); 00138 00139 m_sharedvertex_map.clear(); 00140 m_Polygons.clear(); 00141 m_materials.clear(); 00142 } 00143 00144 bool RAS_MeshObject::MeshModified() 00145 { 00146 return m_bMeshModified; 00147 } 00148 00149 //unsigned int RAS_MeshObject::GetLightLayer() 00150 //{ 00151 // return m_lightlayer; 00152 //} 00153 00154 00155 00156 int RAS_MeshObject::NumMaterials() 00157 { 00158 return m_materials.size(); 00159 } 00160 00161 const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) 00162 { 00163 RAS_MeshMaterial* mmat = GetMeshMaterial(matid); 00164 00165 if(mmat) 00166 return mmat->m_bucket->GetPolyMaterial()->GetMaterialName(); 00167 00168 return s_emptyname; 00169 } 00170 00171 RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid) 00172 { 00173 if (m_materials.size() > 0 && (matid < m_materials.size())) 00174 { 00175 list<RAS_MeshMaterial>::iterator it = m_materials.begin(); 00176 while (matid--) ++it; 00177 return &*it; 00178 } 00179 00180 return NULL; 00181 } 00182 00183 00184 00185 int RAS_MeshObject::NumPolygons() 00186 { 00187 return m_Polygons.size(); 00188 } 00189 00190 00191 00192 RAS_Polygon* RAS_MeshObject::GetPolygon(int num) const 00193 { 00194 return m_Polygons[num]; 00195 } 00196 00197 00198 00199 00200 list<RAS_MeshMaterial>::iterator GetFirstMaterial(); 00201 list<RAS_MeshMaterial>::iterator GetLastMaterial(); 00202 list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetFirstMaterial() 00203 { 00204 return m_materials.begin(); 00205 } 00206 00207 00208 00209 list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetLastMaterial() 00210 { 00211 return m_materials.end(); 00212 } 00213 00214 00215 00216 void RAS_MeshObject::SetName(const char *name) 00217 { 00218 m_name = name; 00219 } 00220 00221 00222 00223 STR_String& RAS_MeshObject::GetName() 00224 { 00225 return m_name; 00226 } 00227 00228 00229 00230 const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid) 00231 { 00232 RAS_MeshMaterial* mmat = GetMeshMaterial(matid); 00233 00234 if(mmat) 00235 return mmat->m_bucket->GetPolyMaterial()->GetTextureName(); 00236 00237 return s_emptyname; 00238 } 00239 00240 RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat) 00241 { 00242 list<RAS_MeshMaterial>::iterator mit; 00243 00244 /* find a mesh material */ 00245 for(mit = m_materials.begin(); mit != m_materials.end(); mit++) 00246 if(mit->m_bucket->GetPolyMaterial() == mat) 00247 return &*mit; 00248 00249 return NULL; 00250 } 00251 00252 int RAS_MeshObject::GetMaterialId(RAS_IPolyMaterial *mat) 00253 { 00254 list<RAS_MeshMaterial>::iterator mit; 00255 int imat; 00256 00257 /* find a mesh material */ 00258 for(imat=0, mit = m_materials.begin(); mit != m_materials.end(); mit++, imat++) 00259 if(mit->m_bucket->GetPolyMaterial() == mat) 00260 return imat; 00261 00262 return -1; 00263 } 00264 00265 RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts) 00266 { 00267 RAS_MeshMaterial *mmat; 00268 RAS_Polygon *poly; 00269 RAS_MeshSlot *slot; 00270 00271 /* find a mesh material */ 00272 mmat = GetMeshMaterial(bucket->GetPolyMaterial()); 00273 00274 /* none found, create a new one */ 00275 if(!mmat) { 00276 RAS_MeshMaterial meshmat; 00277 meshmat.m_bucket = bucket; 00278 meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts); 00279 meshmat.m_baseslot->m_mesh = this; 00280 m_materials.push_back(meshmat); 00281 mmat = &m_materials.back(); 00282 } 00283 00284 /* add it to the bucket, this also adds new display arrays */ 00285 slot = mmat->m_baseslot; 00286 slot->AddPolygon(numverts); 00287 00288 /* create a new polygon */ 00289 RAS_DisplayArray *darray = slot->CurrentDisplayArray(); 00290 poly = new RAS_Polygon(bucket, darray, numverts); 00291 m_Polygons.push_back(poly); 00292 00293 return poly; 00294 } 00295 00296 void RAS_MeshObject::DebugColor(unsigned int abgr) 00297 { 00298 /*int numpolys = NumPolygons(); 00299 00300 for (int i=0;i<numpolys;i++) { 00301 RAS_Polygon* poly = m_polygons[i]; 00302 for (int v=0;v<poly->VertexCount();v++) 00303 RAS_TexVert* vtx = poly->GetVertex(v)->setDebugRGBA(abgr); 00304 } 00305 */ 00306 00307 /* m_debugcolor = abgr; */ 00308 } 00309 00310 void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) 00311 { 00312 RAS_MeshMaterial *mmat = GetMeshMaterial(mat); 00313 RAS_MeshSlot *slot = mmat->m_baseslot; 00314 RAS_MeshSlot::iterator it; 00315 size_t i; 00316 00317 for(slot->begin(it); !slot->end(it); slot->next(it)) 00318 for(i=it.startvertex; i<it.endvertex; i++) 00319 it.vertex[i].SetRGBA(rgba); 00320 } 00321 00322 void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i, 00323 const MT_Point3& xyz, 00324 const MT_Point2& uv, 00325 const MT_Point2& uv2, 00326 const MT_Vector4& tangent, 00327 const unsigned int rgba, 00328 const MT_Vector3& normal, 00329 bool flat, 00330 int origindex) 00331 { 00332 RAS_TexVert texvert(xyz, uv, uv2, tangent, rgba, normal, flat, origindex); 00333 RAS_MeshMaterial *mmat; 00334 RAS_DisplayArray *darray; 00335 RAS_MeshSlot *slot; 00336 int offset; 00337 00338 mmat = GetMeshMaterial(poly->GetMaterial()->GetPolyMaterial()); 00339 slot = mmat->m_baseslot; 00340 darray = slot->CurrentDisplayArray(); 00341 00342 { /* Shared Vertex! */ 00343 /* find vertices shared between faces, with the restriction 00344 * that they exist in the same display array, and have the 00345 * same uv coordinate etc */ 00346 vector<SharedVertex>& sharedmap = m_sharedvertex_map[origindex]; 00347 vector<SharedVertex>::iterator it; 00348 00349 for(it = sharedmap.begin(); it != sharedmap.end(); it++) 00350 { 00351 if(it->m_darray != darray) 00352 continue; 00353 if(!it->m_darray->m_vertex[it->m_offset].closeTo(&texvert)) 00354 continue; 00355 00356 /* found one, add it and we're done */ 00357 if(poly->IsVisible()) 00358 slot->AddPolygonVertex(it->m_offset); 00359 poly->SetVertexOffset(i, it->m_offset); 00360 return; 00361 } 00362 } 00363 00364 /* no shared vertex found, add a new one */ 00365 offset = slot->AddVertex(texvert); 00366 if(poly->IsVisible()) 00367 slot->AddPolygonVertex(offset); 00368 poly->SetVertexOffset(i, offset); 00369 00370 { /* Shared Vertex! */ 00371 SharedVertex shared; 00372 shared.m_darray = darray; 00373 shared.m_offset = offset; 00374 m_sharedvertex_map[origindex].push_back(shared); 00375 } 00376 } 00377 00378 int RAS_MeshObject::NumVertices(RAS_IPolyMaterial* mat) 00379 { 00380 RAS_MeshMaterial *mmat; 00381 RAS_MeshSlot *slot; 00382 RAS_MeshSlot::iterator it; 00383 size_t len = 0; 00384 00385 mmat = GetMeshMaterial(mat); 00386 slot = mmat->m_baseslot; 00387 for(slot->begin(it); !slot->end(it); slot->next(it)) 00388 len += it.endvertex - it.startvertex; 00389 00390 return len; 00391 } 00392 00393 00394 RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, 00395 unsigned int index) 00396 { 00397 RAS_MeshMaterial *mmat; 00398 RAS_MeshSlot *slot; 00399 RAS_MeshSlot::iterator it; 00400 size_t len; 00401 00402 mmat = GetMeshMaterial(matid); 00403 00404 if(!mmat) 00405 return NULL; 00406 00407 slot = mmat->m_baseslot; 00408 len = 0; 00409 for(slot->begin(it); !slot->end(it); slot->next(it)) { 00410 if(index >= len + it.endvertex - it.startvertex) 00411 len += it.endvertex - it.startvertex; 00412 else 00413 return &it.vertex[index - len]; 00414 } 00415 00416 return NULL; 00417 } 00418 00419 const float* RAS_MeshObject::GetVertexLocation(unsigned int orig_index) 00420 { 00421 vector<SharedVertex>& sharedmap = m_sharedvertex_map[orig_index]; 00422 vector<SharedVertex>::iterator it= sharedmap.begin(); 00423 return it->m_darray->m_vertex[it->m_offset].getXYZ(); 00424 } 00425 00426 void RAS_MeshObject::AddMeshUser(void *clientobj, SG_QList *head, RAS_Deformer* deformer) 00427 { 00428 list<RAS_MeshMaterial>::iterator it; 00429 list<RAS_MeshMaterial>::iterator mit; 00430 00431 for(it = m_materials.begin();it!=m_materials.end();++it) { 00432 /* always copy from the base slot, which is never removed 00433 * since new objects can be created with the same mesh data */ 00434 if (deformer && !deformer->UseVertexArray()) 00435 { 00436 // HACK! 00437 // this deformer doesn't use vertex array => derive mesh 00438 // we must keep only the mesh slots that have unique material id 00439 // this is to match the derived mesh drawing function 00440 // Need a better solution in the future: scan the derive mesh and create vertex array 00441 RAS_IPolyMaterial* curmat = it->m_bucket->GetPolyMaterial(); 00442 if (curmat->GetFlag() & RAS_BLENDERGLSL) 00443 { 00444 for(mit = m_materials.begin(); mit != it; ++mit) 00445 { 00446 RAS_IPolyMaterial* mat = mit->m_bucket->GetPolyMaterial(); 00447 if ((mat->GetFlag() & RAS_BLENDERGLSL) && 00448 mat->GetMaterialIndex() == curmat->GetMaterialIndex()) 00449 // no need to convert current mesh slot 00450 break; 00451 } 00452 if (mit != it) 00453 continue; 00454 } 00455 } 00456 RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot); 00457 ms->m_clientObj = clientobj; 00458 ms->SetDeformer(deformer); 00459 it->m_slots.insert(clientobj, ms); 00460 head->QAddBack(ms); 00461 } 00462 } 00463 00464 void RAS_MeshObject::RemoveFromBuckets(void *clientobj) 00465 { 00466 list<RAS_MeshMaterial>::iterator it; 00467 00468 for(it = m_materials.begin();it!=m_materials.end();++it) { 00469 RAS_MeshSlot **msp = it->m_slots[clientobj]; 00470 00471 if(!msp) 00472 continue; 00473 00474 RAS_MeshSlot *ms = *msp; 00475 00476 it->m_bucket->RemoveMesh(ms); 00477 it->m_slots.remove(clientobj); 00478 } 00479 } 00480 00481 //void RAS_MeshObject::Transform(const MT_Transform& trans) 00482 //{ 00483 //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); 00484 00485 // for (int i=0;i<m_Polygons.size();i++) 00486 // { 00487 // m_Polygons[i]->Transform(trans); 00488 // } 00489 //} 00490 00491 00492 /* 00493 void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) 00494 { 00495 for (int i=0;i<m_Polygons.size();i++) 00496 { 00497 m_Polygons[i]->RelativeTransform(vec); 00498 } 00499 } 00500 */ 00501 00502 void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform) 00503 { 00504 // Limitations: sorting is quite simple, and handles many 00505 // cases wrong, partially due to polygons being sorted per 00506 // bucket. 00507 // 00508 // a) mixed triangles/quads are sorted wrong 00509 // b) mixed materials are sorted wrong 00510 // c) more than 65k faces are sorted wrong 00511 // d) intersecting objects are sorted wrong 00512 // e) intersecting polygons are sorted wrong 00513 // 00514 // a) can be solved by making all faces either triangles or quads 00515 // if they need to be z-sorted. c) could be solved by allowing 00516 // larger buckets, b) and d) cannot be solved easily if we want 00517 // to avoid excessive state changes while drawing. e) would 00518 // require splitting polygons. 00519 00520 RAS_MeshSlot::iterator it; 00521 size_t j; 00522 00523 for(ms.begin(it); !ms.end(it); ms.next(it)) { 00524 unsigned int nvert = (int)it.array->m_type; 00525 unsigned int totpoly = it.totindex/nvert; 00526 00527 if(totpoly <= 1) 00528 continue; 00529 if(it.array->m_type == RAS_DisplayArray::LINE) 00530 continue; 00531 00532 // Extract camera Z plane... 00533 const MT_Vector3 pnorm(transform.getBasis()[2]); 00534 // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; 00535 00536 vector<polygonSlot> slots(totpoly); 00537 00538 /* get indices and z into temporary array */ 00539 for(j=0; j<totpoly; j++) 00540 slots[j].get(it.vertex, it.index, j*nvert, nvert, pnorm); 00541 00542 /* sort (stable_sort might be better, if flickering happens?) */ 00543 std::sort(slots.begin(), slots.end(), backtofront()); 00544 00545 /* get indices from temporary array again */ 00546 for(j=0; j<totpoly; j++) 00547 slots[j].set(it.index, j*nvert, nvert); 00548 } 00549 } 00550 00551 00552 void RAS_MeshObject::SchedulePolygons(int drawingmode) 00553 { 00554 if (m_bModified) 00555 { 00556 m_bModified = false; 00557 m_bMeshModified = true; 00558 } 00559 } 00560 00561 static int get_def_index(Object* ob, const char* vgroup) 00562 { 00563 bDeformGroup *curdef; 00564 int index = 0; 00565 00566 for (curdef = (bDeformGroup*)ob->defbase.first; curdef; curdef=(bDeformGroup*)curdef->next, index++) 00567 if (!strcmp(curdef->name, vgroup)) 00568 return index; 00569 00570 return -1; 00571 } 00572 00573 void RAS_MeshObject::CheckWeightCache(Object* obj) 00574 { 00575 KeyBlock *kb; 00576 int kbindex, defindex; 00577 MDeformVert *dvert= NULL; 00578 int totvert, i, j; 00579 float *weights; 00580 00581 if (!m_mesh->key) 00582 return; 00583 00584 for(kbindex=0, kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next, kbindex++) 00585 { 00586 // first check the cases where the weight must be cleared 00587 if (kb->vgroup[0] == 0 || 00588 m_mesh->dvert == NULL || 00589 (defindex = get_def_index(obj, kb->vgroup)) == -1) { 00590 if (kb->weights) { 00591 MEM_freeN(kb->weights); 00592 kb->weights = NULL; 00593 } 00594 m_cacheWeightIndex[kbindex] = -1; 00595 } else if (m_cacheWeightIndex[kbindex] != defindex) { 00596 // a weight array is required but the cache is not matching 00597 if (kb->weights) { 00598 MEM_freeN(kb->weights); 00599 kb->weights = NULL; 00600 } 00601 00602 dvert= m_mesh->dvert; 00603 totvert= m_mesh->totvert; 00604 00605 weights= (float*)MEM_callocN(totvert*sizeof(float), "weights"); 00606 00607 for (i=0; i < totvert; i++, dvert++) { 00608 for(j=0; j<dvert->totweight; j++) { 00609 if (dvert->dw[j].def_nr == defindex) { 00610 weights[i]= dvert->dw[j].weight; 00611 break; 00612 } 00613 } 00614 } 00615 kb->weights = weights; 00616 m_cacheWeightIndex[kbindex] = defindex; 00617 } 00618 } 00619 } 00620 00621