~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to source/blender/blenkernel/intern/modifier.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2007-05-17 11:47:59 UTC
  • mfrom: (1.2.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20070517114759-yp4ybrnhp2u7pk66
Tags: 2.44-1
* New upstream release.
* Drop debian/patches/01_64bits_stupidity, not needed anymore: as of this
  version blender is 64 bits safe again. Adjust README.Debian accordingly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
* $Id: modifier.c,v 1.93 2007/01/29 16:28:10 artificer Exp $
 
2
* $Id: modifier.c,v 1.103 2007/04/30 19:20:42 ianwill Exp $
3
3
*
4
4
* ***** BEGIN GPL LICENSE BLOCK *****
5
5
*
563
563
        /* default to 2 duplicates distributed along the x-axis by an
564
564
           offset of 1 object-width
565
565
        */
566
 
        amd->curve_ob = amd->offset_ob = NULL;
 
566
        amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
567
567
        amd->count = 2;
568
568
        amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
569
569
        amd->scale[0] = 1;
580
580
        ArrayModifierData *amd = (ArrayModifierData*) md;
581
581
        ArrayModifierData *tamd = (ArrayModifierData*) target;
582
582
 
 
583
        tamd->start_cap = amd->start_cap;
 
584
        tamd->end_cap = amd->end_cap;
583
585
        tamd->curve_ob = amd->curve_ob;
584
586
        tamd->offset_ob = amd->offset_ob;
585
587
        tamd->count = amd->count;
599
601
{
600
602
        ArrayModifierData *amd = (ArrayModifierData*) md;
601
603
 
 
604
        walk(userData, ob, &amd->start_cap);
 
605
        walk(userData, ob, &amd->end_cap);
602
606
        walk(userData, ob, &amd->curve_ob);
603
607
        walk(userData, ob, &amd->offset_ob);
604
608
}
608
612
{
609
613
        ArrayModifierData *amd = (ArrayModifierData*) md;
610
614
 
 
615
        if (amd->start_cap) {
 
616
                DagNode *curNode = dag_get_node(forest, amd->start_cap);
 
617
 
 
618
                dag_add_relation(forest, curNode, obNode,
 
619
                                 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
 
620
        }
 
621
        if (amd->end_cap) {
 
622
                DagNode *curNode = dag_get_node(forest, amd->end_cap);
 
623
 
 
624
                dag_add_relation(forest, curNode, obNode,
 
625
                                 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
 
626
        }
611
627
        if (amd->curve_ob) {
612
628
                DagNode *curNode = dag_get_node(forest, amd->curve_ob);
613
629
 
654
670
        short merge_final;
655
671
} IndexMapEntry;
656
672
 
657
 
static int calc_mapping(IndexMapEntry *indexMap, int oldVert, int copy)
 
673
/* indexMap - an array of IndexMap entries
 
674
 * oldIndex - the old index to map
 
675
 * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
 
676
 */
 
677
static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
658
678
{
659
 
        int newVert;
660
 
 
661
 
        if(indexMap[oldVert].merge < 0) {
 
679
        if(indexMap[oldIndex].merge < 0) {
662
680
                /* vert wasn't merged, so use copy of this vert */
663
 
                newVert = indexMap[oldVert].new + copy + 1;
664
 
        } else if(indexMap[oldVert].merge == oldVert) {
 
681
                return indexMap[oldIndex].new + copyNum;
 
682
        } else if(indexMap[oldIndex].merge == oldIndex) {
665
683
                /* vert was merged with itself */
666
 
                newVert = indexMap[oldVert].new;
 
684
                return indexMap[oldIndex].new;
667
685
        } else {
668
686
                /* vert was merged with another vert */
669
 
                int mergeVert = indexMap[oldVert].merge;
670
 
 
671
687
                /* follow the chain of merges to the end, or until we've passed
672
688
                 * a number of vertices equal to the copy number
673
689
                 */
674
 
                while(copy > 0 && indexMap[mergeVert].merge >= 0
675
 
                      && indexMap[mergeVert].merge != mergeVert) {
676
 
                        mergeVert = indexMap[mergeVert].merge;
677
 
                        --copy;
678
 
                }
679
 
 
680
 
                if(indexMap[mergeVert].merge == mergeVert)
681
 
                        /* vert merged with vert that was merged with itself */
682
 
                        newVert = indexMap[mergeVert].new;
 
690
                if(copyNum <= 0)
 
691
                        return indexMap[oldIndex].new;
683
692
                else
684
 
                        /* use copy of the vert this vert was merged with */
685
 
                        newVert = indexMap[mergeVert].new + copy;
 
693
                        return calc_mapping(indexMap, indexMap[oldIndex].merge,
 
694
                                            copyNum - 1);
686
695
        }
687
 
 
688
 
        return newVert;
689
696
}
690
697
 
691
698
static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
701
708
        int count = amd->count;
702
709
        int numVerts, numEdges, numFaces;
703
710
        int maxVerts, maxEdges, maxFaces;
704
 
        DerivedMesh *result;
 
711
        int finalVerts, finalEdges, finalFaces;
 
712
        DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
705
713
        MVert *mvert, *src_mvert;
706
714
        MEdge *medge;
707
715
        MFace *mface;
710
718
 
711
719
        EdgeHash *edges;
712
720
 
 
721
        /* need to avoid infinite recursion here */
 
722
        if(amd->start_cap && amd->start_cap != ob)
 
723
                start_cap = mesh_get_derived_final(amd->start_cap, CD_MASK_MESH);
 
724
        if(amd->end_cap && amd->end_cap != ob)
 
725
                end_cap = mesh_get_derived_final(amd->end_cap, CD_MASK_MESH);
 
726
 
713
727
        MTC_Mat4One(offset);
714
728
 
715
729
        indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
772
786
        if(count < 1)
773
787
                count = 1;
774
788
 
775
 
        /* allocate memory for count duplicates (including original) */
776
 
        result = CDDM_from_template(dm, dm->getNumVerts(dm) * count,
777
 
                                    dm->getNumEdges(dm) * count,
778
 
                                    dm->getNumFaces(dm) * count);
 
789
        /* allocate memory for count duplicates (including original) plus
 
790
         * start and end caps
 
791
         */
 
792
        finalVerts = dm->getNumVerts(dm) * count;
 
793
        finalEdges = dm->getNumEdges(dm) * count;
 
794
        finalFaces = dm->getNumFaces(dm) * count;
 
795
        if(start_cap) {
 
796
                finalVerts += start_cap->getNumVerts(start_cap);
 
797
                finalEdges += start_cap->getNumEdges(start_cap);
 
798
                finalFaces += start_cap->getNumFaces(start_cap);
 
799
        }
 
800
        if(end_cap) {
 
801
                finalVerts += end_cap->getNumVerts(end_cap);
 
802
                finalEdges += end_cap->getNumEdges(end_cap);
 
803
                finalFaces += end_cap->getNumFaces(end_cap);
 
804
        }
 
805
        result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
779
806
 
780
807
        /* calculate the offset matrix of the final copy (for merging) */ 
781
808
        MTC_Mat4One(final_offset);
879
906
                 */
880
907
                if(indexMap[inMED.v1].merge_final) {
881
908
                        med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
882
 
                                              count - 2);
 
909
                                              count - 1);
883
910
                }
884
911
                if(indexMap[inMED.v2].merge_final) {
885
912
                        med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
886
 
                                              count - 2);
 
913
                                              count - 1);
887
914
                }
888
915
 
889
916
                if (initFlags) {
898
925
                        BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
899
926
                }
900
927
 
901
 
                for(j=0; j < count - 1; j++)
 
928
                for(j = 1; j < count; j++)
902
929
                {
903
930
                        vert1 = calc_mapping(indexMap, inMED.v1, j);
904
931
                        vert2 = calc_mapping(indexMap, inMED.v2, j);
918
945
                }
919
946
        }
920
947
 
921
 
        /* don't need the hashtable any more */
922
 
        BLI_edgehash_free(edges, NULL);
923
 
 
924
948
        maxFaces = dm->getNumFaces(dm);
925
949
        mface = CDDM_get_faces(result);
926
950
        for (i=0; i < maxFaces; i++) {
942
966
                 * merge targets, calculate that final copy
943
967
                 */
944
968
                if(indexMap[inMF.v1].merge_final)
945
 
                        mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-2);
 
969
                        mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
946
970
                if(indexMap[inMF.v2].merge_final)
947
 
                        mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-2);
 
971
                        mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
948
972
                if(indexMap[inMF.v3].merge_final)
949
 
                        mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-2);
 
973
                        mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
950
974
                if(inMF.v4 && indexMap[inMF.v4].merge_final)
951
 
                        mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-2);
 
975
                        mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
952
976
 
953
977
                test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3);
954
978
                numFaces++;
959
983
                        DM_free_face_data(result, numFaces, 1);
960
984
                }
961
985
 
962
 
                for(j=0; j < count - 1; j++)
 
986
                for(j = 1; j < count; j++)
963
987
                {
964
988
                        MFace *mf2 = &mface[numFaces];
965
989
 
983
1007
                }
984
1008
        }
985
1009
 
 
1010
        /* add start and end caps */
 
1011
        if(start_cap) {
 
1012
                float startoffset[4][4];
 
1013
                MVert *cap_mvert;
 
1014
                MEdge *cap_medge;
 
1015
                MFace *cap_mface;
 
1016
                int *origindex;
 
1017
                int *vert_map;
 
1018
                int capVerts, capEdges, capFaces;
 
1019
 
 
1020
                capVerts = start_cap->getNumVerts(start_cap);
 
1021
                capEdges = start_cap->getNumEdges(start_cap);
 
1022
                capFaces = start_cap->getNumFaces(start_cap);
 
1023
                cap_mvert = start_cap->getVertArray(start_cap);
 
1024
                cap_medge = start_cap->getEdgeArray(start_cap);
 
1025
                cap_mface = start_cap->getFaceArray(start_cap);
 
1026
 
 
1027
                Mat4Invert(startoffset, offset);
 
1028
 
 
1029
                vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
 
1030
                                       "arrayModifier_doArray vert_map");
 
1031
 
 
1032
                origindex = result->getVertDataArray(result, CD_ORIGINDEX);
 
1033
                for(i = 0; i < capVerts; i++) {
 
1034
                        MVert *mv = &cap_mvert[i];
 
1035
                        short merged = 0;
 
1036
 
 
1037
                        if(amd->flags & MOD_ARR_MERGE) {
 
1038
                                float tmp_co[3];
 
1039
                                MVert *in_mv;
 
1040
                                int j;
 
1041
 
 
1042
                                VECCOPY(tmp_co, mv->co);
 
1043
                                Mat4MulVecfl(startoffset, tmp_co);
 
1044
 
 
1045
                                for(j = 0; j < maxVerts; j++) {
 
1046
                                        in_mv = &src_mvert[j];
 
1047
                                        /* if this vert is within merge limit, merge */
 
1048
                                        if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
 
1049
                                                vert_map[i] = calc_mapping(indexMap, j, 0);
 
1050
                                                merged = 1;
 
1051
                                                break;
 
1052
                                        }
 
1053
                                }
 
1054
                        }
 
1055
 
 
1056
                        if(!merged) {
 
1057
                                DM_copy_vert_data(start_cap, result, i, numVerts, 1);
 
1058
                                mvert[numVerts] = *mv;
 
1059
                                Mat4MulVecfl(startoffset, mvert[numVerts].co);
 
1060
                                origindex[numVerts] = ORIGINDEX_NONE;
 
1061
 
 
1062
                                vert_map[i] = numVerts;
 
1063
 
 
1064
                                numVerts++;
 
1065
                        }
 
1066
                }
 
1067
                origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
 
1068
                for(i = 0; i < capEdges; i++) {
 
1069
                        int v1, v2;
 
1070
 
 
1071
                        v1 = vert_map[cap_medge[i].v1];
 
1072
                        v2 = vert_map[cap_medge[i].v2];
 
1073
 
 
1074
                        if(!BLI_edgehash_haskey(edges, v1, v2)) {
 
1075
                                DM_copy_edge_data(start_cap, result, i, numEdges, 1);
 
1076
                                medge[numEdges] = cap_medge[i];
 
1077
                                medge[numEdges].v1 = v1;
 
1078
                                medge[numEdges].v2 = v2;
 
1079
                                origindex[numEdges] = ORIGINDEX_NONE;
 
1080
 
 
1081
                                numEdges++;
 
1082
                        }
 
1083
                }
 
