Blender  V2.59
RAS_MeshObject.cpp
Go to the documentation of this file.
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