Blender V2.61 - r43446

DerivedMesh.c

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) 2005 Blender Foundation.
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 
00033 #include <string.h>
00034 
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "DNA_cloth_types.h"
00039 #include "DNA_key_types.h"
00040 #include "DNA_meshdata_types.h"
00041 #include "DNA_armature_types.h"
00042 #include "DNA_object_types.h"
00043 #include "DNA_scene_types.h" // N_T
00044 
00045 #include "BLI_blenlib.h"
00046 #include "BLI_editVert.h"
00047 #include "BLI_math.h"
00048 #include "BLI_memarena.h"
00049 #include "BLI_pbvh.h"
00050 #include "BLI_utildefines.h"
00051 #include "BLI_linklist.h"
00052 
00053 #include "BKE_cdderivedmesh.h"
00054 #include "BKE_displist.h"
00055 #include "BKE_key.h"
00056 #include "BKE_modifier.h"
00057 #include "BKE_mesh.h"
00058 #include "BKE_object.h"
00059 #include "BKE_paint.h"
00060 #include "BKE_texture.h"
00061 #include "BKE_multires.h"
00062 #include "BKE_armature.h"
00063 #include "BKE_deform.h"
00064 
00065 #ifdef WITH_GAMEENGINE
00066 #include "BKE_navmesh_conversion.h"
00067 static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
00068 #endif
00069 
00070 #include "BLO_sys_types.h" // for intptr_t support
00071 
00072 #include "GL/glew.h"
00073 
00074 #include "GPU_buffers.h"
00075 #include "GPU_draw.h"
00076 #include "GPU_extensions.h"
00077 #include "GPU_material.h"
00078 
00079 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
00080 
00083 
00084 static MVert *dm_getVertArray(DerivedMesh *dm)
00085 {
00086     MVert *mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
00087 
00088     if (!mvert) {
00089         mvert = CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL,
00090             dm->getNumVerts(dm));
00091         CustomData_set_layer_flag(&dm->vertData, CD_MVERT, CD_FLAG_TEMPORARY);
00092         dm->copyVertArray(dm, mvert);
00093     }
00094 
00095     return mvert;
00096 }
00097 
00098 static MEdge *dm_getEdgeArray(DerivedMesh *dm)
00099 {
00100     MEdge *medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
00101 
00102     if (!medge) {
00103         medge = CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL,
00104             dm->getNumEdges(dm));
00105         CustomData_set_layer_flag(&dm->edgeData, CD_MEDGE, CD_FLAG_TEMPORARY);
00106         dm->copyEdgeArray(dm, medge);
00107     }
00108 
00109     return medge;
00110 }
00111 
00112 static MFace *dm_getFaceArray(DerivedMesh *dm)
00113 {
00114     MFace *mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
00115 
00116     if (!mface) {
00117         mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL,
00118             dm->getNumFaces(dm));
00119         CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
00120         dm->copyFaceArray(dm, mface);
00121     }
00122 
00123     return mface;
00124 }
00125 
00126 static MVert *dm_dupVertArray(DerivedMesh *dm)
00127 {
00128     MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm),
00129                              "dm_dupVertArray tmp");
00130 
00131     if(tmp) dm->copyVertArray(dm, tmp);
00132 
00133     return tmp;
00134 }
00135 
00136 static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
00137 {
00138     MEdge *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumEdges(dm),
00139                              "dm_dupEdgeArray tmp");
00140 
00141     if(tmp) dm->copyEdgeArray(dm, tmp);
00142 
00143     return tmp;
00144 }
00145 
00146 static MFace *dm_dupFaceArray(DerivedMesh *dm)
00147 {
00148     MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumFaces(dm),
00149                              "dm_dupFaceArray tmp");
00150 
00151     if(tmp) dm->copyFaceArray(dm, tmp);
00152 
00153     return tmp;
00154 }
00155 
00156 void DM_init_funcs(DerivedMesh *dm)
00157 {
00158     /* default function implementations */
00159     dm->getVertArray = dm_getVertArray;
00160     dm->getEdgeArray = dm_getEdgeArray;
00161     dm->getFaceArray = dm_getFaceArray;
00162     dm->dupVertArray = dm_dupVertArray;
00163     dm->dupEdgeArray = dm_dupEdgeArray;
00164     dm->dupFaceArray = dm_dupFaceArray;
00165 
00166     dm->getVertData = DM_get_vert_data;
00167     dm->getEdgeData = DM_get_edge_data;
00168     dm->getFaceData = DM_get_face_data;
00169     dm->getVertDataArray = DM_get_vert_data_layer;
00170     dm->getEdgeDataArray = DM_get_edge_data_layer;
00171     dm->getFaceDataArray = DM_get_face_data_layer;
00172 
00173     bvhcache_init(&dm->bvhCache);
00174 }
00175 
00176 void DM_init(DerivedMesh *dm, DerivedMeshType type,
00177              int numVerts, int numEdges, int numFaces)
00178 {
00179     dm->type = type;
00180     dm->numVertData = numVerts;
00181     dm->numEdgeData = numEdges;
00182     dm->numFaceData = numFaces;
00183 
00184     DM_init_funcs(dm);
00185     
00186     dm->needsFree = 1;
00187     dm->auto_bump_scale = -1.0f;
00188 }
00189 
00190 void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
00191                       int numVerts, int numEdges, int numFaces)
00192 {
00193     CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH,
00194                     CD_CALLOC, numVerts);
00195     CustomData_copy(&source->edgeData, &dm->edgeData, CD_MASK_DERIVEDMESH,
00196                     CD_CALLOC, numEdges);
00197     CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH,
00198                     CD_CALLOC, numFaces);
00199 
00200     dm->type = type;
00201     dm->numVertData = numVerts;
00202     dm->numEdgeData = numEdges;
00203     dm->numFaceData = numFaces;
00204 
00205     DM_init_funcs(dm);
00206 
00207     dm->needsFree = 1;
00208 }
00209 
00210 int DM_release(DerivedMesh *dm)
00211 {
00212     if (dm->needsFree) {
00213         bvhcache_free(&dm->bvhCache);
00214         GPU_drawobject_free( dm );
00215         CustomData_free(&dm->vertData, dm->numVertData);
00216         CustomData_free(&dm->edgeData, dm->numEdgeData);
00217         CustomData_free(&dm->faceData, dm->numFaceData);
00218 
00219         return 1;
00220     }
00221     else {
00222         CustomData_free_temporary(&dm->vertData, dm->numVertData);
00223         CustomData_free_temporary(&dm->edgeData, dm->numEdgeData);
00224         CustomData_free_temporary(&dm->faceData, dm->numFaceData);
00225 
00226         return 0;
00227     }
00228 }
00229 
00230 void DM_to_mesh(DerivedMesh *dm, Mesh *me)
00231 {
00232     /* dm might depend on me, so we need to do everything with a local copy */
00233     Mesh tmp = *me;
00234     int totvert, totedge, totface;
00235 
00236     memset(&tmp.vdata, 0, sizeof(tmp.vdata));
00237     memset(&tmp.edata, 0, sizeof(tmp.edata));
00238     memset(&tmp.fdata, 0, sizeof(tmp.fdata));
00239 
00240     totvert = tmp.totvert = dm->getNumVerts(dm);
00241     totedge = tmp.totedge = dm->getNumEdges(dm);
00242     totface = tmp.totface = dm->getNumFaces(dm);
00243 
00244     CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
00245     CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
00246     CustomData_copy(&dm->faceData, &tmp.fdata, CD_MASK_MESH, CD_DUPLICATE, totface);
00247 
00248     /* not all DerivedMeshes store their verts/edges/faces in CustomData, so
00249        we set them here in case they are missing */
00250     if(!CustomData_has_layer(&tmp.vdata, CD_MVERT))
00251         CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN, dm->dupVertArray(dm), totvert);
00252     if(!CustomData_has_layer(&tmp.edata, CD_MEDGE))
00253         CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, dm->dupEdgeArray(dm), totedge);
00254     if(!CustomData_has_layer(&tmp.fdata, CD_MFACE))
00255         CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupFaceArray(dm), totface);
00256 
00257     /* object had got displacement layer, should copy this layer to save sculpted data */
00258     /* NOTE: maybe some other layers should be copied? nazgul */
00259     if(CustomData_has_layer(&me->fdata, CD_MDISPS)) {
00260         if (totface == me->totface) {
00261             MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
00262             CustomData_add_layer(&tmp.fdata, CD_MDISPS, CD_DUPLICATE, mdisps, totface);
00263         }
00264     }
00265 
00266     mesh_update_customdata_pointers(&tmp);
00267 
00268     CustomData_free(&me->vdata, me->totvert);
00269     CustomData_free(&me->edata, me->totedge);
00270     CustomData_free(&me->fdata, me->totface);
00271 
00272     /* if the number of verts has changed, remove invalid data */
00273     if(tmp.totvert != me->totvert) {
00274         if(tmp.key) tmp.key->id.us--;
00275         tmp.key = NULL;
00276     }
00277 
00278     *me = tmp;
00279 }
00280 
00281 void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb)
00282 {
00283     int a, totvert = dm->getNumVerts(dm);
00284     float *fp;
00285     MVert *mvert;
00286     
00287     if(totvert==0 || me->totvert==0 || me->totvert!=totvert) return;
00288     
00289     if(kb->data) MEM_freeN(kb->data);
00290     kb->data= MEM_callocN(me->key->elemsize*me->totvert, "kb->data");
00291     kb->totelem= totvert;
00292     
00293     fp= kb->data;
00294     mvert=dm->getVertDataArray(dm, CD_MVERT);
00295     
00296     for(a=0; a<kb->totelem; a++, fp+=3, mvert++) {
00297         copy_v3_v3(fp, mvert->co);
00298     }
00299 }
00300 
00301 void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask)
00302 {
00303     CustomData_set_only_copy(&dm->vertData, mask);
00304     CustomData_set_only_copy(&dm->edgeData, mask);
00305     CustomData_set_only_copy(&dm->faceData, mask);
00306 }
00307 
00308 void DM_add_vert_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
00309 {
00310     CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData);
00311 }
00312 
00313 void DM_add_edge_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
00314 {
00315     CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
00316 }
00317 
00318 void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
00319 {
00320     CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData);
00321 }
00322 
00323 void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
00324 {
00325     return CustomData_get(&dm->vertData, index, type);
00326 }
00327 
00328 void *DM_get_edge_data(DerivedMesh *dm, int index, int type)
00329 {
00330     return CustomData_get(&dm->edgeData, index, type);
00331 }
00332 
00333 void *DM_get_face_data(DerivedMesh *dm, int index, int type)
00334 {
00335     return CustomData_get(&dm->faceData, index, type);
00336 }
00337 
00338 void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
00339 {
00340     if(type == CD_MVERT)
00341         return dm->getVertArray(dm);
00342 
00343     return CustomData_get_layer(&dm->vertData, type);
00344 }
00345 
00346 void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
00347 {
00348     if(type == CD_MEDGE)
00349         return dm->getEdgeArray(dm);
00350 
00351     return CustomData_get_layer(&dm->edgeData, type);
00352 }
00353 
00354 void *DM_get_face_data_layer(DerivedMesh *dm, int type)
00355 {
00356     if(type == CD_MFACE)
00357         return dm->getFaceArray(dm);
00358 
00359     return CustomData_get_layer(&dm->faceData, type);
00360 }
00361 
00362 void DM_set_vert_data(DerivedMesh *dm, int index, int type, void *data)
00363 {
00364     CustomData_set(&dm->vertData, index, type, data);
00365 }
00366 
00367 void DM_set_edge_data(DerivedMesh *dm, int index, int type, void *data)
00368 {
00369     CustomData_set(&dm->edgeData, index, type, data);
00370 }
00371 
00372 void DM_set_face_data(DerivedMesh *dm, int index, int type, void *data)
00373 {
00374     CustomData_set(&dm->faceData, index, type, data);
00375 }
00376 
00377 void DM_copy_vert_data(DerivedMesh *source, DerivedMesh *dest,
00378                        int source_index, int dest_index, int count)
00379 {
00380     CustomData_copy_data(&source->vertData, &dest->vertData,
00381                          source_index, dest_index, count);
00382 }
00383 
00384 void DM_copy_edge_data(DerivedMesh *source, DerivedMesh *dest,
00385                        int source_index, int dest_index, int count)
00386 {
00387     CustomData_copy_data(&source->edgeData, &dest->edgeData,
00388                          source_index, dest_index, count);
00389 }
00390 
00391 void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest,
00392                        int source_index, int dest_index, int count)
00393 {
00394     CustomData_copy_data(&source->faceData, &dest->faceData,
00395                          source_index, dest_index, count);
00396 }
00397 
00398 void DM_free_vert_data(struct DerivedMesh *dm, int index, int count)
00399 {
00400     CustomData_free_elem(&dm->vertData, index, count);
00401 }
00402 
00403 void DM_free_edge_data(struct DerivedMesh *dm, int index, int count)
00404 {
00405     CustomData_free_elem(&dm->edgeData, index, count);
00406 }
00407 
00408 void DM_free_face_data(struct DerivedMesh *dm, int index, int count)
00409 {
00410     CustomData_free_elem(&dm->faceData, index, count);
00411 }
00412 
00413 void DM_interp_vert_data(DerivedMesh *source, DerivedMesh *dest,
00414                          int *src_indices, float *weights,
00415                          int count, int dest_index)
00416 {
00417     CustomData_interp(&source->vertData, &dest->vertData, src_indices,
00418                       weights, NULL, count, dest_index);
00419 }
00420 
00421 void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest,
00422                          int *src_indices,
00423                          float *weights, EdgeVertWeight *vert_weights,
00424                          int count, int dest_index)
00425 {
00426     CustomData_interp(&source->edgeData, &dest->edgeData, src_indices,
00427                       weights, (float*)vert_weights, count, dest_index);
00428 }
00429 
00430 void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
00431                          int *src_indices,
00432                          float *weights, FaceVertWeight *vert_weights,
00433                          int count, int dest_index)
00434 {
00435     CustomData_interp(&source->faceData, &dest->faceData, src_indices,
00436                       weights, (float*)vert_weights, count, dest_index);
00437 }
00438 
00439 void DM_swap_face_data(DerivedMesh *dm, int index, const int *corner_indices)
00440 {
00441     CustomData_swap(&dm->faceData, index, corner_indices);
00442 }
00443 
00445 
00446 DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3])
00447 {
00448     DerivedMesh *dm = CDDM_from_mesh(me, ob);
00449     
00450     if(!dm)
00451         return NULL;
00452     
00453     if (vertCos)
00454         CDDM_apply_vert_coords(dm, vertCos);
00455 
00456     CDDM_calc_normals(dm);
00457 
00458     return dm;
00459 }
00460 
00461 DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md)
00462 {
00463     Mesh *me = ob->data;
00464     ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00465     DerivedMesh *dm;
00466 
00467     md->scene= scene;
00468     
00469     if (!(md->mode&eModifierMode_Realtime)) return NULL;
00470     if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL;
00471 
00472     if (mti->type==eModifierTypeType_OnlyDeform) {
00473         int numVerts;
00474         float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
00475 
00476         mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0);
00477         dm = mesh_create_derived(me, ob, deformedVerts);
00478 
00479         MEM_freeN(deformedVerts);
00480     } else {
00481         DerivedMesh *tdm = mesh_create_derived(me, ob, NULL);
00482         dm = mti->applyModifier(md, ob, tdm, 0, 0);
00483 
00484         if(tdm != dm) tdm->release(tdm);
00485     }
00486 
00487     return dm;
00488 }
00489 
00490 static float *get_editmesh_orco_verts(EditMesh *em)
00491 {
00492     EditVert *eve;
00493     float *orco;
00494     int a, totvert;
00495 
00496     /* these may not really be the orco's, but it's only for preview.
00497      * could be solver better once, but isn't simple */
00498 
00499     totvert= 0;
00500     for(eve=em->verts.first; eve; eve=eve->next)
00501         totvert++;
00502     
00503     orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco");
00504 
00505     for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3) {
00506         copy_v3_v3(orco+a, eve->co);
00507     }
00508     
00509     return orco;
00510 }
00511 
00512 /* orco custom data layer */
00513 
00514 static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free)
00515 {
00516     *free= 0;
00517 
00518     if(layer == CD_ORCO) {
00519         /* get original coordinates */
00520         *free= 1;
00521 
00522         if(em)
00523             return (float(*)[3])get_editmesh_orco_verts(em);
00524         else
00525             return (float(*)[3])get_mesh_orco_verts(ob);
00526     }
00527     else if(layer == CD_CLOTH_ORCO) {
00528         /* apply shape key for cloth, this should really be solved
00529            by a more flexible customdata system, but not simple */
00530         if(!em) {
00531             ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
00532             KeyBlock *kb= key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest);
00533 
00534             if(kb->data)
00535                 return kb->data;
00536         }
00537 
00538         return NULL;
00539     }
00540 
00541     return NULL;
00542 }
00543 
00544 static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em, int layer)
00545 {
00546     DerivedMesh *dm;
00547     float (*orco)[3];
00548     int free;
00549 
00550     if(em) dm= CDDM_from_editmesh(em, me);
00551     else dm= CDDM_from_mesh(me, ob);
00552 
00553     orco= get_orco_coords_dm(ob, em, layer, &free);
00554 
00555     if(orco) {
00556         CDDM_apply_vert_coords(dm, orco);
00557         if(free) MEM_freeN(orco);
00558     }
00559 
00560     CDDM_calc_normals(dm);
00561 
00562     return dm;
00563 }
00564 
00565 static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm, int layer)
00566 {
00567     float (*orco)[3], (*layerorco)[3];
00568     int totvert, free;
00569 
00570     totvert= dm->getNumVerts(dm);
00571 
00572     if(orcodm) {
00573         orco= MEM_callocN(sizeof(float)*3*totvert, "dm orco");
00574         free= 1;
00575 
00576         if(orcodm->getNumVerts(orcodm) == totvert)
00577             orcodm->getVertCos(orcodm, orco);
00578         else
00579             dm->getVertCos(dm, orco);
00580     }
00581     else
00582         orco= get_orco_coords_dm(ob, em, layer, &free);
00583 
00584     if(orco) {
00585         if(layer == CD_ORCO)
00586             transform_mesh_orco_verts(ob->data, orco, totvert, 0);
00587 
00588         if(!(layerorco = DM_get_vert_data_layer(dm, layer))) {
00589             DM_add_vert_layer(dm, layer, CD_CALLOC, NULL);
00590             layerorco = DM_get_vert_data_layer(dm, layer);
00591         }
00592 
00593         memcpy(layerorco, orco, sizeof(float)*3*totvert);
00594         if(free) MEM_freeN(orco);
00595     }
00596 }
00597 
00598 /* weight paint colors */
00599 
00600 /* Something of a hack, at the moment deal with weightpaint
00601  * by tucking into colors during modifier eval, only in
00602  * wpaint mode. Works ok but need to make sure recalc
00603  * happens on enter/exit wpaint.
00604  */
00605 
00606 void weight_to_rgb(float r_rgb[3], const float weight)
00607 {
00608     const float blend= ((weight/2.0f)+0.5f);
00609 
00610     if (weight<=0.25f){ // blue->cyan
00611         r_rgb[0]= 0.0f;
00612         r_rgb[1]= blend*weight*4.0f;
00613         r_rgb[2]= blend;
00614     }
00615     else if (weight<=0.50f){    // cyan->green
00616         r_rgb[0]= 0.0f;
00617         r_rgb[1]= blend;
00618         r_rgb[2]= blend*(1.0f-((weight-0.25f)*4.0f));
00619     }
00620     else if (weight <= 0.75f){  // green->yellow
00621         r_rgb[0]= blend * ((weight-0.50f)*4.0f);
00622         r_rgb[1]= blend;
00623         r_rgb[2]= 0.0f;
00624     }
00625     else if (weight <= 1.0f){ // yellow->red
00626         r_rgb[0]= blend;
00627         r_rgb[1]= blend * (1.0f-((weight-0.75f)*4.0f));
00628         r_rgb[2]= 0.0f;
00629     }
00630     else {
00631         /* exceptional value, unclamped or nan,
00632          * avoid uninitialized memory use */
00633         r_rgb[0]= 1.0f;
00634         r_rgb[1]= 0.0f;
00635         r_rgb[2]= 1.0f;
00636     }
00637 }
00638 
00639 /* draw_flag's for calc_weightpaint_vert_color */
00640 enum {
00641     CALC_WP_MULTIPAINT= (1<<0),
00642     CALC_WP_AUTO_NORMALIZE= (1<<1)
00643 };
00644 
00645 static void weightpaint_color(unsigned char r_col[4], ColorBand *coba, const float input)
00646 {
00647     float colf[4];
00648 
00649     if(coba) do_colorband(coba, input, colf);
00650     else     weight_to_rgb(colf, input);
00651 
00652     r_col[3] = (unsigned char)(colf[0] * 255.0f);
00653     r_col[2] = (unsigned char)(colf[1] * 255.0f);
00654     r_col[1] = (unsigned char)(colf[2] * 255.0f);
00655     r_col[0] = 255;
00656 }
00657 
00658 
00659 static void calc_weightpaint_vert_color(
00660         unsigned char r_col[4],
00661         MDeformVert *dv, ColorBand *coba,
00662         const int defbase_tot, const int defbase_act,
00663         const char *dg_flags,
00664         const int selected, const int draw_flag)
00665 {
00666     float input = 0.0f;
00667     
00668     int make_black= FALSE;
00669 
00670     if ((selected > 1) && (draw_flag & CALC_WP_MULTIPAINT)) {
00671         int was_a_nonzero= FALSE;
00672         unsigned int i;
00673 
00674         MDeformWeight *dw= dv->dw;
00675         for (i = dv->totweight; i != 0; i--, dw++) {
00676             /* in multipaint, get the average if auto normalize is inactive
00677              * get the sum if it is active */
00678             if (dw->def_nr < defbase_tot) {
00679                 if (dg_flags[dw->def_nr]) {
00680                     if (dw->weight) {
00681                         input += dw->weight;
00682                         was_a_nonzero= TRUE;
00683                     }
00684                 }
00685             }
00686         }
00687 
00688         /* make it black if the selected groups have no weight on a vertex */
00689         if (was_a_nonzero == FALSE) {
00690             make_black = TRUE;
00691         }
00692         else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) {
00693             input /= selected; /* get the average */
00694         }
00695     }
00696     else {
00697         /* default, non tricky behavior */
00698         input= defvert_find_weight(dv, defbase_act);
00699     }
00700 
00701     if (make_black) { /* TODO, theme color */
00702         r_col[3] = 0;
00703         r_col[2] = 0;
00704         r_col[1] = 0;
00705         r_col[0] = 255;
00706     }
00707     else {
00708         CLAMP(input, 0.0f, 1.0f);
00709         weightpaint_color(r_col, coba, input);
00710     }
00711 }
00712 
00713 static ColorBand *stored_cb= NULL;
00714 
00715 void vDM_ColorBand_store(ColorBand *coba)
00716 {
00717     stored_cb= coba;
00718 }
00719 
00720 /* return an array of vertex weight colors, caller must free.
00721  *
00722  * note that we could save some memory and allocate RGB only but then we'd need to
00723  * re-arrange the colors when copying to the face since MCol has odd ordering,
00724  * so leave this as is - campbell */
00725 static unsigned char *calc_weightpaint_vert_array(Object *ob, int const draw_flag, ColorBand *coba)
00726 {
00727     Mesh *me = ob->data;
00728     unsigned char *wtcol_v = MEM_mallocN (sizeof(unsigned char) * me->totvert * 4, "weightmap_v");
00729 
00730     if (me->dvert) {
00731         unsigned char *wc = wtcol_v;
00732         MDeformVert *dv= me->dvert;
00733         unsigned int i;
00734 
00735         /* varisbles for multipaint */
00736         const int defbase_tot = BLI_countlist(&ob->defbase);
00737         const int defbase_act = ob->actdef-1;
00738         char *dg_flags = MEM_mallocN(defbase_tot * sizeof(char), __func__);
00739         const int selected = get_selected_defgroups(ob, dg_flags, defbase_tot);
00740         /* const int unselected = defbase_tot - selected; */ /* UNUSED */
00741 
00742         for (i = me->totvert; i != 0; i--, wc += 4, dv++) {
00743             calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, dg_flags, selected, draw_flag);
00744         }
00745 
00746         MEM_freeN(dg_flags);
00747     }
00748     else {
00749         int col_i;
00750         weightpaint_color((unsigned char *)&col_i, coba, 0.0f);
00751         fill_vn_i((int *)wtcol_v, me->totvert, col_i);
00752     }
00753 
00754     return wtcol_v;
00755 }
00756 
00757 static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
00758 {
00759     ColorBand *coba= stored_cb; /* warning, not a local var */
00760 
00761     Mesh *me = ob->data;
00762     unsigned char *wtcol_v = calc_weightpaint_vert_array(ob, draw_flag, coba);
00763     unsigned char *wtcol_f = MEM_mallocN (sizeof(unsigned char) * me->totface*4*4, "weightmap_f");
00764     unsigned char *wtcol_f_step = wtcol_f;
00765 
00766     MFace *mf = me->mface;
00767     int i;
00768 
00769     for (i=0; i<me->totface; i++, mf++, wtcol_f_step += (4 * 4)) {
00770 #if 0
00771         unsigned int fidx= mf->v4 ? 3:2;
00772 
00773 #else   /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */
00774         unsigned int fidx;
00775         if (mf->v4) {
00776             fidx = 3;
00777         }
00778         else {
00779             fidx = 2;
00780             *(int *)(&wtcol_f_step[3 * 4]) = 0;
00781         }
00782 #endif
00783 
00784         do {
00785             copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4],
00786                             (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]);
00787         } while (fidx--);
00788     }
00789 
00790     MEM_freeN(wtcol_v);
00791 
00792     CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol_f, dm->numFaceData);
00793 }
00794 
00795 /* new value for useDeform -1  (hack for the gameengine):
00796  * - apply only the modifier stack of the object, skipping the virtual modifiers,
00797  * - don't apply the key
00798  * - apply deform modifiers and input vertexco
00799  */
00800 static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3],
00801                                 DerivedMesh **deform_r, DerivedMesh **final_r,
00802                                 int useRenderParams, int useDeform,
00803                                 int needMapping, CustomDataMask dataMask, int index, int useCache)
00804 {
00805     Mesh *me = ob->data;
00806     ModifierData *firstmd, *md;
00807     LinkNode *datamasks, *curr;
00808     CustomDataMask mask, nextmask, append_mask = 0;
00809     float (*deformedVerts)[3] = NULL;
00810     DerivedMesh *dm, *orcodm, *clothorcodm, *finaldm;
00811     int numVerts = me->totvert;
00812     int required_mode;
00813     int isPrevDeform= FALSE;
00814     int skipVirtualArmature = (useDeform < 0);
00815     MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0);
00816     int has_multires = mmd != NULL, multires_applied = 0;
00817     int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt;
00818 
00819     int draw_flag= ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) |
00820                     (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0));
00821 
00822     if(mmd && !mmd->sculptlvl)
00823         has_multires = 0;
00824 
00825     if(!skipVirtualArmature) {
00826         firstmd = modifiers_getVirtualModifierList(ob);
00827     }
00828     else {
00829         /* game engine exception */
00830         firstmd = ob->modifiers.first;
00831         if(firstmd && firstmd->type == eModifierType_Armature)
00832             firstmd = firstmd->next;
00833     }
00834 
00835     md = firstmd;
00836 
00837     modifiers_clearErrors(ob);
00838 
00839     if(useRenderParams) required_mode = eModifierMode_Render;
00840     else required_mode = eModifierMode_Realtime;
00841 
00842     datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode);
00843     curr = datamasks;
00844 
00845     if(deform_r) *deform_r = NULL;
00846     *final_r = NULL;
00847 
00848     if(useDeform) {
00849         if(inputVertexCos)
00850             deformedVerts = inputVertexCos;
00851         
00852         /* Apply all leading deforming modifiers */
00853         for(;md; md = md->next, curr = curr->next) {
00854             ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00855 
00856             md->scene= scene;
00857             
00858             if(!modifier_isEnabled(scene, md, required_mode)) continue;
00859             if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
00860 
00861             if(mti->type == eModifierTypeType_OnlyDeform) {
00862                 if(!deformedVerts)
00863                     deformedVerts = mesh_getVertexCos(me, &numVerts);
00864 
00865                 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, useRenderParams, useDeform);
00866             } else {
00867                 break;
00868             }
00869             
00870             /* grab modifiers until index i */
00871             if((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
00872                 break;
00873         }
00874 
00875         /* Result of all leading deforming modifiers is cached for
00876          * places that wish to use the original mesh but with deformed
00877          * coordinates (vpaint, etc.)
00878          */
00879         if (deform_r) {
00880             *deform_r = CDDM_from_mesh(me, ob);
00881 
00882             if(deformedVerts) {
00883                 CDDM_apply_vert_coords(*deform_r, deformedVerts);
00884                 CDDM_calc_normals(*deform_r);
00885             }
00886         }
00887     } else {
00888         /* default behaviour for meshes */
00889         if(inputVertexCos)
00890             deformedVerts = inputVertexCos;
00891         else
00892             deformedVerts = mesh_getVertexCos(me, &numVerts);
00893     }
00894 
00895 
00896     /* Now apply all remaining modifiers. If useDeform is off then skip
00897      * OnlyDeform ones. 
00898      */
00899     dm = NULL;
00900     orcodm = NULL;
00901     clothorcodm = NULL;
00902 
00903     for(;md; md = md->next, curr = curr->next) {
00904         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00905 
00906         md->scene= scene;
00907 
00908         if(!modifier_isEnabled(scene, md, required_mode)) continue;
00909         if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
00910         if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
00911             modifier_setError(md, "Modifier requires original data, bad stack position.");
00912             continue;
00913         }
00914         if(sculpt_mode && (!has_multires || multires_applied)) {
00915             int unsupported= 0;
00916 
00917             if(scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM)
00918                 unsupported|= mti->type != eModifierTypeType_OnlyDeform;
00919 
00920             unsupported|= md->type == eModifierType_Multires && ((MultiresModifierData*)md)->sculptlvl==0;
00921             unsupported|= multires_applied;
00922 
00923             if(unsupported) {
00924                 modifier_setError(md, "Not supported in sculpt mode.");
00925                 continue;
00926             }
00927         }
00928         if(needMapping && !modifier_supportsMapping(md)) continue;
00929         if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
00930 
00931         /* add an orco layer if needed by this modifier */
00932         if(mti->requiredDataMask)
00933             mask = mti->requiredDataMask(ob, md);
00934         else
00935             mask = 0;
00936 
00937         if(dm && (mask & CD_MASK_ORCO))
00938             add_orco_dm(ob, NULL, dm, orcodm, CD_ORCO);
00939 
00940         /* How to apply modifier depends on (a) what we already have as
00941          * a result of previous modifiers (could be a DerivedMesh or just
00942          * deformed vertices) and (b) what type the modifier is.
00943          */
00944 
00945         if(mti->type == eModifierTypeType_OnlyDeform) {
00946             /* No existing verts to deform, need to build them. */
00947             if(!deformedVerts) {
00948                 if(dm) {
00949                     /* Deforming a derived mesh, read the vertex locations
00950                      * out of the mesh and deform them. Once done with this
00951                      * run of deformers verts will be written back.
00952                      */
00953                     numVerts = dm->getNumVerts(dm);
00954                     deformedVerts =
00955                         MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
00956                     dm->getVertCos(dm, deformedVerts);
00957                 } else {
00958                     deformedVerts = mesh_getVertexCos(me, &numVerts);
00959                 }
00960             }
00961 
00962             /* if this is not the last modifier in the stack then recalculate the normals
00963              * to avoid giving bogus normals to the next modifier see: [#23673] */
00964             if(isPrevDeform &&  mti->dependsOnNormals && mti->dependsOnNormals(md)) {
00965                 /* XXX, this covers bug #23673, but we may need normal calc for other types */
00966                 if(dm && dm->type == DM_TYPE_CDDM) {
00967                     CDDM_apply_vert_coords(dm, deformedVerts);
00968                     CDDM_calc_normals(dm);
00969                 }
00970             }
00971 
00972             mti->deformVerts(md, ob, dm, deformedVerts, numVerts, useRenderParams, useDeform);
00973         } else {
00974             DerivedMesh *ndm;
00975 
00976             /* determine which data layers are needed by following modifiers */
00977             if(curr->next)
00978                 nextmask= (CustomDataMask)GET_INT_FROM_POINTER(curr->next->link);
00979             else
00980                 nextmask= dataMask;
00981 
00982             /* apply vertex coordinates or build a DerivedMesh as necessary */
00983             if(dm) {
00984                 if(deformedVerts) {
00985                     DerivedMesh *tdm = CDDM_copy(dm);
00986                     dm->release(dm);
00987                     dm = tdm;
00988 
00989                     CDDM_apply_vert_coords(dm, deformedVerts);
00990                     CDDM_calc_normals(dm);
00991                 }
00992             } else {
00993                 dm = CDDM_from_mesh(me, ob);
00994 
00995                 if(deformedVerts) {
00996                     CDDM_apply_vert_coords(dm, deformedVerts);
00997                     CDDM_calc_normals(dm);
00998                 }
00999 
01000                 if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
01001                     add_weight_mcol_dm(ob, dm, draw_flag); 
01002 
01003                 /* Constructive modifiers need to have an origindex
01004                  * otherwise they wont have anywhere to copy the data from.
01005                  *
01006                  * Also create ORIGINDEX data if any of the following modifiers
01007                  * requests it, this way Mirror, Solidify etc will keep ORIGINDEX
01008                  * data by using generic DM_copy_vert_data() functions.
01009                  */
01010                 if(needMapping || (nextmask & CD_MASK_ORIGINDEX)) {
01011                     /* calc */
01012                     DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
01013                     DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
01014                     DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
01015 
01016                     range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0);
01017                     range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0);
01018                     range_vn_i(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numFaceData, 0);
01019                 }
01020             }
01021 
01022             
01023             /* set the DerivedMesh to only copy needed data */
01024             mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link);
01025             /* needMapping check here fixes bug [#28112], otherwise its
01026              * possible that it wont be copied */
01027             mask |= append_mask;
01028             DM_set_only_copy(dm, mask | (needMapping ? CD_MASK_ORIGINDEX : 0));
01029             
01030             /* add cloth rest shape key if need */
01031             if(mask & CD_MASK_CLOTH_ORCO)
01032                 add_orco_dm(ob, NULL, dm, clothorcodm, CD_CLOTH_ORCO);
01033 
01034             /* add an origspace layer if needed */
01035             if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE)
01036                 if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
01037                     DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
01038 
01039             ndm = mti->applyModifier(md, ob, dm, useRenderParams, useCache);
01040 
01041             if(ndm) {
01042                 /* if the modifier returned a new dm, release the old one */
01043                 if(dm && dm != ndm) dm->release(dm);
01044 
01045                 dm = ndm;
01046 
01047                 if(deformedVerts) {
01048                     if(deformedVerts != inputVertexCos)
01049                         MEM_freeN(deformedVerts);
01050 
01051                     deformedVerts = NULL;
01052                 }
01053             } 
01054 
01055             /* create an orco derivedmesh in parallel */
01056             if(nextmask & CD_MASK_ORCO) {
01057                 if(!orcodm)
01058                     orcodm= create_orco_dm(ob, me, NULL, CD_ORCO);
01059 
01060                 nextmask &= ~CD_MASK_ORCO;
01061                 DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX);
01062                 ndm = mti->applyModifier(md, ob, orcodm, useRenderParams, 0);
01063 
01064                 if(ndm) {
01065                     /* if the modifier returned a new dm, release the old one */
01066                     if(orcodm && orcodm != ndm) orcodm->release(orcodm);
01067                     orcodm = ndm;
01068                 }
01069             }
01070 
01071             /* create cloth orco derivedmesh in parallel */
01072             if(nextmask & CD_MASK_CLOTH_ORCO) {
01073                 if(!clothorcodm)
01074                     clothorcodm= create_orco_dm(ob, me, NULL, CD_CLOTH_ORCO);
01075 
01076                 nextmask &= ~CD_MASK_CLOTH_ORCO;
01077                 DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX);
01078                 ndm = mti->applyModifier(md, ob, clothorcodm, useRenderParams, 0);
01079 
01080                 if(ndm) {
01081                     /* if the modifier returned a new dm, release the old one */
01082                     if(clothorcodm && clothorcodm != ndm) clothorcodm->release(clothorcodm);
01083                     clothorcodm = ndm;
01084                 }
01085             }
01086 
01087             /* in case of dynamic paint, make sure preview mask remains for following modifiers */
01088             if (md->type == eModifierType_DynamicPaint)
01089                 append_mask |= CD_MASK_WEIGHT_MCOL;
01090         }
01091 
01092         isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform);
01093 
01094         /* grab modifiers until index i */
01095         if((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
01096             break;
01097 
01098         if(sculpt_mode && md->type == eModifierType_Multires)
01099             multires_applied = 1;
01100     }
01101 
01102     for(md=firstmd; md; md=md->next)
01103         modifier_freeTemporaryData(md);
01104 
01105     /* Yay, we are done. If we have a DerivedMesh and deformed vertices
01106      * need to apply these back onto the DerivedMesh. If we have no
01107      * DerivedMesh then we need to build one.
01108      */
01109     if(dm && deformedVerts) {
01110         finaldm = CDDM_copy(dm);
01111 
01112         dm->release(dm);
01113 
01114         CDDM_apply_vert_coords(finaldm, deformedVerts);
01115         CDDM_calc_normals(finaldm);
01116 
01117         if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
01118             add_weight_mcol_dm(ob, finaldm, draw_flag);
01119     } else if(dm) {
01120         finaldm = dm;
01121     } else {
01122         finaldm = CDDM_from_mesh(me, ob);
01123 
01124         if(deformedVerts) {
01125             CDDM_apply_vert_coords(finaldm, deformedVerts);
01126             CDDM_calc_normals(finaldm);
01127         }
01128 
01129         if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
01130             add_weight_mcol_dm(ob, finaldm, draw_flag);
01131     }
01132 
01133     /* add an orco layer if needed */
01134     if(dataMask & CD_MASK_ORCO) {
01135         add_orco_dm(ob, NULL, finaldm, orcodm, CD_ORCO);
01136 
01137         if(deform_r && *deform_r)
01138             add_orco_dm(ob, NULL, *deform_r, NULL, CD_ORCO);
01139     }
01140 
01141 #ifdef WITH_GAMEENGINE
01142     /* NavMesh - this is a hack but saves having a NavMesh modifier */
01143     if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) {
01144         DerivedMesh *tdm;
01145         tdm= navmesh_dm_createNavMeshForVisualization(finaldm);
01146         if (finaldm != tdm) {
01147             finaldm->release(finaldm);
01148             finaldm= tdm;
01149         }
01150     }
01151 #endif /* WITH_GAMEENGINE */
01152 
01153     *final_r = finaldm;
01154 
01155     if(orcodm)
01156         orcodm->release(orcodm);
01157     if(clothorcodm)
01158         clothorcodm->release(clothorcodm);
01159 
01160     if(deformedVerts && deformedVerts != inputVertexCos)
01161         MEM_freeN(deformedVerts);
01162 
01163     BLI_linklist_free(datamasks, NULL);
01164 }
01165 
01166 float (*editmesh_get_vertex_cos(EditMesh *em, int *numVerts_r))[3]
01167 {
01168     int i, numVerts = *numVerts_r = BLI_countlist(&em->verts);
01169     float (*cos)[3];
01170     EditVert *eve;
01171 
01172     cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos");
01173     for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) {
01174         copy_v3_v3(cos[i], eve->co);
01175     }
01176 
01177     return cos;
01178 }
01179 
01180 int editmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm)
01181 {
01182     ModifierTypeInfo *mti = modifierType_getInfo(md->type);
01183     int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
01184 
01185     if(!modifier_isEnabled(scene, md, required_mode)) return 0;
01186     if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
01187         modifier_setError(md, "Modifier requires original data, bad stack position.");
01188         return 0;
01189     }
01190     
01191     return 1;
01192 }
01193 
01194 static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, DerivedMesh **cage_r,
01195                                     DerivedMesh **final_r,
01196                                     CustomDataMask dataMask)
01197 {
01198     ModifierData *md;
01199     float (*deformedVerts)[3] = NULL;
01200     CustomDataMask mask;
01201     DerivedMesh *dm, *orcodm = NULL;
01202     int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
01203     LinkNode *datamasks, *curr;
01204     int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
01205 
01206     modifiers_clearErrors(ob);
01207 
01208     if(cage_r && cageIndex == -1) {
01209         *cage_r = editmesh_get_derived(em, NULL);
01210     }
01211 
01212     dm = NULL;
01213     md = modifiers_getVirtualModifierList(ob);
01214 
01215     datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode);
01216 
01217     curr = datamasks;
01218     for(i = 0; md; i++, md = md->next, curr = curr->next) {
01219         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
01220 
01221         md->scene= scene;
01222         
01223         if(!editmesh_modifier_is_enabled(scene, md, dm))
01224             continue;
01225 
01226         /* add an orco layer if needed by this modifier */
01227         if(dm && mti->requiredDataMask) {
01228             mask = mti->requiredDataMask(ob, md);
01229             if(mask & CD_MASK_ORCO)
01230                 add_orco_dm(ob, em, dm, orcodm, CD_ORCO);
01231         }
01232 
01233         /* How to apply modifier depends on (a) what we already have as
01234          * a result of previous modifiers (could be a DerivedMesh or just
01235          * deformed vertices) and (b) what type the modifier is.
01236          */
01237 
01238         if(mti->type == eModifierTypeType_OnlyDeform) {
01239             /* No existing verts to deform, need to build them. */
01240             if(!deformedVerts) {
01241                 if(dm) {
01242                     /* Deforming a derived mesh, read the vertex locations
01243                      * out of the mesh and deform them. Once done with this
01244                      * run of deformers verts will be written back.
01245                      */
01246                     numVerts = dm->getNumVerts(dm);
01247                     deformedVerts =
01248                         MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
01249                     dm->getVertCos(dm, deformedVerts);
01250                 } else {
01251                     deformedVerts = editmesh_get_vertex_cos(em, &numVerts);
01252                 }
01253             }
01254 
01255             if (mti->deformVertsEM)
01256                 mti->deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
01257             else mti->deformVerts(md, ob, dm, deformedVerts, numVerts, 0, 0);
01258         } else {
01259             DerivedMesh *ndm;
01260 
01261             /* apply vertex coordinates or build a DerivedMesh as necessary */
01262             if(dm) {
01263                 if(deformedVerts) {
01264                     DerivedMesh *tdm = CDDM_copy(dm);
01265                     if(!(cage_r && dm == *cage_r)) dm->release(dm);
01266                     dm = tdm;
01267 
01268                     CDDM_apply_vert_coords(dm, deformedVerts);
01269                     CDDM_calc_normals(dm);
01270                 } else if(cage_r && dm == *cage_r) {
01271                     /* dm may be changed by this modifier, so we need to copy it
01272                      */
01273                     dm = CDDM_copy(dm);
01274                 }
01275 
01276             } else {
01277                 dm = CDDM_from_editmesh(em, ob->data);
01278 
01279                 if(deformedVerts) {
01280                     CDDM_apply_vert_coords(dm, deformedVerts);
01281                     CDDM_calc_normals(dm);
01282                 }
01283             }
01284 
01285             /* create an orco derivedmesh in parallel */
01286             mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link);
01287             if(mask & CD_MASK_ORCO) {
01288                 if(!orcodm)
01289                     orcodm= create_orco_dm(ob, ob->data, em, CD_ORCO);
01290 
01291                 mask &= ~CD_MASK_ORCO;
01292                 DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX);
01293 
01294                 if (mti->applyModifierEM)
01295                     ndm = mti->applyModifierEM(md, ob, em, orcodm);
01296                 else
01297                     ndm = mti->applyModifier(md, ob, orcodm, 0, 0);
01298 
01299                 if(ndm) {
01300                     /* if the modifier returned a new dm, release the old one */
01301                     if(orcodm && orcodm != ndm) orcodm->release(orcodm);
01302                     orcodm = ndm;
01303                 }
01304             }
01305 
01306             /* set the DerivedMesh to only copy needed data */
01307             mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); /* CD_MASK_ORCO may have been cleared above */
01308 
01309             DM_set_only_copy(dm, mask | CD_MASK_ORIGINDEX);
01310 
01311             if(mask & CD_MASK_ORIGSPACE)
01312                 if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
01313                     DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
01314             
01315             if (mti->applyModifierEM)
01316                 ndm = mti->applyModifierEM(md, ob, em, dm);
01317             else
01318                 ndm = mti->applyModifier(md, ob, dm, 0, 0);
01319 
01320             if (ndm) {
01321                 if(dm && dm != ndm)
01322                     dm->release(dm);
01323 
01324                 dm = ndm;
01325 
01326                 if (deformedVerts) {
01327                     MEM_freeN(deformedVerts);
01328                     deformedVerts = NULL;
01329                 }
01330             }
01331         }
01332 
01333         if(cage_r && i == cageIndex) {
01334             if(dm && deformedVerts) {
01335                 *cage_r = CDDM_copy(dm);
01336                 CDDM_apply_vert_coords(*cage_r, deformedVerts);
01337             } else if(dm) {
01338                 *cage_r = dm;
01339             } else {
01340                 *cage_r =
01341                     editmesh_get_derived(em,
01342                         deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
01343             }
01344         }
01345     }
01346 
01347     BLI_linklist_free(datamasks, NULL);
01348 
01349     /* Yay, we are done. If we have a DerivedMesh and deformed vertices need
01350      * to apply these back onto the DerivedMesh. If we have no DerivedMesh
01351      * then we need to build one.
01352      */
01353     if(dm && deformedVerts) {
01354         *final_r = CDDM_copy(dm);
01355 
01356         if(!(cage_r && dm == *cage_r)) dm->release(dm);
01357 
01358         CDDM_apply_vert_coords(*final_r, deformedVerts);
01359         CDDM_calc_normals(*final_r);
01360     } else if (dm) {
01361         *final_r = dm;
01362     } else if (!deformedVerts && cage_r && *cage_r) {
01363         *final_r = *cage_r;
01364     } else {
01365         *final_r = editmesh_get_derived(em, deformedVerts);
01366         deformedVerts = NULL;
01367     }
01368 
01369     /* add an orco layer if needed */
01370     if(dataMask & CD_MASK_ORCO)
01371         add_orco_dm(ob, em, *final_r, orcodm, CD_ORCO);
01372 
01373     if(orcodm)
01374         orcodm->release(orcodm);
01375 
01376     if(deformedVerts)
01377         MEM_freeN(deformedVerts);
01378 }
01379 
01380 static void clear_mesh_caches(Object *ob)
01381 {
01382     Mesh *me= ob->data;
01383 
01384         /* also serves as signal to remake texspace */
01385     if (ob->bb) {
01386         MEM_freeN(ob->bb);
01387         ob->bb = NULL;
01388     }
01389     if (me->bb) {
01390         MEM_freeN(me->bb);
01391         me->bb = NULL;
01392     }
01393 
01394     freedisplist(&ob->disp);
01395 
01396     if (ob->derivedFinal) {
01397         ob->derivedFinal->needsFree = 1;
01398         ob->derivedFinal->release(ob->derivedFinal);
01399         ob->derivedFinal= NULL;
01400     }
01401     if (ob->derivedDeform) {
01402         ob->derivedDeform->needsFree = 1;
01403         ob->derivedDeform->release(ob->derivedDeform);
01404         ob->derivedDeform= NULL;
01405     }
01406 
01407     if(ob->sculpt) {
01408         object_sculpt_modifiers_changed(ob);
01409     }
01410 }
01411 
01412 static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
01413 {
01414     Object *obact = scene->basact?scene->basact->object:NULL;
01415     int editing = paint_facesel_test(ob) || paint_vertsel_test(ob);/* paint_vertsel_test */
01416     /* weight paint and face select need original indices because of selection buffer drawing */
01417     int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)));
01418 
01419     clear_mesh_caches(ob);
01420 
01421     mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
01422                         &ob->derivedFinal, 0, 1,
01423                         needMapping, dataMask, -1, 1);
01424 
01425     DM_set_object_boundbox (ob, ob->derivedFinal);
01426 
01427     ob->derivedFinal->needsFree = 0;
01428     ob->derivedDeform->needsFree = 0;
01429     ob->lastDataMask = dataMask;
01430 }
01431 
01432 static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask)
01433 {
01434     clear_mesh_caches(obedit);
01435 
01436     if (em->derivedFinal) {
01437         if (em->derivedFinal!=em->derivedCage) {
01438             em->derivedFinal->needsFree = 1;
01439             em->derivedFinal->release(em->derivedFinal);
01440         }
01441         em->derivedFinal = NULL;
01442     }
01443     if (em->derivedCage) {
01444         em->derivedCage->needsFree = 1;
01445         em->derivedCage->release(em->derivedCage);
01446         em->derivedCage = NULL;
01447     }
01448 
01449     editmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask);
01450     DM_set_object_boundbox (obedit, em->derivedFinal);
01451 
01452     em->lastDataMask = dataMask;
01453     em->derivedFinal->needsFree = 0;
01454     em->derivedCage->needsFree = 0;
01455 }
01456 
01457 void makeDerivedMesh(Scene *scene, Object *ob, EditMesh *em, CustomDataMask dataMask)
01458 {
01459     if (em) {
01460         editmesh_build_data(scene, ob, em, dataMask);
01461     } else {
01462         mesh_build_data(scene, ob, dataMask);
01463     }
01464 }
01465 
01466 /***/
01467 
01468 DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dataMask)
01469 {
01470     /* if there's no derived mesh or the last data mask used doesn't include
01471      * the data we need, rebuild the derived mesh
01472      */
01473     if(!ob->derivedFinal || (dataMask & ob->lastDataMask) != dataMask)
01474         mesh_build_data(scene, ob, dataMask);
01475 
01476     return ob->derivedFinal;
01477 }
01478 
01479 DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask dataMask)
01480 {
01481     /* if there's no derived mesh or the last data mask used doesn't include
01482      * the data we need, rebuild the derived mesh
01483      */
01484     if(!ob->derivedDeform || (dataMask & ob->lastDataMask) != dataMask)
01485         mesh_build_data(scene, ob, dataMask);
01486 
01487     return ob->derivedDeform;
01488 }
01489 
01490 DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask dataMask)
01491 {
01492     DerivedMesh *final;
01493     
01494     mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1, 0);
01495 
01496     return final;
01497 }
01498 
01499 DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index)
01500 {
01501     DerivedMesh *final;
01502     
01503     mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index, 0);
01504 
01505     return final;
01506 }
01507 
01508 DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask dataMask)
01509 {
01510     DerivedMesh *final;
01511 
01512     mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1, 0);
01513 
01514     return final;
01515 }
01516 
01517 DerivedMesh *mesh_create_derived_no_deform(Scene *scene, Object *ob, float (*vertCos)[3],
01518                                            CustomDataMask dataMask)
01519 {
01520     DerivedMesh *final;
01521     
01522     mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1, 0);
01523 
01524     return final;
01525 }
01526 
01527 DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*vertCos)[3],
01528                                             CustomDataMask dataMask)
01529 {
01530     DerivedMesh *final;
01531     
01532     mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1, 0);
01533 
01534     return final;
01535 }
01536 
01537 DerivedMesh *mesh_create_derived_physics(Scene *scene, Object *ob, float (*vertCos)[3],
01538                                             CustomDataMask dataMask)
01539 {
01540     DerivedMesh *final;
01541     
01542     mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0);
01543 
01544     return final;
01545 }
01546 
01547 DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
01548                                                   float (*vertCos)[3],
01549                                                   CustomDataMask dataMask)
01550 {
01551     DerivedMesh *final;
01552 
01553     mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1, 0);
01554 
01555     return final;
01556 }
01557 
01558 /***/
01559 
01560 DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, EditMesh *em, DerivedMesh **final_r,
01561                                                  CustomDataMask dataMask)
01562 {
01563     /* if there's no derived mesh or the last data mask used doesn't include
01564      * the data we need, rebuild the derived mesh
01565      */
01566     if(!em->derivedCage ||
01567        (em->lastDataMask & dataMask) != dataMask)
01568         editmesh_build_data(scene, obedit, em, dataMask);
01569 
01570     *final_r = em->derivedFinal;
01571     return em->derivedCage;
01572 }
01573 
01574 DerivedMesh *editmesh_get_derived_cage(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask)
01575 {
01576     /* if there's no derived mesh or the last data mask used doesn't include
01577      * the data we need, rebuild the derived mesh
01578      */
01579     if(!em->derivedCage ||
01580        (em->lastDataMask & dataMask) != dataMask)
01581         editmesh_build_data(scene, obedit, em, dataMask);
01582 
01583     return em->derivedCage;
01584 }
01585 
01586 DerivedMesh *editmesh_get_derived_base(Object *UNUSED(obedit), EditMesh *em)
01587 {
01588     return editmesh_get_derived(em, NULL);
01589 }
01590 
01591 
01592 /* ********* For those who don't grasp derived stuff! (ton) :) *************** */
01593 
01594 static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
01595 {
01596     float *vec = userData;
01597     
01598     vec+= 6*index;
01599 
01600     /* check if we've been here before (normal should not be 0) */
01601     if(vec[3] || vec[4] || vec[5]) return;
01602 
01603     copy_v3_v3(vec, co);
01604     vec+= 3;
01605     if(no_f) {
01606         copy_v3_v3(vec, no_f);
01607     }
01608     else {
01609         normal_short_to_float_v3(vec, no_s);
01610     }
01611 }
01612 
01613 /* always returns original amount me->totvert of vertices and normals, but fully deformed and subsurfered */
01614 /* this is needed for all code using vertexgroups (no subsurf support) */
01615 /* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
01616 /* in use now by vertex/weight paint and particle generating */
01617 
01618 float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
01619 {
01620     Mesh *me= ob->data;
01621     DerivedMesh *dm;
01622     float *vertexcosnos;
01623     
01624     /* lets prevent crashing... */
01625     if(ob->type!=OB_MESH || me->totvert==0)
01626         return NULL;
01627     
01628     dm= mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
01629     vertexcosnos= MEM_callocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
01630     
01631     if(dm->foreachMappedVert) {
01632         dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
01633     }
01634     else {
01635         float *fp= vertexcosnos;
01636         int a;
01637         
01638         for(a=0; a< me->totvert; a++, fp+=6) {
01639             dm->getVertCo(dm, a, fp);
01640             dm->getVertNo(dm, a, fp+3);
01641         }
01642     }
01643     
01644     dm->release(dm);
01645     return vertexcosnos;
01646 }
01647 
01648 /* ******************* GLSL ******************** */
01649 
01650 typedef struct
01651 {
01652     float * precomputedFaceNormals;
01653     MTFace * mtface;    // texture coordinates
01654     MFace * mface;      // indices
01655     MVert * mvert;      // vertices & normals
01656     float (*orco)[3];
01657     float (*tangent)[4];    // destination
01658     int numFaces;
01659 
01660 } SGLSLMeshToTangent;
01661 
01662 // interface
01663 #include "mikktspace.h"
01664 
01665 static int GetNumFaces(const SMikkTSpaceContext * pContext)
01666 {
01667     SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
01668     return pMesh->numFaces;
01669 }
01670 
01671 static int GetNumVertsOfFace(const SMikkTSpaceContext * pContext, const int face_num)
01672 {
01673     SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
01674     return pMesh->mface[face_num].v4!=0 ? 4 : 3;
01675 }
01676 
01677 static void GetPosition(const SMikkTSpaceContext * pContext, float fPos[], const int face_num, const int vert_index)
01678 {
01679     //assert(vert_index>=0 && vert_index<4);
01680     SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
01681     const float *co= pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].co;
01682     copy_v3_v3(fPos, co);
01683 }
01684 
01685 static void GetTextureCoordinate(const SMikkTSpaceContext * pContext, float fUV[], const int face_num, const int vert_index)
01686 {
01687     //assert(vert_index>=0 && vert_index<4);
01688     SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
01689 
01690     if(pMesh->mtface!=NULL) {
01691         float * uv = pMesh->mtface[face_num].uv[vert_index];
01692         fUV[0]=uv[0]; fUV[1]=uv[1];
01693     }
01694     else {
01695         const float *orco= pMesh->orco[(&pMesh->mface[face_num].v1)[vert_index]];
01696         map_to_sphere( &fUV[0], &fUV[1], orco[0], orco[1], orco[2]);
01697     }
01698 }
01699 
01700 static void GetNormal(const SMikkTSpaceContext * pContext, float fNorm[], const int face_num, const int vert_index)
01701 {
01702     //assert(vert_index>=0 && vert_index<4);
01703     SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
01704 
01705     const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH);
01706     if(!smoothnormal) { // flat
01707         if(pMesh->precomputedFaceNormals) {
01708             copy_v3_v3(fNorm, &pMesh->precomputedFaceNormals[3*face_num]);
01709         }
01710         else {
01711             MFace *mf= &pMesh->mface[face_num];
01712             float *p0= pMesh->mvert[mf->v1].co;
01713             float *p1= pMesh->mvert[mf->v2].co;
01714             float *p2= pMesh->mvert[mf->v3].co;
01715 
01716             if(mf->v4) {
01717                 float *p3 = pMesh->mvert[mf->v4].co;
01718                 normal_quad_v3(fNorm, p0, p1, p2, p3);
01719             }
01720             else {
01721                 normal_tri_v3(fNorm, p0, p1, p2);
01722             }
01723         }
01724     }
01725     else {
01726         const short *no= pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].no;
01727         normal_short_to_float_v3(fNorm, no);
01728     }
01729 }
01730 static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert)
01731 {
01732     //assert(vert_index>=0 && vert_index<4);
01733     SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
01734     float * pRes = pMesh->tangent[4*face_num+iVert];
01735     copy_v3_v3(pRes, fvTangent);
01736     pRes[3]=fSign;
01737 }
01738 
01739 
01740 void DM_add_tangent_layer(DerivedMesh *dm)
01741 {
01742     /* mesh vars */
01743     MTFace *mtface, *tf;
01744     MFace *mface, *mf;
01745     MVert *mvert, *v1, *v2, *v3, *v4;
01746     MemArena *arena= NULL;
01747     VertexTangent **vtangents= NULL;
01748     float (*orco)[3]= NULL, (*tangent)[4];
01749     float *uv1, *uv2, *uv3, *uv4, *vtang;
01750     float fno[3], tang[3], uv[4][2];
01751     int i, j, len, mf_vi[4], totvert, totface, iCalcNewMethod;
01752     float *nors;
01753 
01754     if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
01755         return;
01756 
01757     nors = dm->getFaceDataArray(dm, CD_NORMAL);
01758 
01759     /* check we have all the needed layers */
01760     totvert= dm->getNumVerts(dm);
01761     totface= dm->getNumFaces(dm);
01762 
01763     mvert= dm->getVertArray(dm);
01764     mface= dm->getFaceArray(dm);
01765     mtface= dm->getFaceDataArray(dm, CD_MTFACE);
01766 
01767     if(!mtface) {
01768         orco= dm->getVertDataArray(dm, CD_ORCO);
01769         if(!orco)
01770             return;
01771     }
01772     
01773     /* create tangent layer */
01774     DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
01775     tangent= DM_get_face_data_layer(dm, CD_TANGENT);
01776     
01777     /* allocate some space */
01778     arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "tangent layer arena");
01779     BLI_memarena_use_calloc(arena);
01780     vtangents= MEM_callocN(sizeof(VertexTangent*)*totvert, "VertexTangent");
01781 
01782     // new computation method
01783     iCalcNewMethod = 1;
01784     if(iCalcNewMethod != 0) {
01785         SGLSLMeshToTangent mesh2tangent= {0};
01786         SMikkTSpaceContext sContext= {0};
01787         SMikkTSpaceInterface sInterface= {0};
01788 
01789         mesh2tangent.precomputedFaceNormals = nors;
01790         mesh2tangent.mtface = mtface;
01791         mesh2tangent.mface = mface;
01792         mesh2tangent.mvert = mvert;
01793         mesh2tangent.orco = orco;
01794         mesh2tangent.tangent = tangent;
01795         mesh2tangent.numFaces = totface;
01796 
01797         sContext.m_pUserData = &mesh2tangent;
01798         sContext.m_pInterface = &sInterface;
01799         sInterface.m_getNumFaces = GetNumFaces;
01800         sInterface.m_getNumVerticesOfFace = GetNumVertsOfFace;
01801         sInterface.m_getPosition = GetPosition;
01802         sInterface.m_getTexCoord = GetTextureCoordinate;
01803         sInterface.m_getNormal = GetNormal;
01804         sInterface.m_setTSpaceBasic = SetTSpace;
01805 
01806         // 0 if failed
01807         iCalcNewMethod = genTangSpaceDefault(&sContext);
01808     }
01809 
01810     if(!iCalcNewMethod) {
01811         /* sum tangents at connected vertices */
01812         for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) {
01813             v1= &mvert[mf->v1];
01814             v2= &mvert[mf->v2];
01815             v3= &mvert[mf->v3];
01816 
01817             if (mf->v4) {
01818                 v4= &mvert[mf->v4];
01819                 normal_quad_v3( fno,v4->co, v3->co, v2->co, v1->co);
01820             }
01821             else {
01822                 v4= NULL;
01823                 normal_tri_v3( fno,v3->co, v2->co, v1->co);
01824             }
01825         
01826             if(mtface) {
01827                 uv1= tf->uv[0];
01828                 uv2= tf->uv[1];
01829                 uv3= tf->uv[2];
01830                 uv4= tf->uv[3];
01831             }
01832             else {
01833                 uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
01834                 map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]);
01835                 map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]);
01836                 map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]);
01837                 if(v4)
01838                     map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]);
01839             }
01840         
01841             tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang);
01842             sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
01843             sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2);
01844             sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
01845         
01846             if(mf->v4) {
01847                 v4= &mvert[mf->v4];
01848             
01849                 tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang);
01850                 sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
01851                 sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
01852                 sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4);
01853             }
01854         }
01855     
01856         /* write tangent to layer */
01857         for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) {
01858             len= (mf->v4)? 4 : 3; 
01859 
01860             if(mtface == NULL) {
01861                 map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]);
01862                 map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]);
01863                 map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]);
01864                 if(len==4)
01865                     map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]);
01866             }
01867         
01868             mf_vi[0]= mf->v1;
01869             mf_vi[1]= mf->v2;
01870             mf_vi[2]= mf->v3;
01871             mf_vi[3]= mf->v4;
01872         
01873             for(j=0; j<len; j++) {
01874                 vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]);
01875                 normalize_v3_v3(tangent[j], vtang);
01876                 ((float *) tangent[j])[3]=1.0f;
01877             }
01878         }
01879     }
01880     
01881     BLI_memarena_free(arena);
01882     MEM_freeN(vtangents);
01883 }
01884 
01885 void DM_calc_auto_bump_scale(DerivedMesh *dm)
01886 {
01887     /* int totvert= dm->getNumVerts(dm); */ /* UNUSED */
01888     int totface= dm->getNumFaces(dm);
01889 
01890     MVert * mvert = dm->getVertArray(dm);
01891     MFace * mface = dm->getFaceArray(dm);
01892     MTFace * mtface = dm->getFaceDataArray(dm, CD_MTFACE);
01893 
01894     if(mtface)
01895     {
01896         double dsum = 0.0;
01897         int nr_accumulated = 0;
01898         int f;
01899 
01900         for ( f=0; f<totface; f++ )
01901         {
01902             {
01903                 float * verts[4], * tex_coords[4];
01904                 const int nr_verts = mface[f].v4!=0 ? 4 : 3;
01905                 int i, is_degenerate;
01906 
01907                 verts[0]=mvert[mface[f].v1].co; verts[1]=mvert[mface[f].v2].co; verts[2]=mvert[mface[f].v3].co;
01908                 tex_coords[0]=mtface[f].uv[0]; tex_coords[1]=mtface[f].uv[1]; tex_coords[2]=mtface[f].uv[2];
01909                 if(nr_verts==4)
01910                 {
01911                     verts[3]=mvert[mface[f].v4].co;
01912                     tex_coords[3]=mtface[f].uv[3];
01913                 }
01914 
01915                 // discard degenerate faces
01916                 is_degenerate = 0;
01917                 if( equals_v3v3(verts[0], verts[1]) || equals_v3v3(verts[0], verts[2]) || equals_v3v3(verts[1], verts[2]) ||
01918                     equals_v2v2(tex_coords[0], tex_coords[1]) || equals_v2v2(tex_coords[0], tex_coords[2]) || equals_v2v2(tex_coords[1], tex_coords[2]) )
01919                 {
01920                     is_degenerate = 1;
01921                 }
01922 
01923                 // verify last vertex as well if this is a quad
01924                 if ( is_degenerate==0 && nr_verts==4 )
01925                 {
01926                     if( equals_v3v3(verts[3], verts[0]) || equals_v3v3(verts[3], verts[1]) || equals_v3v3(verts[3], verts[2]) ||
01927                         equals_v2v2(tex_coords[3], tex_coords[0]) || equals_v2v2(tex_coords[3], tex_coords[1]) || equals_v2v2(tex_coords[3], tex_coords[2]) )
01928                     {
01929                         is_degenerate = 1;
01930                     }
01931 
01932                     // verify the winding is consistent
01933                     if ( is_degenerate==0 )
01934                     {
01935                         float prev_edge[2];
01936                         int is_signed = 0;
01937                         sub_v2_v2v2(prev_edge, tex_coords[0], tex_coords[3]);
01938 
01939                         i = 0;
01940                         while ( is_degenerate==0 && i<4 )
01941                         {
01942                             float cur_edge[2], signed_area;
01943                             sub_v2_v2v2(cur_edge, tex_coords[(i+1)&0x3], tex_coords[i]);
01944                             signed_area = prev_edge[0]*cur_edge[1] - prev_edge[1]*cur_edge[0];
01945                             if ( i==0 ) is_signed = signed_area<0.0f ? 1 : 0;
01946                             else if((is_signed!=0)!=(signed_area<0.0f)) is_degenerate=1;
01947 
01948                             if ( is_degenerate==0 )
01949                             {
01950                                 copy_v2_v2(prev_edge, cur_edge);
01951                                 ++i;
01952                             }
01953                         }
01954                     }
01955                 }
01956 
01957                 // proceed if not a degenerate face
01958                 if ( is_degenerate==0 )
01959                 {
01960                     int nr_tris_to_pile=0;
01961                     // quads split at shortest diagonal
01962                     int offs = 0;       // initial triangulation is 0,1,2 and 0, 2, 3
01963                     if ( nr_verts==4 )
01964                     {
01965                         float pos_len_diag0, pos_len_diag1;
01966                         float vtmp[3];
01967                         sub_v3_v3v3(vtmp, verts[2], verts[0]);
01968                         pos_len_diag0 = dot_v3v3(vtmp, vtmp);
01969                         sub_v3_v3v3(vtmp, verts[3], verts[1]);
01970                         pos_len_diag1 = dot_v3v3(vtmp, vtmp);
01971 
01972                         if(pos_len_diag1<pos_len_diag0)
01973                             offs=1;     // alter split
01974                         else if(pos_len_diag0==pos_len_diag1)       // do UV check instead
01975                         {
01976                             float tex_len_diag0, tex_len_diag1;
01977 
01978                             sub_v2_v2v2(vtmp, tex_coords[2], tex_coords[0]);
01979                             tex_len_diag0 = dot_v2v2(vtmp, vtmp);
01980                             sub_v2_v2v2(vtmp, tex_coords[3], tex_coords[1]);
01981                             tex_len_diag1 = dot_v2v2(vtmp, vtmp);
01982 
01983                             if(tex_len_diag1<tex_len_diag0)
01984                             {
01985                                 offs=1;     // alter split
01986                             }
01987                         }
01988                     }
01989                     nr_tris_to_pile = nr_verts-2 ;
01990                     if ( nr_tris_to_pile==1 || nr_tris_to_pile==2 )
01991                     {
01992                         const int indices[] = {offs+0, offs+1, offs+2, offs+0, offs+2, (offs+3)&0x3 };
01993                         int t;
01994                         for ( t=0; t<nr_tris_to_pile; t++ )
01995                         {
01996                             float f2x_area_uv;
01997                             float * p0 = verts[indices[t*3+0]];
01998                             float * p1 = verts[indices[t*3+1]];
01999                             float * p2 = verts[indices[t*3+2]];
02000 
02001                             float edge_t0[2], edge_t1[2];
02002                             sub_v2_v2v2(edge_t0, tex_coords[indices[t*3+1]], tex_coords[indices[t*3+0]]);
02003                             sub_v2_v2v2(edge_t1, tex_coords[indices[t*3+2]], tex_coords[indices[t*3+0]]);
02004 
02005                             f2x_area_uv = fabsf(edge_t0[0]*edge_t1[1] - edge_t0[1]*edge_t1[0]);
02006                             if ( f2x_area_uv>FLT_EPSILON )
02007                             {
02008                                 float norm[3], v0[3], v1[3], f2x_surf_area, fsurf_ratio;
02009                                 sub_v3_v3v3(v0, p1, p0);
02010                                 sub_v3_v3v3(v1, p2, p0);
02011                                 cross_v3_v3v3(norm, v0, v1);
02012 
02013                                 f2x_surf_area = len_v3(norm);
02014                                 fsurf_ratio = f2x_surf_area/f2x_area_uv;    // tri area divided by texture area
02015 
02016                                 ++nr_accumulated;
02017                                 dsum += (double)(fsurf_ratio);
02018                             }
02019                         }
02020                     }
02021                 }
02022             }
02023         }
02024 
02025         // finalize
02026         {
02027             const float avg_area_ratio = (nr_accumulated>0) ? ((float)(dsum / nr_accumulated)) : 1.0f;
02028             const float use_as_render_bump_scale = sqrtf(avg_area_ratio);       // use width of average surface ratio as your bump scale
02029             dm->auto_bump_scale = use_as_render_bump_scale;
02030         }
02031     }
02032     else
02033     {
02034         dm->auto_bump_scale = 1.0f;
02035     }
02036 }
02037 
02038 void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
02039 {
02040     CustomData *vdata, *fdata, *tfdata = NULL;
02041     int a, b, layer;
02042 
02043     /* From the layers requested by the GLSL shader, figure out which ones are
02044      * actually available for this derivedmesh, and retrieve the pointers */
02045 
02046     memset(attribs, 0, sizeof(DMVertexAttribs));
02047 
02048     vdata = &dm->vertData;
02049     fdata = &dm->faceData;
02050 
02051     /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we
02052      * can use offsets instead */
02053     if(dm->type == DM_TYPE_EDITMESH)
02054         tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata;
02055     else
02056         tfdata = fdata;
02057 
02058     /* calc auto bump scale if necessary */
02059     if(dm->auto_bump_scale<=0.0f)
02060         DM_calc_auto_bump_scale(dm);
02061 
02062     /* add a tangent layer if necessary */
02063     for(b = 0; b < gattribs->totlayer; b++)
02064         if(gattribs->layer[b].type == CD_TANGENT)
02065             if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1)
02066                 DM_add_tangent_layer(dm);
02067 
02068     for(b = 0; b < gattribs->totlayer; b++) {
02069         if(gattribs->layer[b].type == CD_MTFACE) {
02070             /* uv coordinates */
02071             if(gattribs->layer[b].name[0])
02072                 layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
02073                     gattribs->layer[b].name);
02074             else
02075                 layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
02076 
02077             if(layer != -1) {
02078                 a = attribs->tottface++;
02079 
02080                 attribs->tface[a].array = tfdata->layers[layer].data;
02081                 attribs->tface[a].emOffset = tfdata->layers[layer].offset;
02082                 attribs->tface[a].glIndex = gattribs->layer[b].glindex;
02083                 attribs->tface[a].glTexco = gattribs->layer[b].gltexco;
02084             }
02085         }
02086         else if(gattribs->layer[b].type == CD_MCOL) {
02087             /* vertex colors */
02088             if(gattribs->layer[b].name[0])
02089                 layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
02090                     gattribs->layer[b].name);
02091             else
02092                 layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
02093 
02094             if(layer != -1) {
02095                 a = attribs->totmcol++;
02096 
02097                 attribs->mcol[a].array = tfdata->layers[layer].data;
02098                 attribs->mcol[a].emOffset = tfdata->layers[layer].offset;
02099                 attribs->mcol[a].glIndex = gattribs->layer[b].glindex;
02100             }
02101         }
02102         else if(gattribs->layer[b].type == CD_TANGENT) {
02103             /* tangents */
02104             layer = CustomData_get_layer_index(fdata, CD_TANGENT);
02105 
02106             if(layer != -1) {
02107                 attribs->tottang = 1;
02108 
02109                 attribs->tang.array = fdata->layers[layer].data;
02110                 attribs->tang.emOffset = fdata->layers[layer].offset;
02111                 attribs->tang.glIndex = gattribs->layer[b].glindex;
02112             }
02113         }
02114         else if(gattribs->layer[b].type == CD_ORCO) {
02115             /* original coordinates */
02116             layer = CustomData_get_layer_index(vdata, CD_ORCO);
02117 
02118             if(layer != -1) {
02119                 attribs->totorco = 1;
02120 
02121                 attribs->orco.array = vdata->layers[layer].data;
02122                 attribs->orco.emOffset = vdata->layers[layer].offset;
02123                 attribs->orco.glIndex = gattribs->layer[b].glindex;
02124                 attribs->orco.glTexco = gattribs->layer[b].gltexco;
02125             }
02126         }
02127     }
02128 }
02129 
02130 /* Set object's bounding box based on DerivedMesh min/max data */
02131 void DM_set_object_boundbox(Object *ob, DerivedMesh *dm)
02132 {
02133     float min[3], max[3];
02134 
02135     INIT_MINMAX(min, max);
02136 
02137     dm->getMinMax(dm, min, max);
02138 
02139     if(!ob->bb)
02140         ob->bb= MEM_callocN(sizeof(BoundBox), "DM-BoundBox");
02141 
02142     boundbox_set_from_min_max(ob->bb, min, max);
02143 }
02144 
02145 /* --- NAVMESH (begin) --- */
02146 #ifdef WITH_GAMEENGINE
02147 
02148 BM_INLINE int navmesh_bit(int a, int b)
02149 {
02150     return (a & (1 << b)) >> b;
02151 }
02152 
02153 BM_INLINE void navmesh_intToCol(int i, float col[3])
02154 {
02155     int r = navmesh_bit(i, 0) + navmesh_bit(i, 3) * 2 + 1;
02156     int g = navmesh_bit(i, 1) + navmesh_bit(i, 4) * 2 + 1;
02157     int b = navmesh_bit(i, 2) + navmesh_bit(i, 5) * 2 + 1;
02158     col[0] = 1 - r*63.0f/255.0f;
02159     col[1] = 1 - g*63.0f/255.0f;
02160     col[2] = 1 - b*63.0f/255.0f;
02161 }
02162 
02163 static void navmesh_drawColored(DerivedMesh *dm)
02164 {
02165     int a, glmode;
02166     MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT);
02167     MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE);
02168     int *polygonIdx = (int *)CustomData_get_layer(&dm->faceData, CD_RECAST);
02169     float col[3];
02170 
02171     if (!polygonIdx)
02172         return;
02173 
02174     /*
02175     //UI_ThemeColor(TH_WIRE);
02176     glDisable(GL_LIGHTING);
02177     glLineWidth(2.0);
02178     dm->drawEdges(dm, 0, 1);
02179     glLineWidth(1.0);
02180     glEnable(GL_LIGHTING);*/
02181 
02182     glDisable(GL_LIGHTING);
02183     /*  if(GPU_buffer_legacy(dm) ) */ { /* TODO - VBO draw code, not high priority - campbell */
02184         DEBUG_VBO( "Using legacy code. drawNavMeshColored\n" );
02185         //glShadeModel(GL_SMOOTH);
02186         glBegin(glmode = GL_QUADS);
02187         for(a = 0; a < dm->numFaceData; a++, mface++) {
02188             int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
02189             int pi = polygonIdx[a];
02190             if (pi <= 0) {
02191                 zero_v3(col);
02192             }
02193             else {
02194                 navmesh_intToCol(pi, col);
02195             }
02196 
02197             if(new_glmode != glmode) {
02198                 glEnd();
02199                 glBegin(glmode = new_glmode);
02200             }
02201             glColor3fv(col);
02202             glVertex3fv(mvert[mface->v1].co);
02203             glVertex3fv(mvert[mface->v2].co);
02204             glVertex3fv(mvert[mface->v3].co);
02205             if(mface->v4) {
02206                 glVertex3fv(mvert[mface->v4].co);
02207             }
02208         }
02209         glEnd();
02210     }
02211     glEnable(GL_LIGHTING);
02212 }
02213 
02214 static void navmesh_DM_drawFacesTex(DerivedMesh *dm,
02215             int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr),
02216             int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
02217             void *userData)
02218 {
02219     (void) setDrawOptions;
02220     (void) compareDrawOptions;
02221     (void) userData;
02222 
02223     navmesh_drawColored(dm);
02224 }
02225 
02226 static void navmesh_DM_drawFacesSolid(DerivedMesh *dm,
02227                                       float (*partial_redraw_planes)[4],
02228                                       int UNUSED(fast), int (*setMaterial)(int, void *attribs))
02229 {
02230     (void) partial_redraw_planes;
02231     (void) setMaterial;
02232 
02233     //drawFacesSolid_original(dm, partial_redraw_planes, fast, setMaterial);
02234     navmesh_drawColored(dm);
02235 }
02236 
02237 static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm)
02238 {
02239     DerivedMesh *result;
02240     int maxFaces = dm->getNumFaces(dm);
02241     int *recastData;
02242     int vertsPerPoly=0, nverts=0, ndtris=0, npolys=0;
02243     float* verts=NULL;
02244     unsigned short *dtris=NULL, *dmeshes=NULL, *polys=NULL;
02245     int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL;
02246     int res;
02247 
02248     result = CDDM_copy(dm);
02249     if (!CustomData_has_layer(&result->faceData, CD_RECAST)) {
02250         int *sourceRecastData = (int*)CustomData_get_layer(&dm->faceData, CD_RECAST);
02251         if (sourceRecastData) {
02252             CustomData_add_layer_named(&result->faceData, CD_RECAST, CD_DUPLICATE,
02253                                        sourceRecastData, maxFaces, "recastData");
02254         }
02255     }
02256     recastData = (int*)CustomData_get_layer(&result->faceData, CD_RECAST);
02257 
02258     /* note: This is not good design! - really should not be doing this */
02259     result->drawFacesTex =  navmesh_DM_drawFacesTex;
02260     result->drawFacesSolid = navmesh_DM_drawFacesSolid;
02261 
02262 
02263     /* process mesh */
02264     res  = buildNavMeshDataByDerivedMesh(dm, &vertsPerPoly, &nverts, &verts, &ndtris, &dtris,
02265                                          &npolys, &dmeshes, &polys, &dtrisToPolysMap, &dtrisToTrisMap,
02266                                          &trisToFacesMap);
02267     if (res) {
02268         size_t polyIdx;
02269 
02270         /* invalidate concave polygon */
02271         for (polyIdx=0; polyIdx<(size_t)npolys; polyIdx++) {
02272             unsigned short* poly = &polys[polyIdx*2*vertsPerPoly];
02273             if (!polyIsConvex(poly, vertsPerPoly, verts)) {
02274                 /* set negative polygon idx to all faces */
02275                 unsigned short *dmesh = &dmeshes[4*polyIdx];
02276                 unsigned short tbase = dmesh[2];
02277                 unsigned short tnum = dmesh[3];
02278                 unsigned short ti;
02279 
02280                 for (ti=0; ti<tnum; ti++) {
02281                     unsigned short triidx = dtrisToTrisMap[tbase+ti];
02282                     unsigned short faceidx = trisToFacesMap[triidx];
02283                     if (recastData[faceidx] > 0) {
02284                         recastData[faceidx] = -recastData[faceidx];
02285                     }
02286                 }
02287             }
02288         }
02289     }
02290     else {
02291         printf("Error during creation polygon infos\n");
02292     }
02293 
02294     /* clean up */
02295     if (verts!=NULL)
02296         MEM_freeN(verts);
02297     if (dtris!=NULL)
02298         MEM_freeN(dtris);
02299     if (dmeshes!=NULL)
02300         MEM_freeN(dmeshes);
02301     if (polys!=NULL)
02302         MEM_freeN(polys);
02303     if (dtrisToPolysMap!=NULL)
02304         MEM_freeN(dtrisToPolysMap);
02305     if (dtrisToTrisMap!=NULL)
02306         MEM_freeN(dtrisToTrisMap);
02307     if (trisToFacesMap!=NULL)
02308         MEM_freeN(trisToFacesMap);
02309 
02310     return result;
02311 }
02312 
02313 #endif /* WITH_GAMEENGINE */
02314 
02315 /* --- NAVMESH (end) --- */