1084
                origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
 
1085
                for(i = 0; i < capFaces; i++) {
 
1086
                        DM_copy_face_data(start_cap, result, i, numFaces, 1);
 
1087
                        mface[numFaces] = cap_mface[i];
 
1088
                        mface[numFaces].v1 = vert_map[mface[numFaces].v1];
 
1089
                        mface[numFaces].v2 = vert_map[mface[numFaces].v2];
 
1090
                        mface[numFaces].v3 = vert_map[mface[numFaces].v3];
 
1091
                        if(mface[numFaces].v4)
 
1092
                                mface[numFaces].v4 = vert_map[mface[numFaces].v4];
 
1093
                        origindex[numFaces] = ORIGINDEX_NONE;
 
1094
 
 
1095
                        numFaces++;
 
1096
                }
 
1097
 
 
1098
                MEM_freeN(vert_map);
 
1099
                start_cap->release(start_cap);
 
1100
        }
 
1101
 
 
1102
        if(end_cap) {
 
1103
                float endoffset[4][4];
 
1104
                MVert *cap_mvert;
 
1105
                MEdge *cap_medge;
 
1106
                MFace *cap_mface;
 
1107
                int *origindex;
 
1108
                int *vert_map;
 
1109
                int capVerts, capEdges, capFaces;
 
1110
 
 
1111
                capVerts = end_cap->getNumVerts(end_cap);
 
1112
                capEdges = end_cap->getNumEdges(end_cap);
 
1113
                capFaces = end_cap->getNumFaces(end_cap);
 
1114
                cap_mvert = end_cap->getVertArray(end_cap);
 
1115
                cap_medge = end_cap->getEdgeArray(end_cap);
 
1116
                cap_mface = end_cap->getFaceArray(end_cap);
 
1117
 
 
1118
                Mat4MulMat4(endoffset, final_offset, offset);
 
1119
 
 
1120
                vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
 
1121
                                       "arrayModifier_doArray vert_map");
 
1122
 
 
1123
                origindex = result->getVertDataArray(result, CD_ORIGINDEX);
 
1124
                for(i = 0; i < capVerts; i++) {
 
1125
                        MVert *mv = &cap_mvert[i];
 
1126
                        short merged = 0;
 
1127
 
 
1128
                        if(amd->flags & MOD_ARR_MERGE) {
 
1129
                                float tmp_co[3];
 
1130
                                MVert *in_mv;
 
1131
                                int j;
 
1132
 
 
1133
                                VECCOPY(tmp_co, mv->co);
 
1134
                                Mat4MulVecfl(offset, tmp_co);
 
1135
 
 
1136
                                for(j = 0; j < maxVerts; j++) {
 
1137
                                        in_mv = &src_mvert[j];
 
1138
                                        /* if this vert is within merge limit, merge */
 
1139
                                        if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
 
1140
                                                vert_map[i] = calc_mapping(indexMap, j, count - 1);
 
1141
                                                merged = 1;
 
1142
                                                break;
 
1143
                                        }
 
1144
                                }
 
1145
                        }
 
1146
 
 
1147
                        if(!merged) {
 
1148
                                DM_copy_vert_data(end_cap, result, i, numVerts, 1);
 
1149
                                mvert[numVerts] = *mv;
 
1150
                                Mat4MulVecfl(endoffset, mvert[numVerts].co);
 
1151
                                origindex[numVerts] = ORIGINDEX_NONE;
 
1152
 
 
1153
                                vert_map[i] = numVerts;
 
1154
 
 
1155
                                numVerts++;
 
1156
                        }
 
1157
                }
 
1158
                origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
 
1159
                for(i = 0; i < capEdges; i++) {
 
1160
                        int v1, v2;
 
1161
 
 
1162
                        v1 = vert_map[cap_medge[i].v1];
 
1163
                        v2 = vert_map[cap_medge[i].v2];
 
1164
 
 
1165
                        if(!BLI_edgehash_haskey(edges, v1, v2)) {
 
1166
                                DM_copy_edge_data(end_cap, result, i, numEdges, 1);
 
1167
                                medge[numEdges] = cap_medge[i];
 
1168
                                medge[numEdges].v1 = v1;
 
1169
                                medge[numEdges].v2 = v2;
 
1170
                                origindex[numEdges] = ORIGINDEX_NONE;
 
1171
 
 
1172
                                numEdges++;
 
1173
                        }
 
1174
                }
 
1175
                origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
 
1176
                for(i = 0; i < capFaces; i++) {
 
1177
                        DM_copy_face_data(end_cap, result, i, numFaces, 1);
 
1178
                        mface[numFaces] = cap_mface[i];
 
1179
                        mface[numFaces].v1 = vert_map[mface[numFaces].v1];
 
1180
                        mface[numFaces].v2 = vert_map[mface[numFaces].v2];
 
1181
                        mface[numFaces].v3 = vert_map[mface[numFaces].v3];
 
1182
                        if(mface[numFaces].v4)
 
1183
                                mface[numFaces].v4 = vert_map[mface[numFaces].v4];
 
1184
                        origindex[numFaces] = ORIGINDEX_NONE;
 
1185
 
 
1186
                        numFaces++;
 
1187
                }
 
1188
 
 
1189
                MEM_freeN(vert_map);
 
1190
                end_cap->release(end_cap);
 
1191
        }
 
1192
 
 
1193
        BLI_edgehash_free(edges, NULL);
986
1194
        MEM_freeN(indexMap);
987
1195
 
988
1196
        CDDM_lower_num_verts(result, numVerts);
1018
1226
static void mirrorModifier_initData(ModifierData *md)
1019
1227
{
1020
1228
        MirrorModifierData *mmd = (MirrorModifierData*) md;
1021
 
 
 
1229
 
 
1230
        mmd->flag |= MOD_MIR_AXIS_X;
1022
1231
        mmd->tolerance = 0.001;
1023
1232
}
1024
1233
 
1032
1241
        tmmd->tolerance = mmd->tolerance;
1033
1242
}
1034
1243
 
1035
 
static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
1036
 
                                             DerivedMesh *dm,
1037
 
                                             int initFlags)
 
1244
static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
 
1245
                                                   DerivedMesh *dm,
 
1246
                                                   int initFlags,
 
1247
                                                   int axis)
1038
1248
{
1039
 
        int i, axis = mmd->axis;
 
1249
        int i;
1040
1250
        float tolerance = mmd->tolerance;
1041
1251
        DerivedMesh *result;
1042
1252
        int numVerts, numEdges, numFaces;
1141
1351
                        mf2->v3 += indexMap[inMF.v3][1];
1142
1352
                        if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
1143
1353
 
 
1354
                        /* mirror UVs if enabled */
 
1355
                        if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
 
1356
                                MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
 
1357
                                if(tf) {
 
1358
                                        int j;
 
1359
                                        for(j = 0; j < 4; ++j) {
 
1360
                                                if(mmd->flag & MOD_MIR_MIRROR_U)
 
1361
                                                        tf->uv[j][0] = 1.0f - tf->uv[j][0];
 
1362
                                                if(mmd->flag & MOD_MIR_MIRROR_V)
 
1363
                                                        tf->uv[j][1] = 1.0f - tf->uv[j][1];
 
1364
                                        }
 
1365
                                }
 
1366
                        }
 
1367
 
1144
1368
                        /* Flip face normal */
1145
1369
                        SWAP(int, mf2->v1, mf2->v3);
1146
1370
                        DM_swap_face_data(result, numFaces, corner_indices);
1159
1383
        return result;
1160
1384
}
1161
1385
 
 
1386
static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
 
1387
                                             DerivedMesh *dm,
 
1388
                                             int initFlags)
 
1389
{
 
1390
        DerivedMesh *result = dm;
 
1391
 
 
1392
        /* check which axes have been toggled and mirror accordingly */
 
1393
        if(mmd->flag & MOD_MIR_AXIS_X) {
 
1394
                result = doMirrorOnAxis(mmd, result, initFlags, 0);
 
1395
        }
 
1396
        if(mmd->flag & MOD_MIR_AXIS_Y) {
 
1397
                DerivedMesh *tmp = result;
 
1398
                result = doMirrorOnAxis(mmd, result, initFlags, 1);
 
1399
                if(tmp != dm) tmp->release(tmp); /* free intermediate results */
 
1400
        }
 
1401
        if(mmd->flag & MOD_MIR_AXIS_Z) {
 
1402
                DerivedMesh *tmp = result;
 
1403
                result = doMirrorOnAxis(mmd, result, initFlags, 2);
 
1404
                if(tmp != dm) tmp->release(tmp); /* free intermediate results */
 
1405
        }
 
1406
 
 
1407
        return result;
 
1408
}
 
1409
 
1162
1410
static DerivedMesh *mirrorModifier_applyModifier(
1163
1411
                 ModifierData *md, Object *ob, DerivedMesh *derivedData,
1164
1412
                 int useRenderParams, int isFinalCalc)
1210
1458
        temd->flags = emd->flags;
1211
1459
}
1212
1460
 
1213
 
typedef struct SmoothMesh {
1214
 
        GHash *verts;
1215
 
        GHash *edges;
1216
 
        GHash *faces;
1217
 
        DerivedMesh *dm;
1218
 
        float threshold; /* the cosine of the smoothing angle */
1219
 
        int flags;
1220
 
} SmoothMesh;
1221
 
 
1222
1461
/* Mesh data for edgesplit operation */
1223
1462
typedef struct SmoothVert {
1224
1463
        LinkNode *faces;     /* all faces which use this vert */
1226
1465
        int newIndex; /* the index of the new DerivedMesh vert */
1227
1466
} SmoothVert;
1228
1467
 
1229
 
static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
1230
 
{
1231
 
        SmoothVert *copy = MEM_callocN(sizeof(*copy), "copy_smoothvert");
1232
 
 
1233
 
        *copy = *vert;
1234
 
        copy->faces = NULL;
1235
 
        copy->newIndex = BLI_ghash_size(mesh->verts);
1236
 
        BLI_ghash_insert(mesh->verts, (void *)copy->newIndex, copy);
1237
 
 
1238
 
#ifdef EDGESPLIT_DEBUG_2
1239
 
        printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
1240
 
#endif
1241
 
        return copy;
1242
 
}
1243
 
 
1244
 
static void smoothvert_free(void *vert)
1245
 
{
1246
 
        BLI_linklist_free(((SmoothVert *)vert)->faces, NULL);
1247
 
        MEM_freeN(vert);
1248
 
}
1249
 
 
1250
1468
#define SMOOTHEDGE_NUM_VERTS 2
1251
1469
 
1252
1470
typedef struct SmoothEdge {
1257
1475
        short flag; /* the flags from the original DerivedMesh edge */
1258
1476
} SmoothEdge;
1259
1477
 
1260
 
static void smoothedge_free(void *edge)
1261
 
{
1262
 
        BLI_linklist_free(((SmoothEdge *)edge)->faces, NULL);
1263
 
        MEM_freeN(edge);
1264
 
}
1265
 
 
1266
 
static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
1267
 
{
1268
 
        SmoothEdge *copy = MEM_callocN(sizeof(*copy), "copy_smoothedge");
1269
 
 
1270
 
        *copy = *edge;
1271
 
        copy->faces = NULL;
1272
 
        copy->newIndex = BLI_ghash_size(mesh->edges);
1273
 
        BLI_ghash_insert(mesh->edges, (void *)copy->newIndex, copy);
1274
 
 
1275
 
#ifdef EDGESPLIT_DEBUG_2
1276
 
        printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
1277
 
#endif
1278
 
        return copy;
1279
 
}
1280
 
 
1281
 
static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
1282
 
{
1283
 
        int i;
1284
 
        for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
1285
 
                if(edge->verts[i] == vert) return 1;
1286
 
 
1287
 
        return 0;
1288
 
}
1289
 
 
1290
1478
#define SMOOTHFACE_MAX_EDGES 4
1291
1479
 
1292
1480
typedef struct SmoothFace {
1297
1485
        int newIndex; /* the index of the new DerivedMesh face */
1298
1486
} SmoothFace;
1299
1487
 
1300
 
static void smoothface_free(void *face)
1301
 
{
1302
 
        MEM_freeN(face);
1303
 
}
1304
 
 
1305
 
static SmoothMesh *smoothmesh_new()
 
