Blender V2.61 - r43446

RAS_MeshObject.cpp

Go to the documentation of this file.
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