doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / gameengine / Rasterizer / RAS_MeshObject.cpp
1 /*
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28 #include "MEM_guardedalloc.h"
29
30 #include "DNA_object_types.h"
31 #include "DNA_key_types.h"
32 #include "DNA_mesh_types.h"
33 #include "DNA_meshdata_types.h"
34
35 #include "RAS_MeshObject.h"
36 #include "RAS_IRasterizer.h"
37 #include "MT_MinMax.h"
38 #include "MT_Point3.h"
39
40 #include <algorithm>
41
42 /* polygon sorting */
43
44 struct RAS_MeshObject::polygonSlot
45 {
46         float m_z;
47         int m_index[4];
48         
49         polygonSlot() {}
50
51         /* pnorm is the normal from the plane equation that the distance from is
52          * used to sort again. */
53         void get(const RAS_TexVert *vertexarray, const unsigned short *indexarray,
54                 int offset, int nvert, const MT_Vector3& pnorm)
55         {
56                 MT_Vector3 center(0, 0, 0);
57                 int i;
58
59                 for(i=0; i<nvert; i++) {
60                         m_index[i] = indexarray[offset+i];
61                         center += vertexarray[m_index[i]].getXYZ();
62                 }
63
64                 /* note we don't divide center by the number of vertices, since all
65                  * polygons have the same number of vertices, and that we leave out
66                  * the 4-th component of the plane equation since it is constant. */
67                 m_z = MT_dot(pnorm, center);
68         }
69
70         void set(unsigned short *indexarray, int offset, int nvert)
71         {
72                 int i;
73
74                 for(i=0; i<nvert; i++)
75                         indexarray[offset+i] = m_index[i];
76         }
77 };
78         
79 struct RAS_MeshObject::backtofront
80 {
81         bool operator()(const polygonSlot &a, const polygonSlot &b) const
82         {
83                 return a.m_z < b.m_z;
84         }
85 };
86
87 struct RAS_MeshObject::fronttoback
88 {
89         bool operator()(const polygonSlot &a, const polygonSlot &b) const
90         {
91                 return a.m_z > b.m_z;
92         }
93 };
94
95 /* mesh object */
96
97 STR_String RAS_MeshObject::s_emptyname = "";
98
99 RAS_MeshObject::RAS_MeshObject(Mesh* mesh)
100         : m_bModified(true),
101         m_bMeshModified(true),
102         m_mesh(mesh)
103 {
104         if (m_mesh && m_mesh->key)
105         {
106                 KeyBlock *kb;
107                 int count=0;
108                 // initialize weight cache for shape objects
109                 // count how many keys in this mesh
110                 for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next)
111                         count++;
112                 m_cacheWeightIndex.resize(count,-1);
113         }
114 }
115
116 RAS_MeshObject::~RAS_MeshObject()
117 {
118         vector<RAS_Polygon*>::iterator it;
119
120         if (m_mesh && m_mesh->key) 
121         {
122                 KeyBlock *kb;
123                 // remove the weight cache to avoid memory leak 
124                 for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) {
125                         if(kb->weights) 
126                                 MEM_freeN(kb->weights);
127                         kb->weights= NULL;
128                 }
129         }
130
131         for(it=m_Polygons.begin(); it!=m_Polygons.end(); it++)
132                 delete (*it);
133
134         m_sharedvertex_map.clear();
135         m_Polygons.clear();
136         m_materials.clear();
137 }
138
139 bool RAS_MeshObject::MeshModified()
140 {
141         return m_bMeshModified;
142 }
143
144 //unsigned int RAS_MeshObject::GetLightLayer()
145 //{
146 //      return m_lightlayer;
147 //}
148
149
150
151 int RAS_MeshObject::NumMaterials()
152 {
153         return m_materials.size();
154 }
155
156 const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid)
157
158         RAS_MeshMaterial* mmat = GetMeshMaterial(matid);
159
160         if(mmat)
161                 return mmat->m_bucket->GetPolyMaterial()->GetMaterialName();
162         
163         return s_emptyname;
164 }
165
166 RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid)
167 {
168         if (m_materials.size() > 0 && (matid < m_materials.size()))
169         {
170                 list<RAS_MeshMaterial>::iterator it = m_materials.begin();
171                 while (matid--) ++it;
172                 return &*it;
173         }
174
175         return NULL;
176 }
177
178
179
180 int RAS_MeshObject::NumPolygons()
181 {
182         return m_Polygons.size();
183 }
184
185
186
187 RAS_Polygon* RAS_MeshObject::GetPolygon(int num) const
188 {
189         return m_Polygons[num];
190 }
191
192         
193         
194
195         list<RAS_MeshMaterial>::iterator GetFirstMaterial();
196         list<RAS_MeshMaterial>::iterator GetLastMaterial();
197 list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetFirstMaterial()
198 {
199         return m_materials.begin();
200 }
201
202
203
204 list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetLastMaterial()
205 {
206         return m_materials.end();
207 }
208
209
210
211 void RAS_MeshObject::SetName(const char *name)
212 {
213         m_name = name;
214 }
215
216
217
218 STR_String& RAS_MeshObject::GetName()
219 {
220         return m_name;
221 }
222
223
224
225 const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid)
226
227         RAS_MeshMaterial* mmat = GetMeshMaterial(matid);
228         
229         if(mmat)
230                 return mmat->m_bucket->GetPolyMaterial()->GetTextureName();
231
232         return s_emptyname;
233 }
234
235 RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat)
236 {
237         list<RAS_MeshMaterial>::iterator mit;
238
239         /* find a mesh material */
240         for(mit = m_materials.begin(); mit != m_materials.end(); mit++)
241                 if(mit->m_bucket->GetPolyMaterial() == mat)
242                         return &*mit;
243
244         return NULL;
245 }
246
247 int RAS_MeshObject::GetMaterialId(RAS_IPolyMaterial *mat)
248 {
249         list<RAS_MeshMaterial>::iterator mit;
250         int imat;
251
252         /* find a mesh material */
253         for(imat=0, mit = m_materials.begin(); mit != m_materials.end(); mit++, imat++)
254                 if(mit->m_bucket->GetPolyMaterial() == mat)
255                         return imat;
256
257         return -1;
258 }
259
260 RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts)
261 {
262         RAS_MeshMaterial *mmat;
263         RAS_Polygon *poly;
264         RAS_MeshSlot *slot;
265
266         /* find a mesh material */
267         mmat = GetMeshMaterial(bucket->GetPolyMaterial());
268
269         /* none found, create a new one */
270         if(!mmat) {
271                 RAS_MeshMaterial meshmat;
272                 meshmat.m_bucket = bucket;
273                 meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts);
274                 meshmat.m_baseslot->m_mesh = this;
275                 m_materials.push_back(meshmat);
276                 mmat = &m_materials.back();
277         }
278
279         /* add it to the bucket, this also adds new display arrays */
280         slot = mmat->m_baseslot;
281         slot->AddPolygon(numverts);
282
283         /* create a new polygon */
284         RAS_DisplayArray *darray = slot->CurrentDisplayArray();
285         poly = new RAS_Polygon(bucket, darray, numverts);
286         m_Polygons.push_back(poly);
287
288         return poly;
289 }
290
291 void RAS_MeshObject::DebugColor(unsigned int abgr)
292 {
293         /*int numpolys = NumPolygons();
294
295         for (int i=0;i<numpolys;i++) {
296                 RAS_Polygon* poly = m_polygons[i];
297                 for (int v=0;v<poly->VertexCount();v++)
298                         RAS_TexVert* vtx = poly->GetVertex(v)->setDebugRGBA(abgr);
299         }
300         */
301
302         /* m_debugcolor = abgr; */
303 }
304
305 void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba)
306 {
307         RAS_MeshMaterial *mmat = GetMeshMaterial(mat);
308         RAS_MeshSlot *slot = mmat->m_baseslot;
309         RAS_MeshSlot::iterator it;
310         size_t i;
311
312         for(slot->begin(it); !slot->end(it); slot->next(it))
313                 for(i=it.startvertex; i<it.endvertex; i++)
314                         it.vertex[i].SetRGBA(rgba);
315 }
316
317 void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i,
318                                                                 const MT_Point3& xyz,
319                                                                 const MT_Point2& uv,
320                                                                 const MT_Point2& uv2,
321                                                                 const MT_Vector4& tangent,
322                                                                 const unsigned int rgba,
323                                                                 const MT_Vector3& normal,
324                                                                 bool flat,
325                                                                 int origindex)
326 {
327         RAS_TexVert texvert(xyz, uv, uv2, tangent, rgba, normal, flat, origindex);
328         RAS_MeshMaterial *mmat;
329         RAS_DisplayArray *darray;
330         RAS_MeshSlot *slot;
331         int offset;
332         
333         mmat = GetMeshMaterial(poly->GetMaterial()->GetPolyMaterial());
334         slot = mmat->m_baseslot;
335         darray = slot->CurrentDisplayArray();
336
337         { /* Shared Vertex! */
338                 /* find vertices shared between faces, with the restriction
339                  * that they exist in the same display array, and have the
340                  * same uv coordinate etc */
341                 vector<SharedVertex>& sharedmap = m_sharedvertex_map[origindex];
342                 vector<SharedVertex>::iterator it;
343
344                 for(it = sharedmap.begin(); it != sharedmap.end(); it++)
345                 {
346                         if(it->m_darray != darray)
347                                 continue;
348                         if(!it->m_darray->m_vertex[it->m_offset].closeTo(&texvert))
349                                 continue;
350
351                         /* found one, add it and we're done */
352                         if(poly->IsVisible())
353                                 slot->AddPolygonVertex(it->m_offset);
354                         poly->SetVertexOffset(i, it->m_offset);
355                         return;
356                 }
357         }
358
359         /* no shared vertex found, add a new one */
360         offset = slot->AddVertex(texvert);
361         if(poly->IsVisible())
362                 slot->AddPolygonVertex(offset);
363         poly->SetVertexOffset(i, offset);
364
365         { /* Shared Vertex! */
366                 SharedVertex shared;
367                 shared.m_darray = darray;
368                 shared.m_offset = offset;
369                 m_sharedvertex_map[origindex].push_back(shared);
370         }
371 }
372
373 int RAS_MeshObject::NumVertices(RAS_IPolyMaterial* mat)
374 {
375         RAS_MeshMaterial *mmat;
376         RAS_MeshSlot *slot;
377         RAS_MeshSlot::iterator it;
378         size_t len = 0;
379
380         mmat = GetMeshMaterial(mat);
381         slot = mmat->m_baseslot;
382         for(slot->begin(it); !slot->end(it); slot->next(it))
383                 len += it.endvertex - it.startvertex;
384         
385         return len;
386 }
387
388
389 RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid,
390                                                                            unsigned int index)
391 {
392         RAS_MeshMaterial *mmat;
393         RAS_MeshSlot *slot;
394         RAS_MeshSlot::iterator it;
395         size_t len;
396
397         mmat = GetMeshMaterial(matid);
398
399         if(!mmat)
400                 return NULL;
401         
402         slot = mmat->m_baseslot;
403         len = 0;
404         for(slot->begin(it); !slot->end(it); slot->next(it)) {
405                 if(index >= len + it.endvertex - it.startvertex)
406                         len += it.endvertex - it.startvertex;
407                 else
408                         return &it.vertex[index - len];
409         }
410         
411         return NULL;
412 }
413
414 const float* RAS_MeshObject::GetVertexLocation(unsigned int orig_index)
415 {
416         vector<SharedVertex>& sharedmap = m_sharedvertex_map[orig_index];
417         vector<SharedVertex>::iterator it= sharedmap.begin();
418         return it->m_darray->m_vertex[it->m_offset].getXYZ();
419 }
420
421 void RAS_MeshObject::AddMeshUser(void *clientobj, SG_QList *head, RAS_Deformer* deformer)
422 {
423         list<RAS_MeshMaterial>::iterator it;
424         list<RAS_MeshMaterial>::iterator mit;
425
426         for(it = m_materials.begin();it!=m_materials.end();++it) {
427                 /* always copy from the base slot, which is never removed 
428                  * since new objects can be created with the same mesh data */
429                 if (deformer && !deformer->UseVertexArray())
430                 {
431                         // HACK! 
432                         // this deformer doesn't use vertex array => derive mesh
433                         // we must keep only the mesh slots that have unique material id
434                         // this is to match the derived mesh drawing function
435                         // Need a better solution in the future: scan the derive mesh and create vertex array
436                         RAS_IPolyMaterial* curmat = it->m_bucket->GetPolyMaterial();
437                         if (curmat->GetFlag() & RAS_BLENDERGLSL) 
438                         {
439                                 for(mit = m_materials.begin(); mit != it; ++mit)
440                                 {
441                                         RAS_IPolyMaterial* mat = mit->m_bucket->GetPolyMaterial();
442                                         if ((mat->GetFlag() & RAS_BLENDERGLSL) && 
443                                                 mat->GetMaterialIndex() == curmat->GetMaterialIndex())
444                                                 // no need to convert current mesh slot
445                                                 break;
446                                 }
447                                 if (mit != it)
448                                         continue;
449                         }
450                 }
451                 RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot);
452                 ms->m_clientObj = clientobj;
453                 ms->SetDeformer(deformer);
454                 it->m_slots.insert(clientobj, ms);
455                 head->QAddBack(ms);
456         }
457 }
458
459 void RAS_MeshObject::RemoveFromBuckets(void *clientobj)
460 {
461         list<RAS_MeshMaterial>::iterator it;
462         
463         for(it = m_materials.begin();it!=m_materials.end();++it) {
464                 RAS_MeshSlot **msp = it->m_slots[clientobj];
465
466                 if(!msp)
467                         continue;
468
469                 RAS_MeshSlot *ms = *msp;
470
471                 it->m_bucket->RemoveMesh(ms);
472                 it->m_slots.remove(clientobj);
473         }
474 }
475
476 //void RAS_MeshObject::Transform(const MT_Transform& trans)
477 //{
478         //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans);
479         
480 //      for (int i=0;i<m_Polygons.size();i++)
481 //      {
482 //              m_Polygons[i]->Transform(trans);
483 //      }
484 //}
485
486
487 /*
488 void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec)
489 {
490         for (int i=0;i<m_Polygons.size();i++)
491         {
492                 m_Polygons[i]->RelativeTransform(vec);
493         }
494 }
495 */
496
497 void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform)
498 {
499         // Limitations: sorting is quite simple, and handles many
500         // cases wrong, partially due to polygons being sorted per
501         // bucket.
502         // 
503         // a) mixed triangles/quads are sorted wrong
504         // b) mixed materials are sorted wrong
505         // c) more than 65k faces are sorted wrong
506         // d) intersecting objects are sorted wrong
507         // e) intersecting polygons are sorted wrong
508         //
509         // a) can be solved by making all faces either triangles or quads
510         // if they need to be z-sorted. c) could be solved by allowing
511         // larger buckets, b) and d) cannot be solved easily if we want
512         // to avoid excessive state changes while drawing. e) would
513         // require splitting polygons.
514
515         RAS_MeshSlot::iterator it;
516         size_t j;
517
518         for(ms.begin(it); !ms.end(it); ms.next(it)) {
519                 unsigned int nvert = (int)it.array->m_type;
520                 unsigned int totpoly = it.totindex/nvert;
521
522                 if(totpoly <= 1)
523                         continue;
524                 if(it.array->m_type == RAS_DisplayArray::LINE)
525                         continue;
526
527                 // Extract camera Z plane...
528                 const MT_Vector3 pnorm(transform.getBasis()[2]);
529                 // unneeded: const MT_Scalar pval = transform.getOrigin()[2];
530
531                 vector<polygonSlot> slots(totpoly);
532
533                 /* get indices and z into temporary array */
534                 for(j=0; j<totpoly; j++)
535                         slots[j].get(it.vertex, it.index, j*nvert, nvert, pnorm);
536
537                 /* sort (stable_sort might be better, if flickering happens?) */
538                 std::sort(slots.begin(), slots.end(), backtofront());
539
540                 /* get indices from temporary array again */
541                 for(j=0; j<totpoly; j++)
542                         slots[j].set(it.index, j*nvert, nvert);
543         }
544 }
545
546
547 void RAS_MeshObject::SchedulePolygons(int drawingmode)
548 {
549         if (m_bModified)
550         {
551                 m_bModified = false;
552                 m_bMeshModified = true;
553         } 
554 }
555
556 static int get_def_index(Object* ob, const char* vgroup)
557 {
558         bDeformGroup *curdef;
559         int index = 0;
560
561         for (curdef = (bDeformGroup*)ob->defbase.first; curdef; curdef=(bDeformGroup*)curdef->next, index++)
562                 if (!strcmp(curdef->name, vgroup))
563                         return index;
564
565         return -1;
566 }
567
568 void RAS_MeshObject::CheckWeightCache(Object* obj)
569 {
570         KeyBlock *kb;
571         int kbindex, defindex;
572         MDeformVert *dvert= NULL;
573         int totvert, i, j;
574         float *weights;
575
576         if (!m_mesh->key)
577                 return;
578
579         for(kbindex=0, kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next, kbindex++)
580         {
581                 // first check the cases where the weight must be cleared
582                 if (kb->vgroup[0] == 0 ||
583                         m_mesh->dvert == NULL ||
584                         (defindex = get_def_index(obj, kb->vgroup)) == -1) {
585                         if (kb->weights) {
586                                 MEM_freeN(kb->weights);
587                                 kb->weights = NULL;
588                         }
589                         m_cacheWeightIndex[kbindex] = -1;
590                 } else if (m_cacheWeightIndex[kbindex] != defindex) {
591                         // a weight array is required but the cache is not matching
592                         if (kb->weights) {
593                                 MEM_freeN(kb->weights);
594                                 kb->weights = NULL;
595                         }
596
597                         dvert= m_mesh->dvert;
598                         totvert= m_mesh->totvert;
599                 
600                         weights= (float*)MEM_callocN(totvert*sizeof(float), "weights");
601                 
602                         for (i=0; i < totvert; i++, dvert++) {
603                                 for(j=0; j<dvert->totweight; j++) {
604                                         if (dvert->dw[j].def_nr == defindex) {
605                                                 weights[i]= dvert->dw[j].weight;
606                                                 break;
607                                         }
608                                 }
609                         }
610                         kb->weights = weights;
611                         m_cacheWeightIndex[kbindex] = defindex;
612                 }
613         }
614 }
615
616