1488
typedef struct SmoothMesh {
 
1489
        SmoothVert *verts;
 
1490
        SmoothEdge *edges;
 
1491
        SmoothFace *faces;
 
1492
        int num_verts, num_edges, num_faces;
 
1493
        int max_verts, max_edges, max_faces;
 
1494
        DerivedMesh *dm;
 
1495
        float threshold; /* the cosine of the smoothing angle */
 
1496
        int flags;
 
1497
} SmoothMesh;
 
1498
 
 
1499
static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
 
1500
{
 
1501
        SmoothVert *copy = &mesh->verts[mesh->num_verts];
 
1502
 
 
1503
        if(mesh->num_verts >= mesh->max_verts) {
 
1504
                printf("Attempted to add a SmoothMesh vert beyond end of array\n");
 
1505
                return NULL;
 
1506
        }
 
1507
 
 
1508
        *copy = *vert;
 
1509
        copy->faces = NULL;
 
1510
        copy->newIndex = mesh->num_verts;
 
1511
        ++mesh->num_verts;
 
1512
 
 
1513
#ifdef EDGESPLIT_DEBUG_2
 
1514
        printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
 
1515
#endif
 
1516
        return copy;
 
1517
}
 
1518
 
 
1519
static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
 
1520
{
 
1521
        SmoothEdge *copy = &mesh->edges[mesh->num_edges];
 
1522
 
 
1523
        if(mesh->num_edges >= mesh->max_edges) {
 
1524
                printf("Attempted to add a SmoothMesh edge beyond end of array\n");
 
1525
                return NULL;
 
1526
        }
 
1527
 
 
1528
        *copy = *edge;
 
1529
        copy->faces = NULL;
 
1530
        copy->newIndex = mesh->num_edges;
 
1531
        ++mesh->num_edges;
 
1532
 
 
1533
#ifdef EDGESPLIT_DEBUG_2
 
1534
        printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
 
1535
#endif
 
1536
        return copy;
 
1537
}
 
1538
 
 
1539
static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
 
1540
{
 
1541
        int i;
 
1542
        for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
 
1543
                if(edge->verts[i] == vert) return 1;
 
1544
 
 
1545
        return 0;
 
1546
}
 
1547
 
 
1548
static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
 
1549
                                  int max_verts, int max_edges, int max_faces)
1306
1550
{
1307
1551
        SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
1308
 
        mesh->verts = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
1309
 
        mesh->edges = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
1310
 
        mesh->faces = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
 
1552
        mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
 
1553
                                  "SmoothMesh.verts");
 
1554
        mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
 
1555
                                  "SmoothMesh.edges");
 
1556
        mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
 
1557
                                  "SmoothMesh.faces");
 
1558
 
 
1559
        mesh->num_verts = num_verts;
 
1560
        mesh->num_edges = num_edges;
 
1561
        mesh->num_faces = num_faces;
 
1562
 
 
1563
        mesh->max_verts = max_verts;
 
1564
        mesh->max_edges = max_edges;
 
1565
        mesh->max_faces = max_faces;
1311
1566
 
1312
1567
        return mesh;
1313
1568
}
1314
1569
 
1315
1570
static void smoothmesh_free(SmoothMesh *mesh)
1316
1571
{
1317
 
        BLI_ghash_free(mesh->verts, NULL, smoothvert_free);
1318
 
        BLI_ghash_free(mesh->edges, NULL, smoothedge_free);
1319
 
        BLI_ghash_free(mesh->faces, NULL, smoothface_free);
 
1572
        int i;
 
1573
 
 
1574
        for(i = 0; i < mesh->num_verts; ++i)
 
1575
                BLI_linklist_free(mesh->verts[i].faces, NULL);
 
1576
 
 
1577
        for(i = 0; i < mesh->num_edges; ++i)
 
1578
                BLI_linklist_free(mesh->edges[i].faces, NULL);
 
1579
 
 
1580
        MEM_freeN(mesh->verts);
 
1581
        MEM_freeN(mesh->edges);
 
1582
        MEM_freeN(mesh->faces);
1320
1583
        MEM_freeN(mesh);
1321
1584
}
1322
1585
 
 
1586
static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
 
1587
{
 
1588
        int i;
 
1589
        SmoothVert *tmp;
 
1590
 
 
1591
        if(max_verts <= mesh->max_verts) return;
 
1592
 
 
1593
        tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
 
1594
 
 
1595
        memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
 
1596
 
 
1597
        /* remap vert pointers in edges */
 
1598
        for(i = 0; i < mesh->num_edges; ++i) {
 
1599
                int j;
 
1600
                SmoothEdge *edge = &mesh->edges[i];
 
1601
 
 
1602
                for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
 
1603
                        /* pointer arithmetic to get vert array index */
 
1604
                        edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
 
1605
        }
 
1606
 
 
1607
        MEM_freeN(mesh->verts);
 
1608
        mesh->verts = tmp;
 
1609
        mesh->max_verts = max_verts;
 
1610
}
 
1611
 
 
1612
static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
 
1613
{
 
1614
        int i;
 
1615
        SmoothEdge *tmp;
 
1616
 
 
1617
        if(max_edges <= mesh->max_edges) return;
 
1618
 
 
1619
        tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
 
1620
 
 
1621
        memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
 
1622
 
 
1623
        /* remap edge pointers in faces */
 
1624
        for(i = 0; i < mesh->num_faces; ++i) {
 
1625
                int j;
 
1626
                SmoothFace *face = &mesh->faces[i];
 
1627
 
 
1628
                for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
 
1629
                        if(face->edges[j])
 
1630
                                /* pointer arithmetic to get edge array index */
 
1631
                                face->edges[j] = &tmp[face->edges[j] - mesh->edges];
 
1632
        }
 
1633
 
 
1634
        MEM_freeN(mesh->edges);
 
1635
        mesh->edges = tmp;
 
1636
        mesh->max_edges = max_edges;
 
1637
}
 
1638
 
