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