1323
1639
#ifdef EDGESPLIT_DEBUG_0
1324
1640
static void smoothmesh_print(SmoothMesh *mesh)
1325
1641
{
1328
1644
 
1329
1645
        printf("--- SmoothMesh ---\n");
1330
1646
        printf("--- Vertices ---\n");
1331
 
        for(i = 0; i < BLI_ghash_size(mesh->verts); i++) {
1332
 
                SmoothVert *vert = BLI_ghash_lookup(mesh->verts, (void *)i);
 
1647
        for(i = 0; i < mesh->num_verts; i++) {
 
1648
                SmoothVert *vert = &mesh->verts[i];
1333
1649
                LinkNode *node;
1334
1650
                MVert mv;
1335
1651
 
1346
1662
        }
1347
1663
 
1348
1664
        printf("\n--- Edges ---\n");
1349
 
        for(i = 0; i < BLI_ghash_size(mesh->edges); i++) {
1350
 
                SmoothEdge *edge = BLI_ghash_lookup(mesh->edges, (void *)i);
 
1665
        for(i = 0; i < mesh->num_edges; i++) {
 
1666
                SmoothEdge *edge = &mesh->edges[i];
1351
1667
                LinkNode *node;
1352
1668
 
1353
1669
                printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
1363
1679
        }
1364
1680
 
1365
1681
        printf("\n--- Faces ---\n");
1366
 
        for(i = 0; i < BLI_ghash_size(mesh->faces); i++) {
1367
 
                SmoothFace *face = BLI_ghash_lookup(mesh->faces, (void *)i);
 
1682
        for(i = 0; i < mesh->num_faces; i++) {
 
1683
                SmoothFace *face = &mesh->faces[i];
1368
1684
 
1369
1685
                printf("%4d: indices={%4d, %4d}, edges={", i,
1370
1686
                       face->oldIndex, face->newIndex);
1385
1701
 
1386
1702
static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
1387
1703
{
1388
 
        SmoothMesh *mesh = smoothmesh_new();
 
1704
        SmoothMesh *mesh;
1389
1705
        EdgeHash *edges = BLI_edgehash_new();
1390
1706
        int i;
1391
1707
        int totvert, totedge, totface;
1392
1708
 
 
1709
        totvert = dm->getNumVerts(dm);
 
1710
        totedge = dm->getNumEdges(dm);
 
1711
        totface = dm->getNumFaces(dm);
 
1712
 
 
1713
        mesh = smoothmesh_new(totvert, totedge, totface,
 
1714
                              totvert, totedge, totface);
 
1715
 
1393
1716
        mesh->dm = dm;
1394
1717
 
1395
 
        totvert = dm->getNumVerts(dm);
1396
1718
        for(i = 0; i < totvert; i++) {
1397
 
                SmoothVert *vert = MEM_callocN(sizeof(*vert), "smoothvert");
 
1719
                SmoothVert *vert = &mesh->verts[i];
1398
1720
 
1399
1721
                vert->oldIndex = vert->newIndex = i;
1400
 
                BLI_ghash_insert(mesh->verts, (void *)i, vert);
1401
1722
        }
1402
1723
 
1403
 
        totedge = dm->getNumEdges(dm);
1404
1724
        for(i = 0; i < totedge; i++) {
1405
 
                SmoothEdge *edge = MEM_callocN(sizeof(*edge), "smoothedge");
 
1725
                SmoothEdge *edge = &mesh->edges[i];
1406
1726
                MEdge med;
1407
1727
 
1408
1728
                dm->getEdge(dm, i, &med);
1409
 
                edge->verts[0] = BLI_ghash_lookup(mesh->verts, (void *)med.v1);
1410
 
                edge->verts[1] = BLI_ghash_lookup(mesh->verts, (void *)med.v2);
 
1729
                edge->verts[0] = &mesh->verts[med.v1];
 
1730
                edge->verts[1] = &mesh->verts[med.v2];
1411
1731
                edge->oldIndex = edge->newIndex = i;
1412
1732
                edge->flag = med.flag;
1413
 
                BLI_ghash_insert(mesh->edges, (void *)i, edge);
 
1733
 
1414
1734
                BLI_edgehash_insert(edges, med.v1, med.v2, edge);
1415
1735
        }
1416
1736
 
1417
 
        totface = dm->getNumFaces(dm);
1418
1737
        for(i = 0; i < totface; i++) {
1419
 
                SmoothFace *face = MEM_callocN(sizeof(*face), "smoothface");
 
1738
                SmoothFace *face = &mesh->faces[i];
1420
1739
                MFace mf;
1421
1740
                MVert v1, v2, v3;
1422
1741
                int j;
1452
1771
                }
1453
1772
 
1454
1773
                face->oldIndex = face->newIndex = i;
1455
 
                BLI_ghash_insert(mesh->faces, (void *)i, face);
1456
1774
        }
1457
1775
 
1458
1776
        BLI_edgehash_free(edges, NULL);
1463
1781
static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
1464
1782
{
1465
1783
        DerivedMesh *result = CDDM_from_template(mesh->dm,
1466
 
                                                 BLI_ghash_size(mesh->verts),
1467
 
                                                 BLI_ghash_size(mesh->edges),
1468
 
                                                 BLI_ghash_size(mesh->faces));
1469
 
        GHashIterator *i;
 
1784
                                                 mesh->num_verts,
 
1785
                                                 mesh->num_edges,
 
1786
                                                 mesh->num_faces);
1470
1787
        MVert *new_verts = CDDM_get_verts(result);
1471
1788
        MEdge *new_edges = CDDM_get_edges(result);
1472
1789
        MFace *new_faces = CDDM_get_faces(result);
 
1790
        int i;
1473
1791
 
1474
 
        for(i = BLI_ghashIterator_new(mesh->verts); !BLI_ghashIterator_isDone(i);
1475
 
            BLI_ghashIterator_step(i)) {
1476
 
                SmoothVert *vert = BLI_ghashIterator_getValue(i);
 
1792
        for(i = 0; i < mesh->num_verts; ++i) {
 
1793
                SmoothVert *vert = &mesh->verts[i];
1477
1794
                MVert *newMV = &new_verts[vert->newIndex];
1478
1795
 
1479
1796
                DM_copy_vert_data(mesh->dm, result,
1480
1797
                                  vert->oldIndex, vert->newIndex, 1);
1481
1798
                mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
1482
1799
        }
1483
 
        BLI_ghashIterator_free(i);
1484
1800
 
1485
 
        for(i = BLI_ghashIterator_new(mesh->edges); !BLI_ghashIterator_isDone(i);
1486
 
            BLI_ghashIterator_step(i)) {
1487
 
                SmoothEdge *edge = BLI_ghashIterator_getValue(i);
 
1801
        for(i = 0; i < mesh->num_edges; ++i) {
 
1802
                SmoothEdge *edge = &mesh->edges[i];
1488
1803
                MEdge *newME = &new_edges[edge->newIndex];
1489
1804
 
1490
1805
                DM_copy_edge_data(mesh->dm, result,
1493
1808
                newME->v1 = edge->verts[0]->newIndex;
1494
1809
                newME->v2 = edge->verts[1]->newIndex;
1495
1810
        }
1496
 
        BLI_ghashIterator_free(i);
1497
1811
 
1498
 
        for(i = BLI_ghashIterator_new(mesh->faces); !BLI_ghashIterator_isDone(i);
1499
 
            BLI_ghashIterator_step(i)) {
1500
 
                SmoothFace *face = BLI_ghashIterator_getValue(i);
 
1812
        for(i = 0; i < mesh->num_faces; ++i) {
 
1813
                SmoothFace *face = &mesh->faces[i];
1501
1814
                MFace *newMF = &new_faces[face->newIndex];
1502
1815
 
1503
1816
                DM_copy_face_data(mesh->dm, result,
1514
1827
                        newMF->v4 = 0;
1515
1828
                }
1516
1829
        }
1517
 
        BLI_ghashIterator_free(i);
1518
1830
 
1519
1831
        return result;
1520
1832
}
1801
2113
static int edge_is_sharp(SmoothEdge *edge, int flags,
1802
2114
                         float threshold)
1803
2115
{
1804
 
        /* treat all non-manifold edges as sharp */
1805
 
        if(edge->faces && edge->faces->next && edge->faces->next->next) {
1806
 
#ifdef EDGESPLIT_DEBUG_1
1807
 
                printf("edge %d: non-manifold\n", edge->newIndex);
1808
 
#endif
1809
 
                return 1;
1810
 
        }
1811
2116
#ifdef EDGESPLIT_DEBUG_1
1812
2117
        printf("edge %d: ", edge->newIndex);
1813
2118
#endif
1814
 
 
1815
 
        /* if all flags are disabled, edge cannot be sharp */
1816
 
        if(!(flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))) {
1817
 
#ifdef EDGESPLIT_DEBUG_1
1818
 
                printf("not sharp\n");
1819
 
#endif
1820
 
                return 0;
1821
 
        }
1822
 
 
1823
 
        /* edge can only be sharp if it has at least 2 faces */
1824
 
        if(!edge_is_loose(edge)) {
1825
 
                LinkNode *node1;
1826
 
                LinkNode *node2;
1827
 
 
1828
 
                if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
 
2119
        if(edge->flag & ME_SHARP) {
 
2120
                /* edge can only be sharp if it has at least 2 faces */
 
2121
                if(!edge_is_loose(edge)) {
1829
2122
#ifdef EDGESPLIT_DEBUG_1
1830
2123
                        printf("sharp\n");
1831
2124
#endif
1832
2125
                        return 1;
1833
 
                }
1834
 
 
1835
 
                if(flags & MOD_EDGESPLIT_FROMANGLE) {
1836
 
                        /* check angles between all faces */
1837
 
                        for(node1 = edge->faces; node1; node1 = node1->next) {
1838
 
                                SmoothFace *face1 = node1->link;
1839
 
                                for(node2 = node1->next; node2; node2 = node2->next) {
1840
 
                                        SmoothFace *face2 = node2->link;
1841
 
                                        float edge_angle_cos = MTC_dot3Float(face1->normal,
1842
 
                                                                             face2->normal);
1843
 
                                        if(edge_angle_cos < threshold) {
1844
 
#ifdef EDGESPLIT_DEBUG_1
1845
 
                                                printf("sharp\n");
1846
 
#endif
1847
 
                                                return 1;
1848
 
                                        }
1849
 
                                }
1850
 
                        }
 
2126
                } else {
 
2127
                        /* edge is loose, so it can't be sharp */
 
2128
                        edge->flag &= ~ME_SHARP;
1851
2129
                }
1852
2130
        }
1853
2131
 
2095
2373
#endif
2096
2374
}
2097
2375
 
 
2376
static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
 
2377
                                      int flags, int *extra_edges)
 
2378
{
 
2379
        /* if normal1 dot normal2 < threshold, angle is greater, so split */
 
2380
        /* FIXME not sure if this always works */
 
2381
        /* 0.00001 added for floating-point rounding */
 
2382
        float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
 
2383
        int i;
 
2384
 
 
2385
        *extra_edges = 0;
 
2386
 
 
2387
        /* loop through edges, counting potential new ones */
 
2388
        for(i = 0; i < mesh->num_edges; i++) {
 
2389
                SmoothEdge *edge = &mesh->edges[i];
 
2390
                int sharp = 0;
 
2391
 
 
2392
                /* treat all non-manifold edges (3 or more faces) as sharp */
 
2393
                if(edge->faces && edge->faces->next && edge->faces->next->next) {
 
2394
                        LinkNode *node;
 
2395
 
 
2396
                        /* this edge is sharp */
 
2397
                        sharp = 1;
 
2398
 
 
2399
                        /* add an extra edge for every face beyond the first */
 
2400
                        *extra_edges += 2;
 
2401
                        for(node = edge->faces->next->next->next; node; node = node->next)
 
2402
                                (*extra_edges)++;
 
2403
                } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
 
2404
                          && !edge_is_loose(edge)) {
 
2405
                        /* (the edge can only be sharp if we're checking angle or flag,
 
2406
                         * and it has at least 2 faces) */
 
2407
 
 
2408
                        /* if we're checking the sharp flag and it's set, good */
 
2409
                        if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
 
2410
                                /* this edge is sharp */
 
2411
                                sharp = 1;
 
2412
 
 
2413
                                (*extra_edges)++;
 
2414
                        } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
 
2415
                                /* we know the edge has 2 faces, so check the angle */
 
2416
                                SmoothFace *face1 = edge->faces->link;
 
2417
                                SmoothFace *face2 = edge->faces->next->link;
 
2418
                                float edge_angle_cos = MTC_dot3Float(face1->normal,
 
2419
                                                                     face2->normal);
 
2420
 
 
2421
                                if(edge_angle_cos < threshold) {
 
2422
                                        /* this edge is sharp */
 
2423
                                        sharp = 1;
 
2424
 
 
2425
                                        (*extra_edges)++;
 
2426
                                }
 
2427
                        }
 
2428
                }
 
2429
 
 
2430
                /* set/clear sharp flag appropriately */
 
2431
                if(sharp) edge->flag |= ME_SHARP;
 
2432
                else edge->flag &= ~ME_SHARP;
 
2433
        }
 
2434
}
 
2435
 
2098
2436
static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
2099
2437
{
2100
2438
        int i;
2101
 
        int num_edges = BLI_ghash_size(mesh->edges);
2102
2439
        /* if normal1 dot normal2 < threshold, angle is greater, so split */
2103
2440
        /* FIXME not sure if this always works */
2104
2441
        /* 0.00001 added for floating-point rounding */
2107
2444
 
2108
2445
        /* loop through edges, splitting sharp ones */
2109
2446
        /* can't use an iterator here, because we'll be adding edges */
2110
 
        for(i = 0; i < num_edges; i++) {
2111
 
                SmoothEdge *edge = BLI_ghash_lookup(mesh->edges, (void *)i);
 
2447
        for(i = 0; i < mesh->num_edges; i++) {
 
2448
                SmoothEdge *edge = &mesh->edges[i];
2112
2449
 
2113
2450
                if(edge_is_sharp(edge, flags, mesh->threshold))
2114
2451
                        split_edge(edge, edge->verts[0], mesh);
2118
2455
 
2119
2456
static void split_single_verts(SmoothMesh *mesh)
2120
2457
{
2121
 
        int num_faces = BLI_ghash_size(mesh->faces);
2122
2458
        int i,j;
2123
2459
 
2124
 
        for(i = 0; i < num_faces; i++) {
2125
 
                SmoothFace *face = BLI_ghash_lookup(mesh->faces, (void *)i);
 
2460
        for(i = 0; i < mesh->num_faces; i++) {
 
2461
                SmoothFace *face = &mesh->faces[i];
2126
2462
 
2127
2463
                for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
2128
2464
                        SmoothEdge *edge = face->edges[j];
2154
2490
{
2155
2491
        SmoothMesh *mesh;
2156
2492
        DerivedMesh *result;
 
2493
        int max_verts, max_edges;
2157
2494
 
2158
2495
        if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
2159
2496
                return dm;
2160
2497
 
 
2498
        /* 1. make smoothmesh with initial number of elements */
2161
2499
        mesh = smoothmesh_from_derivedmesh(dm);
2162
2500
 
 
2501
        /* 2. count max number of elements to add */
 
2502
        tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
 
2503
        max_verts = max_edges * 2 + mesh->max_verts;
 
2504
        max_edges += mesh->max_edges;
 
2505
 
 
2506
        /* 3. reallocate smoothmesh arrays & copy elements across */
 
2507
        /* 4. remap copied elements' pointers to point into the new arrays */
 
2508
        smoothmesh_resize_verts(mesh, max_verts);
 
2509
        smoothmesh_resize_edges(mesh, max_edges);
 
2510
 
2163
2511
#ifdef EDGESPLIT_DEBUG_1
2164
2512
        printf("********** Pre-split **********\n");
2165
2513
        smoothmesh_print(mesh);
2179
2527
        smoothmesh_print(mesh);
2180
2528
#endif
2181
2529
 
 
2530
#ifdef EDGESPLIT_DEBUG_0
 
2531
        printf("Edgesplit: Estimated %d verts & %d edges, "
 
2532
               "found %d verts & %d edges\n", max_verts, max_edges,
 
2533
               mesh->num_verts, mesh->num_edges);
 
2534
#endif
 
2535
 
2182
2536
        result = CDDM_from_smoothmesh(mesh);
2183
2537
        smoothmesh_free(mesh);
2184
2538
 
2965
3319
        return result;
2966
3320
}
2967
3321
 
 
3322
/* Smooth */
 
3323
 
 
3324
static void smoothModifier_initData(ModifierData *md)
 
3325
{
 
3326
        SmoothModifierData *smd = (SmoothModifierData*) md;
 
3327
 
 
3328
        smd->fac = 0.5f;
 
3329
        smd->repeat = 1;
 
3330
        smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
 
3331
        smd->defgrp_name[0] = '\0';
 
3332
}
 
3333
 
 
3334
static void smoothModifier_copyData(ModifierData *md, ModifierData *target)
 
3335
{
 
3336
        SmoothModifierData *smd = (SmoothModifierData*) md;
 
3337
        SmoothModifierData *tsmd = (SmoothModifierData*) target;
 
3338
 
 
3339
        tsmd->fac = smd->fac;
 
3340
        tsmd->repeat = smd->repeat;
 
3341
        tsmd->flag = smd->flag;
 
3342
        strncpy(tsmd->defgrp_name, smd->defgrp_name, 32);
 
3343
}
 
3344
 
 
3345
int smoothModifier_isDisabled(ModifierData *md)
 
3346
{
 
3347
        SmoothModifierData *smd = (SmoothModifierData*) md;
 
3348
        short flag;
 
3349
 
 
3350
        flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
 
3351
 
 
3352
        /* disable if modifier is off for X, Y and Z or if factor is 0 */
 
3353
        if((smd->fac == 0.0f) || flag == 0) return 1;
 
3354
 
 
3355
        return 0;
 
3356
}
 
3357
 
 
3358
CustomDataMask smoothModifier_requiredDataMask(ModifierData *md)
 
3359
{
 
3360
        SmoothModifierData *smd = (SmoothModifierData *)md;
 
3361
        CustomDataMask dataMask = 0;
 
3362
 
 
3363
        /* ask for vertexgroups if we need them */
 
3364
        if(smd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
 
3365
 
 
3366
        return dataMask;
 
3367
}
 
3368
 
 
3369
static void smoothModifier_do(
 
3370
                SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
 
3371
                float (*vertexCos)[3], int numVerts)
 
3372
{
 
3373
        MDeformVert *dvert = NULL;
 
3374
        MEdge *medges = NULL;
 
3375
 
 
3376
        int i, j, numDMEdges, defgrp_index;
 
3377
        unsigned char *uctmp;
 
3378
        float *ftmp, fac, facm;
 
3379
 
 
3380
        ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
 
3381
                        "smoothmodifier_f");
 
3382
        if (!ftmp) return;
 
3383
        uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
 
3384
                        "smoothmodifier_uc");
 
3385
        if (!uctmp) {
 
3386
                if (ftmp) MEM_freeN(ftmp);
 
3387
                return;
 
3388
        }
 
3389
 
 
3390
        fac = smd->fac;
 
3391
        facm = 1 - fac;
 
3392
 
 
3393
        medges = CDDM_get_edges(dm);
 
3394
        numDMEdges = dm->getNumEdges(dm);
 
3395
 
 
3396
        defgrp_index = -1;
 
3397
 
 
3398
        if (smd->defgrp_name[0]) {
 
3399
                bDeformGroup *def;
 
3400
 
 
3401
                for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
 
3402
                        if (!strcmp(def->name, smd->defgrp_name)) {
 
3403
                                defgrp_index = i;
 
3404
                                break;
 
3405
                        }
 
3406
                }
 
3407
        }
 
3408
 
 
3409
        if (defgrp_index >= 0)
 
3410
                dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
 
3411
 
 
3412
        /* NOTICE: this can be optimized a little bit by moving the
 
3413
         * if (dvert) out of the loop, if needed */
 
3414
        for (j = 0; j < smd->repeat; j++) {
 
3415
                for (i = 0; i < numDMEdges; i++) {
 
3416
                        float fvec[3];
 
3417
                        float *v1, *v2;
 
3418
                        unsigned int idx1, idx2;
 
3419
 
 
3420
                        idx1 = medges[i].v1;
 
3421
                        idx2 = medges[i].v2;
 
3422
 
 
3423
                        v1 = vertexCos[idx1];
 
3424
                        v2 = vertexCos[idx2];
 
3425
 
 
3426
                        fvec[0] = (v1[0] + v2[0]) / 2.0;
 
3427
                        fvec[1] = (v1[1] + v2[1]) / 2.0;
 
3428
                        fvec[2] = (v1[2] + v2[2]) / 2.0;
 
3429
 
 
3430
                        v1 = &ftmp[idx1*3];
 
3431
                        v2 = &ftmp[idx2*3];
 
3432
 
 
3433
                        if (uctmp[idx1] < 255) {
 
3434
                                uctmp[idx1]++;
 
3435
                                VecAddf(v1, v1, fvec);
 
3436
                        }
 
3437
                        if (uctmp[idx2] < 255) {
 
3438
                                uctmp[idx2]++;
 
3439
                                VecAddf(v2, v2, fvec);
 
3440
                        }
 
3441
                }
 
3442
 
 
3443
                if (dvert) {
 
3444
                        for (i = 0; i < numVerts; i++) {
 
3445
                                MDeformWeight *dw = NULL;
 
3446
                                float f, fm, facw, *fp, *v;
 
3447
                                int k;
 
3448
                                short flag = smd->flag;
 
3449
 
 
3450
                                v = vertexCos[i];
 
3451
                                fp = &ftmp[i*3];
 
3452
 
 
3453
                                for (k = 0; k < dvert[i].totweight; ++k) {
 
3454
                                        if(dvert[i].dw[k].def_nr == defgrp_index) {
 
3455
                                                dw = &dvert[i].dw[k];
 
3456
                                                break;
 
3457
                                        }
 
3458
                                }
 
3459
                                if (!dw) continue;
 
3460
 
 
3461
                                f = fac * dw->weight;
 
3462
                                fm = 1.0f - f;
 
3463
 
 
3464
                                /* fp is the sum of uctmp[i] verts, so must be averaged */
 
3465
                                facw = 0.0f;
 
3466
                                if (uctmp[i]) 
 
3467
                                        facw = f / (float)uctmp[i];
 
3468
 
 
3469
                                if (flag & MOD_SMOOTH_X)
 
3470
                                        v[0] = fm * v[0] + facw * fp[0];
 
3471
                                if (flag & MOD_SMOOTH_Y)
 
3472
                                        v[1] = fm * v[1] + facw * fp[1];
 
3473
                                if (flag & MOD_SMOOTH_Z)
 
3474
                                        v[2] = fm * v[2] + facw * fp[2];
 
3475
                        }
 
3476
                }
 
3477
                else { /* no vertex group */
 
3478
                        for (i = 0; i < numVerts; i++) {
 
3479
                                float facw, *fp, *v;
 
3480
                                short flag = smd->flag;
 
3481
 
 
3482
                                v = vertexCos[i];
 
3483
                                fp = &ftmp[i*3];
 
3484
 
 
3485
                                /* fp is the sum of uctmp[i] verts, so must be averaged */
 
3486
                                facw = 0.0f;
 
3487
                                if (uctmp[i]) 
 
3488
                                        facw = fac / (float)uctmp[i];
 
3489
 
 
3490
                                if (flag & MOD_SMOOTH_X)
 
3491
                                        v[0] = facm * v[0] + facw * fp[0];
 
3492
                                if (flag & MOD_SMOOTH_Y)
 
3493
                                        v[1] = facm * v[1] + facw * fp[1];
 
3494
                                if (flag & MOD_SMOOTH_Z)
 
3495
                                        v[2] = facm * v[2] + facw * fp[2];
 
3496
                        }
 
3497
 
 
3498
                }
 
3499
 
 
3500
                memset(ftmp, 0, 3*sizeof(float)*numVerts);
 
3501
                memset(uctmp, 0, sizeof(unsigned char)*numVerts);
 
3502
        }
 
3503
 
 
3504
        MEM_freeN(ftmp);
 
3505
        MEM_freeN(uctmp);
 
3506
}
 
3507
 
 
3508
static void smoothModifier_deformVerts(
 
3509
                ModifierData *md, Object *ob, DerivedMesh *derivedData,
 
3510
                float (*vertexCos)[3], int numVerts)
 
3511
{
 
3512
        DerivedMesh *dm;
 
3513
 
 
3514
        if(derivedData) dm = CDDM_copy(derivedData);
 
3515
        else dm = CDDM_from_mesh(ob->data, ob);
 
3516
 
 
3517
        CDDM_apply_vert_coords(dm, vertexCos);
 
3518
        CDDM_calc_normals(dm);
 
3519
 
 
3520
        smoothModifier_do((SmoothModifierData *)md, ob, dm,
 
3521
                vertexCos, numVerts);
 
3522
 
 
3523
        dm->release(dm);
 
3524
}
 
3525
 
 
3526
static void smoothModifier_deformVertsEM(
 
3527
                ModifierData *md, Object *ob, EditMesh *editData,
 
3528
                DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
 
3529
{
 
3530
        DerivedMesh *dm;
 
3531
 
 
3532
        if(derivedData) dm = CDDM_copy(derivedData);
 
3533
        else dm = CDDM_from_editmesh(editData, ob->data);
 
3534
 
 
3535
        CDDM_apply_vert_coords(dm, vertexCos);
 
3536
        CDDM_calc_normals(dm);
 
3537
 
 
3538
        smoothModifier_do((SmoothModifierData *)md, ob, dm,
 
3539
                vertexCos, numVerts);
 
3540
 
 
3541
        dm->release(dm);
 
3542
}
 
3543
 
 
3544
/* Cast */
 
3545
 
 
3546
static void castModifier_initData(ModifierData *md)
 
3547
{
 
3548
        CastModifierData *cmd = (CastModifierData*) md;
 
3549
 
 
3550
        cmd->fac = 0.5f;
 
3551
        cmd->radius = 0.0f;
 
3552
        cmd->size = 0.0f;
 
3553
        cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z
 
3554
                    | MOD_CAST_SIZE_FROM_RADIUS;
 
3555
        cmd->type = MOD_CAST_TYPE_SPHERE;
 
3556
        cmd->defgrp_name[0] = '\0';
 
3557
        cmd->object = NULL;
 
3558
}
 
3559
 
 
3560
 
 
3561
static void castModifier_copyData(ModifierData *md, ModifierData *target)
 
3562
{
 
3563
        CastModifierData *cmd = (CastModifierData*) md;
 
3564
        CastModifierData *tcmd = (CastModifierData*) target;
 
3565
 
 
3566
        tcmd->fac = cmd->fac;
 
3567
        tcmd->radius = cmd->radius;
 
3568
        tcmd->size = cmd->size;
 
3569
        tcmd->flag = cmd->flag;
 
3570
        tcmd->type = cmd->type;
 
3571
        tcmd->object = cmd->object;
 
3572
        strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32);
 
3573
}
 
3574
 
 
3575
int castModifier_isDisabled(ModifierData *md)
 
3576
{
 
3577
        CastModifierData *cmd = (CastModifierData*) md;
 
3578
        short flag;
 
3579
        
 
3580
        flag = cmd->flag & (MOD_CAST_X|MOD_CAST_Y|MOD_CAST_Z);
 
3581
 
 
3582
        if((cmd->fac == 0.0f) || flag == 0) return 1;
 
3583
 
 
3584
        return 0;
 
3585
}
 
3586
 
 
3587
CustomDataMask castModifier_requiredDataMask(ModifierData *md)
 
3588
{
 
3589
        CastModifierData *cmd = (CastModifierData *)md;
 
3590
        CustomDataMask dataMask = 0;
 
3591
 
 
3592
        /* ask for vertexgroups if we need them */
 
3593
        if(cmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
 
3594
 
 
3595
        return dataMask;
 
3596
}
 
3597
 
 
3598
static void castModifier_foreachObjectLink(
 
3599
                ModifierData *md, Object *ob,
 
3600
                void (*walk)(void *userData, Object *ob, Object **obpoin),
 
3601
                void *userData)
 
3602
{
 
3603
        CastModifierData *cmd = (CastModifierData*) md;
 
3604
 
 
3605
        walk (userData, ob, &cmd->object);
 
3606
}
 
3607
 
 
3608
static void castModifier_updateDepgraph(
 
3609
                ModifierData *md, DagForest *forest, Object *ob,
 
3610
                DagNode *obNode)
 
3611
{
 
3612
        CastModifierData *cmd = (CastModifierData*) md;
 
3613
 
 
3614
        if (cmd->object) {
 
3615
                DagNode *curNode = dag_get_node(forest, cmd->object);
 
3616
 
 
3617
                dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
 
3618
        }
 
3619
}
 
3620
 
 
3621
static void castModifier_sphere_do(
 
3622
                CastModifierData *cmd, Object *ob, DerivedMesh *dm,
 
3623
                float (*vertexCos)[3], int numVerts)
 
3624
{
 
3625
        MDeformVert *dvert = NULL;
 
3626
 
 
3627
        Object *ctrl_ob = NULL;
 
3628
 
 
3629
        int i, defgrp_index = -1;
 
3630
        int has_radius = 0;
 
3631
        short flag, type;
 
3632
        float fac, facm, len = 0.0f;
 
3633
        float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
 
3634
        float mat[4][4], imat[4][4];
 
3635
 
 
3636
        fac = cmd->fac;
 
3637
        facm = 1.0f - fac;
 
3638
 
 
3639
        flag = cmd->flag;
 
3640
        type = cmd->type; /* projection type: sphere or cylinder */
 
3641
 
 
3642
        if (type == MOD_CAST_TYPE_CYLINDER) 
 
3643
                flag &= ~MOD_CAST_Z;
 
3644
 
 
3645
        ctrl_ob = cmd->object;
 
3646
 
 
3647
        /* spherify's center is {0, 0, 0} (the ob's own center in its local
 
3648
         * space), by default, but if the user defined a control object,
 
3649
         * we use its location, transformed to ob's local space */
 
3650
        if (ctrl_ob) {
 
3651
                if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
3652
                        Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
 
3653
                        Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
 
3654
                        Mat4Invert(imat, mat);
 
3655
                }
 
3656
 
 
3657
                Mat4Invert(ob->imat, ob->obmat);
 
3658
                VECCOPY(center, ctrl_ob->obmat[3]);
 
3659
                Mat4MulVecfl(ob->imat, center);
 
3660
        }
 
3661
 
 
3662
        /* now we check which options the user wants */
 
3663
 
 
3664
        /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
 
3665
        /* 2) cmd->radius > 0.0f: only the vertices within this radius from
 
3666
         * the center of the effect should be deformed */
 
3667
        if (cmd->radius > FLT_EPSILON) has_radius = 1;
 
3668
 
 
3669
        /* 3) if we were given a vertex group name,
 
3670
         * only those vertices should be affected */
 
3671
        if (cmd->defgrp_name[0]) {
 
3672
                bDeformGroup *def;
 
3673
 
 
3674
                for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
 
3675
                        if (!strcmp(def->name, cmd->defgrp_name)) {
 
3676
                                defgrp_index = i;
 
3677
                                break;
 
3678
                        }
 
3679
                }
 
3680
        }
 
3681
 
 
3682
        if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
 
3683
                dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
 
3684
 
 
3685
        if(flag & MOD_CAST_SIZE_FROM_RADIUS) {
 
3686
                len = cmd->radius;
 
3687
        }
 
3688
        else {
 
3689
                len = cmd->size;
 
3690
        }
 
3691
 
 
3692
        if(len <= 0) {
 
3693
                for (i = 0; i < numVerts; i++) {
 
3694
                        len += VecLenf(center, vertexCos[i]);
 
3695
                }
 
3696
                len /= numVerts;
 
3697
 
 
3698
                if (len == 0.0f) len = 10.0f;
 
3699
        }
 
3700
 
 
3701
        /* ready to apply the effect, one vertex at a time;
 
3702
         * tiny optimization: the code is separated (with parts repeated)
 
3703
         * in two possible cases:
 
3704
         * with or w/o a vgroup. With lots of if's in the code below,
 
3705
         * further optimizations are possible, if needed */
 
3706
        if (dvert) { /* with a vgroup */
 
3707
                float fac_orig = fac;
 
3708
                for (i = 0; i < numVerts; i++) {
 
3709
                        MDeformWeight *dw = NULL;
 
3710
                        int j;
 
3711
                        float tmp_co[3];
 
3712
 
 
3713
                        VECCOPY(tmp_co, vertexCos[i]);
 
3714
                        if(ctrl_ob) {
 
3715
                                if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
3716
                                        Mat4MulVecfl(mat, tmp_co);
 
3717
                                } else {
 
3718
                                        VecSubf(tmp_co, tmp_co, center);
 
3719
                                }
 
3720
                        }
 
3721
 
 
3722
                        VECCOPY(vec, tmp_co);
 
3723
 
 
3724
                        if (type == MOD_CAST_TYPE_CYLINDER)
 
3725
                                vec[2] = 0.0f;
 
3726
 
 
3727
                        if (has_radius) {
 
3728
                                if (VecLength(vec) > cmd->radius) continue;
 
3729
                        }
 
3730
 
 
3731
                        for (j = 0; j < dvert[i].totweight; ++j) {
 
3732
                                if(dvert[i].dw[j].def_nr == defgrp_index) {
 
3733
                                        dw = &dvert[i].dw[j];
 
3734
                                        break;
 
3735
                                }
 
3736
                        }
 
3737
                        if (!dw) continue;
 
3738
 
 
3739
                        fac = fac_orig * dw->weight;
 
3740
                        facm = 1.0f - fac;
 
3741
 
 
3742
                        Normalize(vec);
 
3743
 
 
3744
                        if (flag & MOD_CAST_X)
 
3745
                                tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
 
3746
                        if (flag & MOD_CAST_Y)
 
3747
                                tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
 
3748
                        if (flag & MOD_CAST_Z)
 
3749
                                tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
 
3750
 
 
3751
                        if(ctrl_ob) {
 
3752
                                if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
3753
                                        Mat4MulVecfl(imat, tmp_co);
 
3754
                                } else {
 
3755
                                        VecAddf(tmp_co, tmp_co, center);
 
3756
                                }
 
3757
                        }
 
3758
 
 
3759
                        VECCOPY(vertexCos[i], tmp_co);
 
3760
                }
 
3761
                return;
 
3762
        }
 
3763
 
 
3764
        /* no vgroup */
 
3765
        for (i = 0; i < numVerts; i++) {
 
3766
                float tmp_co[3];
 
3767
 
 
3768
                VECCOPY(tmp_co, vertexCos[i]);
 
3769
                if(ctrl_ob) {
 
3770
                        if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
3771
                                Mat4MulVecfl(mat, tmp_co);
 
3772
                        } else {
 
3773
                                VecSubf(tmp_co, tmp_co, center);
 
3774
                        }
 
3775
                }
 
3776
 
 
3777
                VECCOPY(vec, tmp_co);
 
3778
 
 
3779
                if (type == MOD_CAST_TYPE_CYLINDER)
 
3780
                        vec[2] = 0.0f;
 
3781
 
 
3782
                if (has_radius) {
 
3783
                        if (VecLength(vec) > cmd->radius) continue;
 
3784
                }
 
3785
 
 
3786
                Normalize(vec);
 
3787
 
 
3788
                if (flag & MOD_CAST_X)
 
3789
                        tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
 
3790
                if (flag & MOD_CAST_Y)
 
3791
                        tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
 
3792
                if (flag & MOD_CAST_Z)
 
3793
                        tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
 
3794
 
 
3795
                if(ctrl_ob) {
 
3796
                        if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
3797
                                Mat4MulVecfl(imat, tmp_co);
 
3798
                        } else {
 
3799
                                VecAddf(tmp_co, tmp_co, center);
 
3800
                        }
 
3801
                }
 
3802
 
 
3803
                VECCOPY(vertexCos[i], tmp_co);
 
3804
        }
 
3805
}
 
3806
 
 
3807
static void castModifier_cuboid_do(
 
3808
                CastModifierData *cmd, Object *ob, DerivedMesh *dm,
 
3809
                float (*vertexCos)[3], int numVerts)
 
3810
{
 
3811
        MDeformVert *dvert = NULL;
 
3812
        Object *ctrl_ob = NULL;
 
3813
 
 
3814
        int i, defgrp_index = -1;
 
3815
        int has_radius = 0;
 
3816
        short flag;
 
3817
        float fac, facm;
 
3818
        float min[3], max[3], bb[8][3];
 
3819
        float center[3] = {0.0f, 0.0f, 0.0f};
 
3820
        float mat[4][4], imat[4][4];
 
3821
 
 
3822
        fac = cmd->fac;
 
3823
        facm = 1.0f - fac;
 
3824
 
 
3825
        flag = cmd->flag;
 
3826
 
 
3827
        ctrl_ob = cmd->object;
 
3828
 
 
3829
        /* now we check which options the user wants */
 
3830
 
 
3831
        /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
 
3832
        /* 2) cmd->radius > 0.0f: only the vertices within this radius from
 
3833
         * the center of the effect should be deformed */
 
3834
        if (cmd->radius > FLT_EPSILON) has_radius = 1;
 
3835
 
 
3836
        /* 3) if we were given a vertex group name,
 
3837
         * only those vertices should be affected */
 
3838
        if (cmd->defgrp_name[0]) {
 
3839
                bDeformGroup *def;
 
3840
 
 
3841
                for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
 
3842
                        if (!strcmp(def->name, cmd->defgrp_name)) {
 
3843
                                defgrp_index = i;
 
3844
                                break;
 
3845
                        }
 
3846
                }
 
3847
        }
 
3848
 
 
3849
        if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
 
3850
                dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
 
3851
 
 
3852
        if (ctrl_ob) {
 
3853
                if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
3854
                        Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
 
3855
                        Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
 
3856
                        Mat4Invert(imat, mat);
 
3857
                }
 
3858
 
 
3859
                Mat4Invert(ob->imat, ob->obmat);
 
3860
                VECCOPY(center, ctrl_ob->obmat[3]);
 
3861
                Mat4MulVecfl(ob->imat, center);
 
3862
        }
 
3863
 
 
3864
        if((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
 
3865
                for(i = 0; i < 3; i++) {
 
3866
                        min[i] = -cmd->radius;
 
3867
                        max[i] = cmd->radius;
 
3868
                }
 
3869
        } else if(!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
 
3870
                for(i = 0; i < 3; i++) {
 
3871
                        min[i] = -cmd->size;
 
3872
                        max[i] = cmd->size;
 
3873
                }
 
3874
        } else {
 
3875
                /* get bound box */
 
3876
                /* We can't use the object's bound box because other modifiers
 
3877
                 * may have changed the vertex data. */
 
3878
                INIT_MINMAX(min, max);
 
3879
 
 
3880
                /* Cast's center is the ob's own center in its local space,
 
3881
                 * by default, but if the user defined a control object, we use
 
3882
                 * its location, transformed to ob's local space. */
 
3883
                if (ctrl_ob) {
 
3884
                        float vec[3];
 
3885
 
 
3886
                        /* let the center of the ctrl_ob be part of the bound box: */
 
3887
                        DO_MINMAX(center, min, max);
 
3888
 
 
3889
                        for (i = 0; i < numVerts; i++) {
 
3890
                                VecSubf(vec, vertexCos[i], center);
 
3891
                                DO_MINMAX(vec, min, max);
 
3892
                        }
 
3893
                }
 
3894
                else {
 
3895
                        for (i = 0; i < numVerts; i++) {
 
3896
                                DO_MINMAX(vertexCos[i], min, max);
 
3897
                        }
 
3898
                }
 
3899
 
 
3900
                /* we want a symmetric bound box around the origin */
 
3901
                if (fabs(min[0]) > fabs(max[0])) max[0] = fabs(min[0]); 
 
3902
                if (fabs(min[1]) > fabs(max[1])) max[1] = fabs(min[1]); 
 
3903
                if (fabs(min[2]) > fabs(max[2])) max[2] = fabs(min[2]);
 
3904
                min[0] = -max[0];
 
3905
                min[1] = -max[1];
 
3906
                min[2] = -max[2];
 
3907
        }
 
3908
 
 
3909
        /* building our custom bounding box */
 
3910
        bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
 
3911
        bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
 
3912
        bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
 
3913
        bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
 
3914
        bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
 
3915
        bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
 
3916
 
 
3917
        /* ready to apply the effect, one vertex at a time;
 
3918
         * tiny optimization: the code is separated (with parts repeated)
 
3919
         * in two possible cases:
 
3920
         * with or w/o a vgroup. With lots of if's in the code below,
 
3921
         * further optimizations are possible, if needed */
 
3922
        if (dvert) { /* with a vgroup */
 
3923
                float fac_orig = fac;
 
3924
                for (i = 0; i < numVerts; i++) {
 
3925
                        MDeformWeight *dw = NULL;
 
3926
                        int j, octant, coord;
 
3927
                        float d[3], dmax, apex[3], fbb;
 
3928
                        float tmp_co[3];
 
3929
 
 
3930
                        VECCOPY(tmp_co, vertexCos[i]);
 
3931
                        if(ctrl_ob) {
 
3932
                                if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
3933
                                        Mat4MulVecfl(mat, tmp_co);
 
3934
                                } else {
 
3935
                                        VecSubf(tmp_co, tmp_co, center);
 
3936
                                }
 
3937
                        }
 
3938
 
 
3939
                        if (has_radius) {
 
3940
                                if (fabs(tmp_co[0]) > cmd->radius ||
 
3941
                                    fabs(tmp_co[1]) > cmd->radius ||
 
3942
                                    fabs(tmp_co[2]) > cmd->radius) continue;
 
3943
                        }
 
3944
 
 
3945
                        for (j = 0; j < dvert[i].totweight; ++j) {
 
3946
                                if(dvert[i].dw[j].def_nr == defgrp_index) {
 
3947
                                        dw = &dvert[i].dw[j];
 
3948
                                        break;
 
3949
                                }
 
3950
                        }
 
3951
                        if (!dw) continue;
 
3952
 
 
3953
                        fac = fac_orig * dw->weight;
 
3954
                        facm = 1.0f - fac;
 
3955
 
 
3956
                        /* The algo used to project the vertices to their
 
3957
                         * bounding box (bb) is pretty simple:
 
3958
                         * for each vertex v:
 
3959
                         * 1) find in which octant v is in;
 
3960
                         * 2) find which outer "wall" of that octant is closer to v;
 
3961
                         * 3) calculate factor (var fbb) to project v to that wall;
 
3962
                         * 4) project. */
 
3963
 
 
3964
                        /* find in which octant this vertex is in */
 
3965
                        octant = 0;
 
3966
                        if (tmp_co[0] > 0.0f) octant += 1;
 
3967
                        if (tmp_co[1] > 0.0f) octant += 2;
 
3968
                        if (tmp_co[2] > 0.0f) octant += 4;
 
3969
 
 
3970
                        /* apex is the bb's vertex at the chosen octant */
 
3971
                        VecCopyf(apex, bb[octant]);
 
3972
 
 
3973
                        /* find which bb plane is closest to this vertex ... */
 
3974
                        d[0] = tmp_co[0] / apex[0];
 
3975
                        d[1] = tmp_co[1] / apex[1];
 
3976
                        d[2] = tmp_co[2] / apex[2];
 
3977
 
 
3978
                        /* ... (the closest has the higher (closer to 1) d value) */
 
3979
                        dmax = d[0];
 
3980
                        coord = 0;
 
3981
                        if (d[1] > dmax) {
 
3982
                                dmax = d[1];
 
3983
                                coord = 1;
 
3984
                        }
 
3985
                        if (d[2] > dmax) {
 
3986
                                /* dmax = d[2]; */ /* commented, we don't need it */
 
3987
                                coord = 2;
 
3988
                        }
 
3989
 
 
3990
                        /* ok, now we know which coordinate of the vertex to use */
 
3991
 
 
3992
                        if (fabs(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
 
3993
                                continue;
 
3994
 
 
3995
                        /* finally, this is the factor we wanted, to project the vertex
 
3996
                         * to its bounding box (bb) */
 
3997
                        fbb = apex[coord] / tmp_co[coord];
 
3998
 
 
3999
                        /* calculate the new vertex position */
 
4000
                        if (flag & MOD_CAST_X)
 
4001
                                tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
 
4002
                        if (flag & MOD_CAST_Y)
 
4003
                                tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
 
4004
                        if (flag & MOD_CAST_Z)
 
4005
                                tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
 
4006
 
 
4007
                        if(ctrl_ob) {
 
4008
                                if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
4009
                                        Mat4MulVecfl(imat, tmp_co);
 
4010
                                } else {
 
4011
                                        VecAddf(tmp_co, tmp_co, center);
 
4012
                                }
 
4013
                        }
 
4014
 
 
4015
                        VECCOPY(vertexCos[i], tmp_co);
 
4016
                }
 
4017
                return;
 
4018
        }
 
4019
 
 
4020
        /* no vgroup (check previous case for comments about the code) */
 
4021
        for (i = 0; i < numVerts; i++) {
 
4022
                int octant, coord;
 
4023
                float d[3], dmax, fbb, apex[3];
 
4024
                float tmp_co[3];
 
4025
 
 
4026
                VECCOPY(tmp_co, vertexCos[i]);
 
4027
                if(ctrl_ob) {
 
4028
                        if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
4029
                                Mat4MulVecfl(mat, tmp_co);
 
4030
                        } else {
 
4031
                                VecSubf(tmp_co, tmp_co, center);
 
4032
                        }
 
4033
                }
 
4034
 
 
4035
                if (has_radius) {
 
4036
                        if (fabs(tmp_co[0]) > cmd->radius ||
 
4037
                            fabs(tmp_co[1]) > cmd->radius ||
 
4038
                            fabs(tmp_co[2]) > cmd->radius) continue;
 
4039
                }
 
4040
 
 
4041
                octant = 0;
 
4042
                if (tmp_co[0] > 0.0f) octant += 1;
 
4043
                if (tmp_co[1] > 0.0f) octant += 2;
 
4044
                if (tmp_co[2] > 0.0f) octant += 4;
 
4045
 
 
4046
                VecCopyf(apex, bb[octant]);
 
4047
 
 
4048
                d[0] = tmp_co[0] / apex[0];
 
4049
                d[1] = tmp_co[1] / apex[1];
 
4050
                d[2] = tmp_co[2] / apex[2];
 
4051
 
 
4052
                dmax = d[0];
 
4053
                coord = 0;
 
4054
                if (d[1] > dmax) {
 
4055
                        dmax = d[1];
 
4056
                        coord = 1;
 
4057
                }
 
4058
                if (d[2] > dmax) {
 
4059
                        /* dmax = d[2]; */ /* commented, we don't need it */
 
4060
                        coord = 2;
 
4061
                }
 
4062
 
 
4063
                if (fabs(tmp_co[coord]) < FLT_EPSILON)
 
4064
                        continue;
 
4065
 
 
4066
                fbb = apex[coord] / tmp_co[coord];
 
4067
 
 
4068
                if (flag & MOD_CAST_X)
 
4069
                        tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
 
4070
                if (flag & MOD_CAST_Y)
 
4071
                        tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
 
4072
                if (flag & MOD_CAST_Z)
 
4073
                        tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
 
4074
 
 
4075
                if(ctrl_ob) {
 
4076
                        if(flag & MOD_CAST_USE_OB_TRANSFORM) {
 
4077
                                Mat4MulVecfl(imat, tmp_co);
 
4078
                        } else {
 
4079
                                VecAddf(tmp_co, tmp_co, center);
 
4080
                        }
 
4081
                }
 
4082
 
 
4083
                VECCOPY(vertexCos[i], tmp_co);
 
4084
        }
 
4085
}
 
4086
 
 
4087
static void castModifier_deformVerts(
 
4088
                ModifierData *md, Object *ob, DerivedMesh *derivedData,
 
4089
                float (*vertexCos)[3], int numVerts)
 
4090
{
 
4091
        DerivedMesh *dm = derivedData;
 
4092
        CastModifierData *cmd = (CastModifierData *)md;
 
4093
 
 
4094
        if (!dm && ob->type == OB_MESH)
 
4095
                dm = CDDM_from_mesh(ob->data, ob);
 
4096
 
 
4097
        if (cmd->type == MOD_CAST_TYPE_CUBOID) {
 
4098
                castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
 
4099
        } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
 
4100
                castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
 
4101
        }
 
4102
 
 
4103
        if (!derivedData && dm) dm->release(dm);
 
4104
}
 
4105
 
 
4106
static void castModifier_deformVertsEM(
 
4107
                ModifierData *md, Object *ob, EditMesh *editData,
 
4108
                DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
 
4109
{
 
4110
        DerivedMesh *dm = derivedData;
 
4111
        CastModifierData *cmd = (CastModifierData *)md;
 
4112
 
 
4113
        if (!dm && ob->type == OB_MESH)
 
4114
                dm = CDDM_from_editmesh(editData, ob->data);
 
4115
 
 
4116
        if (cmd->type == MOD_CAST_TYPE_CUBOID) {
 
4117
                castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
 
4118
        } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
 
4119
                castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
 
4120
        }
 
4121
 
 
4122
        if (!derivedData && dm) dm->release(dm);
 
4123
}
 
4124
 
2968
4125
/* Wave */
2969
4126
 
2970
4127
static void waveModifier_initData(ModifierData *md) 
2971
4128
{
2972
4129
        WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
2973
4130
                
2974
 
        wmd->flag |= (WAV_X+WAV_Y+WAV_CYCL);
 
4131
        wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
 
4132
                      | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
2975
4133
        
2976
4134
        wmd->objectcenter = NULL;
 
4135
        wmd->texture = NULL;
 
4136
        wmd->map_object = NULL;
2977
4137
        wmd->height= 0.5f;
2978
4138
        wmd->width= 1.5f;
2979
4139
        wmd->speed= 0.5f;
2980
4140
        wmd->narrow= 1.5f;
2981
4141
        wmd->lifetime= 0.0f;
2982
4142
        wmd->damp= 10.0f;
 
4143
        wmd->texmapping = MOD_WAV_MAP_LOCAL;
 
4144
        wmd->defgrp_name[0] = 0;
2983
4145
}
2984
4146
 
2985
4147
static void waveModifier_copyData(ModifierData *md, ModifierData *target)
2998
4160
        twmd->timeoffs = wmd->timeoffs;
2999
4161
        twmd->width = wmd->width;
3000
4162
        twmd->objectcenter = wmd->objectcenter;
 
4163
        twmd->texture = wmd->texture;
 
4164
        twmd->map_object = wmd->map_object;
 
4165
        twmd->texmapping = wmd->texmapping;
 
4166
        strncpy(twmd->defgrp_name, wmd->defgrp_name, 32);
3001
4167
}
3002
4168
 
3003
4169
static int waveModifier_dependsOnTime(ModifierData *md)
3006
4172
}
3007
4173
 
3008
4174
static void waveModifier_foreachObjectLink(
3009
 
                ModifierData *md, Object *ob,
3010
 
                void (*walk)(void *userData, Object *ob, Object **obpoin),
3011
 
                void *userData)
 
4175
                                    ModifierData *md, Object *ob,
 
4176
                                    ObjectWalkFunc walk, void *userData)
3012
4177
{
3013
4178
        WaveModifierData *wmd = (WaveModifierData*) md;
3014
4179
 
3015
4180
        walk(userData, ob, &wmd->objectcenter);
 
4181
        walk(userData, ob, &wmd->map_object);
 
4182
}
 
4183
 
 
4184
static void waveModifier_foreachIDLink(ModifierData *md, Object *ob,
 
4185
                                       IDWalkFunc walk, void *userData)
 
4186
{
 
4187
        WaveModifierData *wmd = (WaveModifierData*) md;
 
4188
 
 
4189
        walk(userData, ob, (ID **)&wmd->texture);
 
4190
 
 
4191
        waveModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
3016
4192
}
3017
4193
 
3018
4194
static void waveModifier_updateDepgraph(
3026
4202
 
3027
4203
                dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
3028
4204
        }
3029
 
}
3030
 
 
3031
 
static void waveModifier_deformVerts(
3032
 
                ModifierData *md, Object *ob, DerivedMesh *derivedData,
 
4205
 
 
4206
        if(wmd->map_object) {
 
4207
                DagNode *curNode = dag_get_node(forest, wmd->map_object);
 
4208
 
 
4209
                dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
 
4210
        }
 
4211
}
 
4212
 
 
4213
CustomDataMask waveModifier_requiredDataMask(ModifierData *md)
 
4214
{
 
4215
        WaveModifierData *wmd = (WaveModifierData *)md;
 
4216
        CustomDataMask dataMask = 0;
 
4217
 
 
4218
 
 
4219
        /* ask for UV coordinates if we need them */
 
4220
        if(wmd->texture && wmd->texmapping == MOD_WAV_MAP_UV)
 
4221
                dataMask |= (1 << CD_MTFACE);
 
4222
 
 
4223
        /* ask for vertexgroups if we need them */
 
4224
        if(wmd->defgrp_name[0])
 
4225
                dataMask |= (1 << CD_MDEFORMVERT);
 
4226
 
 
4227
        return dataMask;
 
4228
}
 
4229
 
 
4230
static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
 
4231
                               DerivedMesh *dm,
 
4232
                               float (*co)[3], float (*texco)[3],
 
4233
                               int numVerts)
 
4234
{
 
4235
        int i;
 
4236
        int texmapping = wmd->texmapping;
 
4237
 
 
4238
        if(texmapping == MOD_WAV_MAP_OBJECT) {
 
4239
                if(wmd->map_object)
 
4240
                        Mat4Invert(wmd->map_object->imat, wmd->map_object->obmat);
 
4241
                else /* if there is no map object, default to local */
 
4242
                        texmapping = MOD_WAV_MAP_LOCAL;
 
4243
        }
 
4244
 
 
4245
        /* UVs need special handling, since they come from faces */
 
4246
        if(texmapping == MOD_WAV_MAP_UV) {
 
4247
                if(dm->getFaceDataArray(dm, CD_MTFACE)) {
 
4248
                        MFace *mface = dm->getFaceArray(dm);
 
4249
                        MFace *mf;
 
4250
                        char *done = MEM_callocN(sizeof(*done) * numVerts,
 
4251
                                                 "get_texture_coords done");
 
4252
                        int numFaces = dm->getNumFaces(dm);
 
4253
                        MTFace *tf;
 
4254
 
 
4255
                        validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name);
 
4256
 
 
4257
                        tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
 
4258
                                                        wmd->uvlayer_name);
 
4259
 
 
4260
                        /* verts are given the UV from the first face that uses them */
 
4261
                        for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
 
4262
                                if(!done[mf->v1]) {
 
4263
                                        texco[mf->v1][0] = tf->uv[0][0];
 
4264
                                        texco[mf->v1][1] = tf->uv[0][1];
 
4265
                                        texco[mf->v1][2] = 0;
 
4266
                                        done[mf->v1] = 1;
 
4267
                                }
 
4268
                                if(!done[mf->v2]) {
 
4269
                                        texco[mf->v2][0] = tf->uv[1][0];
 
4270
                                        texco[mf->v2][1] = tf->uv[1][1];
 
4271
                                        texco[mf->v2][2] = 0;
 
4272
                                        done[mf->v2] = 1;
 
4273
                                }
 
4274
                                if(!done[mf->v3]) {
 
4275
                                        texco[mf->v3][0] = tf->uv[2][0];
 
4276
                                        texco[mf->v3][1] = tf->uv[2][1];
 
4277
                                        texco[mf->v3][2] = 0;
 
4278
                                        done[mf->v3] = 1;
 
4279
                                }
 
4280
                                if(!done[mf->v4]) {
 
4281
                                        texco[mf->v4][0] = tf->uv[3][0];
 
4282
                                        texco[mf->v4][1] = tf->uv[3][1];
 
4283
                                        texco[mf->v4][2] = 0;
 
4284
                                        done[mf->v4] = 1;
 
4285
                                }
 
4286
                        }
 
4287
 
 
4288
                        /* remap UVs from [0, 1] to [-1, 1] */
 
4289
                        for(i = 0; i < numVerts; ++i) {
 
4290
                                texco[i][0] = texco[i][0] * 2 - 1;
 
4291
                                texco[i][1] = texco[i][1] * 2 - 1;
 
4292
                        }
 
4293
 
 
4294
                        MEM_freeN(done);
 
4295
                        return;
 
4296
                } else /* if there are no UVs, default to local */
 
4297
                        texmapping = MOD_WAV_MAP_LOCAL;
 
4298
        }
 
4299
 
 
4300
        for(i = 0; i < numVerts; ++i, ++co, ++texco) {
 
4301
                switch(texmapping) {
 
4302
                case MOD_WAV_MAP_LOCAL:
 
4303
                        VECCOPY(*texco, *co);
 
4304
                        break;
 
4305
                case MOD_WAV_MAP_GLOBAL:
 
4306
                        VECCOPY(*texco, *co);
 
4307
                        Mat4MulVecfl(ob->obmat, *texco);
 
4308
                        break;
 
4309
                case MOD_WAV_MAP_OBJECT:
 
4310
                        VECCOPY(*texco, *co);
 
4311
                        Mat4MulVecfl(ob->obmat, *texco);
 
4312
                        Mat4MulVecfl(wmd->map_object->imat, *texco);
 
4313
                        break;
 
4314
                }
 
4315
        }
 
4316
}
 
4317
 
 
4318
static void waveModifier_do(
 
4319
                WaveModifierData *md, Object *ob, DerivedMesh *dm,
3033
4320
                float (*vertexCos)[3], int numVerts)
3034
4321
{
3035
4322
        WaveModifierData *wmd = (WaveModifierData*) md;
 
4323
        MVert *mvert = NULL;
 
4324
        MDeformVert *dvert = NULL;
 
4325
        int defgrp_index;
3036
4326
        float ctime = bsystem_time(ob, 0, (float)G.scene->r.cfra, 0.0);
3037
4327
        float minfac =
3038
4328
          (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
3039
4329
        float lifefac = wmd->height;
 
4330
        float (*tex_co)[3];
 
4331
 
 
4332
        if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH)
 
4333
                mvert = dm->getVertArray(dm);
3040
4334
 
3041
4335
        if(wmd->objectcenter){
3042
4336
                float mat[4][4];
3048
4342
                wmd->starty = mat[3][1];
3049
4343
        }
3050
4344
 
 
4345
        /* get the index of the deform group */
 
4346
        defgrp_index = -1;
 
4347
 
 
4348
        if(wmd->defgrp_name[0]) {
 
4349
                int i;
 
4350
                bDeformGroup *def;
 
4351
                for(i = 0, def = ob->defbase.first; def; def = def->next, i++) {
 
4352
                        if(!strcmp(def->name, wmd->defgrp_name)) {
 
4353
                                defgrp_index = i;
 
4354
                                break;
 
4355
                        }
 
4356
                }
 
4357
        }
 
4358
 
 
4359
        if(defgrp_index >= 0){
 
4360
                dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
 
4361
        }
 
4362
 
3051
4363
        if(wmd->damp == 0) wmd->damp = 10.0f;
3052
4364
 
3053
4365
        if(wmd->lifetime != 0.0) {
3062
4374
                }
3063
4375
        }
3064
4376
 
 
4377
        if(wmd->texture) {
 
4378
                tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
 
4379
                                     "waveModifier_do tex_co");
 
4380
                wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts);
 
4381
        }
 
4382
 
3065
4383
        if(lifefac != 0.0) {
3066
4384
                int i;
3067
4385
 
3070
4388
                        float x = co[0] - wmd->startx;
3071
4389
                        float y = co[1] - wmd->starty;
3072
4390
                        float amplit= 0.0f;
3073
 
 
3074
 
                        if(wmd->flag & WAV_X) {
3075
 
                                if(wmd->flag & WAV_Y) amplit = (float)sqrt(x*x + y*y);
 
4391
                        TexResult texres;
 
4392
                        MDeformWeight *def_weight = NULL;
 
4393
 
 
4394
                        /* get weights */
 
4395
                        if(dvert) {
 
4396
                                int j;
 
4397
                                for(j = 0; j < dvert[i].totweight; ++j) {
 
4398
                                        if(dvert[i].dw[j].def_nr == defgrp_index) {
 
4399
                                                def_weight = &dvert[i].dw[j];
 
4400
                                                break;
 
4401
                                        }
 
4402
                                }
 
4403
 
 
4404
                                /* if this vert isn't in the vgroup, don't deform it */
 
4405
                                if(!def_weight) continue;
 
4406
                        }
 
4407
 
 
4408
                        if(wmd->texture) {
 
4409
                                texres.nor = NULL;
 
4410
                                get_texture_value(wmd->texture, tex_co[i], &texres);
 
4411
                        }
 
4412
 
 
4413
 
 
4414
                        if(wmd->flag & MOD_WAVE_X) {
 
4415
                                if(wmd->flag & MOD_WAVE_Y) amplit = (float)sqrt(x*x + y*y);
3076
4416
                                else amplit = x;
3077
4417
                        }
3078
 
                        else if(wmd->flag & WAV_Y) 
 
4418
                        else if(wmd->flag & MOD_WAVE_Y) 
3079
4419
                                amplit= y;
3080
4420
                        
3081
4421
                        /* this way it makes nice circles */
3082
4422
                        amplit -= (ctime - wmd->timeoffs) * wmd->speed;
3083
4423
 
3084
 
                        if(wmd->flag & WAV_CYCL) {
 
4424
                        if(wmd->flag & MOD_WAVE_CYCL) {
3085
4425
                                amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width)
3086
4426
                                         + wmd->width;
3087
4427
                        }
3090
4430
                        if(amplit > -wmd->width && amplit < wmd->width) {
3091
4431
                                amplit = amplit * wmd->narrow;
3092
4432
                                amplit = (float)(1.0 / exp(amplit * amplit) - minfac);
3093
 
 
3094
 
                                co[2] += lifefac * amplit;
 
4433
                                if(wmd->texture)
 
4434
                                        amplit = amplit * texres.tin;
 
4435
 
 
4436
                                if(def_weight)
 
4437
                                        amplit = amplit * def_weight->weight;
 
4438
 
 
4439
                                if(mvert) {
 
4440
                                        /* move along normals */
 
4441
                                        if(wmd->flag & MOD_WAVE_NORM_X) {
 
4442
                                                co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
 
4443
                                        }
 
4444
                                        if(wmd->flag & MOD_WAVE_NORM_Y) {
 
4445
                                                co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
 
4446
                                        }
 
4447
                                        if(wmd->flag & MOD_WAVE_NORM_Z) {
 
4448
                                                co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
 
4449
                                        }
 
4450
                                }
 
4451
                                else {
 
4452
                                        /* move along local z axis */
 
4453
                                        co[2] += lifefac * amplit;
 
4454
                                }
3095
4455
                        }
3096
4456
                }
3097
4457
        }
 
4458
 
 
4459
        if(wmd->texture) MEM_freeN(tex_co);
 
4460
}
 
4461
 
 
4462
static void waveModifier_deformVerts(
 
4463
                ModifierData *md, Object *ob, DerivedMesh *derivedData,
 
4464
                float (*vertexCos)[3], int numVerts)
 
4465
{
 
4466
        DerivedMesh *dm;
 
4467
        WaveModifierData *wmd = (WaveModifierData *)md;
 
4468
 
 
4469
        if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM))
 
4470
                dm = derivedData;
 
4471
        else if(derivedData) dm = derivedData;
 
4472
        else if(ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
 
4473
        else return;
 
4474
 
 
4475
        if(wmd->flag & MOD_WAVE_NORM) {
 
4476
                CDDM_apply_vert_coords(dm, vertexCos);
 
4477
                CDDM_calc_normals(dm);
 
4478
        }
 
4479
 
 
4480
        waveModifier_do(wmd, ob, dm, vertexCos, numVerts);
 
4481
 
 
4482
        if(dm != derivedData) dm->release(dm);
3098
4483
}
3099
4484
 
3100
4485
static void waveModifier_deformVertsEM(
3101
4486
                ModifierData *md, Object *ob, EditMesh *editData,
3102
4487
                DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
3103
4488
{
3104
 
        waveModifier_deformVerts(md, ob, NULL, vertexCos, numVerts);
 
4489
        DerivedMesh *dm;
 
4490
        WaveModifierData *wmd = (WaveModifierData *)md;
 
4491
 
 
4492
        if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM))
 
4493
                dm = derivedData;
 
4494
        else if(derivedData) dm = derivedData;
 
4495
        else dm = CDDM_from_editmesh(editData, ob->data);
 
4496
 
 
4497
        if(wmd->flag & MOD_WAVE_NORM) {
 
4498
                CDDM_apply_vert_coords(dm, vertexCos);
 
4499
                CDDM_calc_normals(dm);
 
4500
        }
 
4501
 
 
4502
        waveModifier_do(wmd, ob, dm, vertexCos, numVerts);
 
4503
 
 
4504
        if(dm != derivedData) dm->release(dm);
3105
4505
}
3106
4506
 
3107
4507
/* Armature */
3612
5012
                mti->copyData = decimateModifier_copyData;
3613
5013
                mti->applyModifier = decimateModifier_applyModifier;
3614
5014
 
 
5015
                mti = INIT_TYPE(Smooth);
 
5016
                mti->type = eModifierTypeType_OnlyDeform;
 
5017
                mti->flags = eModifierTypeFlag_AcceptsMesh
 
5018
                             | eModifierTypeFlag_SupportsEditmode;
 
5019
                mti->initData = smoothModifier_initData;
 
5020
                mti->copyData = smoothModifier_copyData;
 
5021
                mti->requiredDataMask = smoothModifier_requiredDataMask;
 
5022
                mti->deformVerts = smoothModifier_deformVerts;
 
5023
                mti->deformVertsEM = smoothModifier_deformVertsEM;
 
5024
 
 
5025
                mti = INIT_TYPE(Cast);
 
5026
                mti->type = eModifierTypeType_OnlyDeform;
 
5027
                mti->flags = eModifierTypeFlag_AcceptsCVs
 
5028
                             | eModifierTypeFlag_SupportsEditmode;
 
5029
                mti->initData = castModifier_initData;
 
5030
                mti->copyData = castModifier_copyData;
 
5031
                mti->requiredDataMask = castModifier_requiredDataMask;
 
5032
                mti->foreachObjectLink = castModifier_foreachObjectLink;
 
5033
                mti->updateDepgraph = castModifier_updateDepgraph;
 
5034
                mti->deformVerts = castModifier_deformVerts;
 
5035
                mti->deformVertsEM = castModifier_deformVertsEM;
 
5036
 
3615
5037
                mti = INIT_TYPE(Wave);
3616
5038
                mti->type = eModifierTypeType_OnlyDeform;
3617
5039
                mti->flags = eModifierTypeFlag_AcceptsCVs
3619
5041
                mti->initData = waveModifier_initData;
3620
5042
                mti->copyData = waveModifier_copyData;
3621
5043
                mti->dependsOnTime = waveModifier_dependsOnTime;
 
5044
                mti->requiredDataMask = waveModifier_requiredDataMask;
3622
5045
                mti->foreachObjectLink = waveModifier_foreachObjectLink;
 
5046
                mti->foreachIDLink = waveModifier_foreachIDLink;
3623
5047
                mti->updateDepgraph = waveModifier_updateDepgraph;
3624
5048
                mti->deformVerts = waveModifier_deformVerts;
3625
5049
                mti->deformVertsEM = waveModifier_deformVertsEM;