Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-04-12 02:12:30 +0400
committerCampbell Barton <ideasman42@gmail.com>2010-04-12 02:12:30 +0400
commit3fdaf5cecc9c7c521c4db514f916f083b17881a6 (patch)
treefabdb833cab9ba68321fe9687abb5a44fd303798 /source/blender
parent139a0e7cb8a9003baa3d50d6d99d7f437b1d1899 (diff)
[#14437] Modifier Stack Refactor
patch by Ben Batt (artificer) Updated patch for 6 or so modifiers added since the patch was written. - tested with CMake and SCons - fixed one error were flags were being added to the fluids type. - remove BKE_simple_deform.h, simple_deform.c, move functions into MOD_simpledeform.c since there were problems with circular deps. - moved some fluid and boolean functions used by modifiers too.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/Makefile2
-rw-r--r--source/blender/SConscript1
-rw-r--r--source/blender/blenkernel/BKE_booleanops.h16
-rw-r--r--source/blender/blenkernel/BKE_fluidsim.h14
-rw-r--r--source/blender/blenkernel/CMakeLists.txt3
-rw-r--r--source/blender/blenkernel/SConscript2
-rw-r--r--source/blender/blenkernel/intern/booleanops.c595
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c579
-rw-r--r--source/blender/blenkernel/intern/modifier.c9894
-rw-r--r--source/blender/blenkernel/intern/simple_deform.c255
-rw-r--r--source/blender/modifiers/CMakeLists.txt63
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h71
-rw-r--r--source/blender/modifiers/Makefile34
-rw-r--r--source/blender/modifiers/SConscript17
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c219
-rw-r--r--source/blender/modifiers/intern/MOD_array.c813
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c184
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c182
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c594
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.h50
-rw-r--r--source/blender/modifiers/intern/MOD_build.c342
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c667
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c244
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c292
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c195
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c243
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c396
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c1337
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c939
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c198
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.c669
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.h (renamed from source/blender/blenkernel/BKE_simple_deform.h)20
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c320
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c189
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c449
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c422
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c392
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c157
-rw-r--r--source/blender/modifiers/intern/MOD_none.c70
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c374
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c273
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c925
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c157
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c218
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c424
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c181
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c313
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c125
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c692
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c185
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c228
-rw-r--r--source/blender/modifiers/intern/MOD_util.c173
-rw-r--r--source/blender/modifiers/intern/MOD_util.h45
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c491
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c497
56 files changed, 15132 insertions, 11299 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 6263261ae1c..16437737302 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -29,6 +29,7 @@ ADD_SUBDIRECTORY(editors)
ADD_SUBDIRECTORY(avi)
ADD_SUBDIRECTORY(nodes)
ADD_SUBDIRECTORY(blenkernel)
+ADD_SUBDIRECTORY(modifiers)
ADD_SUBDIRECTORY(blenlib)
ADD_SUBDIRECTORY(blenloader)
ADD_SUBDIRECTORY(blenpluginapi)
diff --git a/source/blender/Makefile b/source/blender/Makefile
index 1c4ff6935b9..1149e1c4be2 100644
--- a/source/blender/Makefile
+++ b/source/blender/Makefile
@@ -33,7 +33,7 @@ include nan_definitions.mk
DIRS = windowmanager editors blenloader readblenfile
DIRS += avi imbuf render blenlib blenkernel blenpluginapi
DIRS += makesdna makesrna
-DIRS += python nodes gpu
+DIRS += python nodes modifiers gpu
DIRS += blenfont ikplugin
ifeq ($(WITH_QUICKTIME), true)
diff --git a/source/blender/SConscript b/source/blender/SConscript
index 9910db1902f..98e8ad73199 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -16,6 +16,7 @@ SConscript(['avi/SConscript',
'readblenfile/SConscript',
'render/SConscript',
'nodes/SConscript',
+ 'modifiers/SConscript',
'ikplugin/SConscript',
'windowmanager/SConscript',
'blenfont/SConscript'])
diff --git a/source/blender/blenkernel/BKE_booleanops.h b/source/blender/blenkernel/BKE_booleanops.h
index dcf71645db3..a213d63cc03 100644
--- a/source/blender/blenkernel/BKE_booleanops.h
+++ b/source/blender/blenkernel/BKE_booleanops.h
@@ -29,21 +29,5 @@
#ifndef BKE_BOOLEANOPS_H
#define BKE_BOOLEANOPS_H
-struct Scene;
-struct Object;
-struct Base;
-struct DerivedMesh;
-
-/* Performs a boolean between two mesh objects, it is assumed that both objects
- are in fact a mesh object. On success returns 1 and creates a new mesh object
- into blender data structures. On failure returns 0 and reports an error. */
-int NewBooleanMesh(struct Scene *scene, struct Base *base, struct Base *base_select, int op);
-
-
-/* Performs a boolean between two mesh objects, it is assumed that both objects
- are in fact mesh object. On success returns a DerivedMesh. On failure
- returns NULL and reports an error. */
-struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob, struct DerivedMesh *dm_select, struct Object *ob_select,
- int int_op_type);
#endif
diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h
index d99e7b42cff..da43ae7f28b 100644
--- a/source/blender/blenkernel/BKE_fluidsim.h
+++ b/source/blender/blenkernel/BKE_fluidsim.h
@@ -30,6 +30,7 @@
#ifndef BKE_FLUIDSIM_H
#define BKE_FLUIDSIM_H
+
struct Object;
struct Scene;
struct FluidsimModifierData;
@@ -37,25 +38,12 @@ struct DerivedMesh;
struct MVert;
/* old interface */
-struct FluidsimSettings *fluidsimSettingsNew(struct Object *srcob);
void initElbeemMesh(struct Scene *scene, struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords, int modifierIndex);
-/* new fluid-modifier interface */
-void fluidsim_init(struct FluidsimModifierData *fluidmd);
-void fluidsim_free(struct FluidsimModifierData *fluidmd);
-
-struct DerivedMesh *fluidsim_read_cache(struct Object *ob, struct DerivedMesh *orgdm,
- struct FluidsimModifierData *fluidmd, int framenr, int useRenderParams);
-void fluidsim_read_vel_cache(struct FluidsimModifierData *fluidmd, struct DerivedMesh *dm,
- char *filename);
-struct DerivedMesh *fluidsimModifier_do(struct FluidsimModifierData *fluidmd,
- struct Scene *scene, struct Object *ob, struct DerivedMesh *dm,
- int useRenderParams, int isFinalCalc);
-
/* bounding box & memory estimate */
void fluid_get_bb(struct MVert *mvert, int totvert, float obmat[][4],
float start[3], float size[3]);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index da5e73bbb45..afb29fbcd62 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -27,7 +27,7 @@
FILE(GLOB SRC intern/*.c)
SET(INC
- . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna
+ . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../modifiers
../render/extern/include ../../../intern/decimation/extern
../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
../../../intern/iksolver/extern ../blenloader ../ikplugin
@@ -38,6 +38,7 @@ SET(INC
${ZLIB_INC}
)
+
ADD_DEFINITIONS(-DGLEW_STATIC)
IF(WITH_BULLET)
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 37a63be6389..57d7e45d986 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -6,7 +6,7 @@ sources = env.Glob('intern/*.c')
incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include'
incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager'
incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna'
-incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes'
+incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers'
incs += ' #/intern/iksolver/extern ../blenloader'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/opennl/extern #/intern/bsp/extern'
diff --git a/source/blender/blenkernel/intern/booleanops.c b/source/blender/blenkernel/intern/booleanops.c
index 3e43dfbb4d5..e69de29bb2d 100644
--- a/source/blender/blenkernel/intern/booleanops.c
+++ b/source/blender/blenkernel/intern/booleanops.c
@@ -1,595 +0,0 @@
-/**
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- * CSG operations.
- */
-
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_math.h"
-#include "BLI_ghash.h"
-
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "CSG_BooleanOps.h"
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_depsgraph.h"
-#include "BKE_material.h"
-#include "BKE_mesh.h"
-#include "BKE_object.h"
-
-
-
-/**
- * Here's the vertex iterator structure used to walk through
- * the blender vertex structure.
- */
-
-typedef struct {
- DerivedMesh *dm;
- Object *ob;
- int pos;
-} VertexIt;
-
-/**
- * Implementations of local vertex iterator functions.
- * These describe a blender mesh to the CSG module.
- */
-
-static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator)
-{
- if (iterator->it) {
- // deallocate memory for iterator
- MEM_freeN(iterator->it);
- iterator->it = 0;
- }
- iterator->Done = NULL;
- iterator->Fill = NULL;
- iterator->Reset = NULL;
- iterator->Step = NULL;
- iterator->num_elements = 0;
-
-}
-
-static int VertexIt_Done(CSG_IteratorPtr it)
-{
- VertexIt * iterator = (VertexIt *)it;
- return(iterator->pos >= iterator->dm->getNumVerts(iterator->dm));
-}
-
-static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert)
-{
- VertexIt * iterator = (VertexIt *)it;
- MVert *verts = iterator->dm->getVertArray(iterator->dm);
-
- float global_pos[3];
-
- /* boolean happens in global space, transform both with obmat */
- mul_v3_m4v3(
- global_pos,
- iterator->ob->obmat,
- verts[iterator->pos].co
- );
-
- vert->position[0] = global_pos[0];
- vert->position[1] = global_pos[1];
- vert->position[2] = global_pos[2];
-}
-
-static void VertexIt_Step(CSG_IteratorPtr it)
-{
- VertexIt * iterator = (VertexIt *)it;
- iterator->pos ++;
-}
-
-static void VertexIt_Reset(CSG_IteratorPtr it)
-{
- VertexIt * iterator = (VertexIt *)it;
- iterator->pos = 0;
-}
-
-static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh *dm, Object *ob)
-{
-
- VertexIt *it;
- if (output == 0) return;
-
- // allocate some memory for blender iterator
- it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt"));
- if (it == 0) {
- return;
- }
- // assign blender specific variables
- it->dm = dm;
- it->ob = ob; // needed for obmat transformations
-
- it->pos = 0;
-
- // assign iterator function pointers.
- output->Step = VertexIt_Step;
- output->Fill = VertexIt_Fill;
- output->Done = VertexIt_Done;
- output->Reset = VertexIt_Reset;
- output->num_elements = it->dm->getNumVerts(it->dm);
- output->it = it;
-}
-
-/**
- * Blender Face iterator
- */
-
-typedef struct {
- DerivedMesh *dm;
- int pos;
- int offset;
- int flip;
-} FaceIt;
-
-static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator)
-{
- MEM_freeN(iterator->it);
- iterator->Done = NULL;
- iterator->Fill = NULL;
- iterator->Reset = NULL;
- iterator->Step = NULL;
- iterator->num_elements = 0;
-}
-
-static int FaceIt_Done(CSG_IteratorPtr it)
-{
- // assume CSG_IteratorPtr is of the correct type.
- FaceIt * iterator = (FaceIt *)it;
- return(iterator->pos >= iterator->dm->getNumFaces(iterator->dm));
-}
-
-static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face)
-{
- // assume CSG_IteratorPtr is of the correct type.
- FaceIt *face_it = (FaceIt *)it;
- MFace *mfaces = face_it->dm->getFaceArray(face_it->dm);
- MFace *mface = &mfaces[face_it->pos];
-
- /* reverse face vertices if necessary */
- face->vertex_index[1] = mface->v2;
- if( face_it->flip == 0 ) {
- face->vertex_index[0] = mface->v1;
- face->vertex_index[2] = mface->v3;
- } else {
- face->vertex_index[2] = mface->v1;
- face->vertex_index[0] = mface->v3;
- }
- if (mface->v4) {
- face->vertex_index[3] = mface->v4;
- face->vertex_number = 4;
- } else {
- face->vertex_number = 3;
- }
-
- face->orig_face = face_it->offset + face_it->pos;
-}
-
-static void FaceIt_Step(CSG_IteratorPtr it)
-{
- FaceIt * face_it = (FaceIt *)it;
- face_it->pos ++;
-}
-
-static void FaceIt_Reset(CSG_IteratorPtr it)
-{
- FaceIt * face_it = (FaceIt *)it;
- face_it->pos = 0;
-}
-
-static void FaceIt_Construct(
- CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset, Object *ob)
-{
- FaceIt *it;
- if (output == 0) return;
-
- // allocate some memory for blender iterator
- it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt"));
- if (it == 0) {
- return ;
- }
- // assign blender specific variables
- it->dm = dm;
- it->offset = offset;
- it->pos = 0;
-
- /* determine if we will need to reverse order of face vertices */
- if (ob->size[0] < 0.0f) {
- if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) {
- it->flip = 1;
- } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) {
- it->flip = 1;
- } else {
- it->flip = 0;
- }
- } else {
- if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) {
- it->flip = 0;
- } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) {
- it->flip = 0;
- } else {
- it->flip = 1;
- }
- }
-
- // assign iterator function pointers.
- output->Step = FaceIt_Step;
- output->Fill = FaceIt_Fill;
- output->Done = FaceIt_Done;
- output->Reset = FaceIt_Reset;
- output->num_elements = it->dm->getNumFaces(it->dm);
- output->it = it;
-}
-
-static Object *AddNewBlenderMesh(Scene *scene, Base *base)
-{
- // This little function adds a new mesh object to the blender object list
- // It uses ob to duplicate data as this seems to be easier than creating
- // a new one. This new oject contains no faces nor vertices.
- Mesh *old_me;
- Base *basen;
- Object *ob_new;
-
- // now create a new blender object.
- // duplicating all the settings from the previous object
- // to the new one.
- ob_new= copy_object(base->object);
-
- // Ok we don't want to use the actual data from the
- // last object, the above function incremented the
- // number of users, so decrement it here.
- old_me= ob_new->data;
- old_me->id.us--;
-
- // Now create a new base to add into the linked list of
- // vase objects.
-
- basen= MEM_mallocN(sizeof(Base), "duplibase");
- *basen= *base;
- BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */
- basen->object= ob_new;
- basen->flag &= ~SELECT;
-
- // Initialize the mesh data associated with this object.
- ob_new->data= add_mesh("Mesh");
-
- // Finally assign the object type.
- ob_new->type= OB_MESH;
-
- return ob_new;
-}
-
-static void InterpCSGFace(
- DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr,
- float mapmat[][4])
-{
- float obco[3], *co[4], *orig_co[4], w[4][4];
- MFace *mface, *orig_mface;
- int j;
-
- mface = CDDM_get_face(dm, index);
- orig_mface = orig_dm->getFaceArray(orig_dm) + orig_index;
-
- // get the vertex coordinates from the original mesh
- orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co;
- orig_co[1] = (orig_dm->getVertArray(orig_dm) + orig_mface->v2)->co;
- orig_co[2] = (orig_dm->getVertArray(orig_dm) + orig_mface->v3)->co;
- orig_co[3] = (orig_mface->v4)? (orig_dm->getVertArray(orig_dm) + orig_mface->v4)->co: NULL;
-
- // get the vertex coordinates from the new derivedmesh
- co[0] = CDDM_get_vert(dm, mface->v1)->co;
- co[1] = CDDM_get_vert(dm, mface->v2)->co;
- co[2] = CDDM_get_vert(dm, mface->v3)->co;
- co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL;
-
- for (j = 0; j < nr; j++) {
- // get coordinate into the space of the original mesh
- if (mapmat)
- mul_v3_m4v3(obco, mapmat, co[j]);
- else
- copy_v3_v3(obco, co[j]);
-
- interp_weights_face_v3( w[j],orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco);
- }
-
- CustomData_interp(&orig_dm->faceData, &dm->faceData, &orig_index, NULL, (float*)w, 1, index);
-}
-
-/* Iterate over the CSG Output Descriptors and create a new DerivedMesh
- from them */
-static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
- CSG_FaceIteratorDescriptor *face_it,
- CSG_VertexIteratorDescriptor *vertex_it,
- float parinv[][4],
- float mapmat[][4],
- Material **mat,
- int *totmat,
- DerivedMesh *dm1,
- Object *ob1,
- DerivedMesh *dm2,
- Object *ob2)
-{
- DerivedMesh *result, *orig_dm;
- GHash *material_hash = NULL;
- Mesh *me1= (Mesh*)ob1->data;
- Mesh *me2= (Mesh*)ob2->data;
- int i;
-
- // create a new DerivedMesh
- result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
- CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
- CD_DEFAULT, face_it->num_elements);
- CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
- CD_DEFAULT, face_it->num_elements);
-
- // step through the vertex iterators:
- for (i = 0; !vertex_it->Done(vertex_it->it); i++) {
- CSG_IVertex csgvert;
- MVert *mvert = CDDM_get_vert(result, i);
-
- // retrieve a csg vertex from the boolean module
- vertex_it->Fill(vertex_it->it, &csgvert);
- vertex_it->Step(vertex_it->it);
-
- // we have to map the vertex coordinates back in the coordinate frame
- // of the resulting object, since it was computed in world space
- mul_v3_m4v3(mvert->co, parinv, csgvert.position);
- }
-
- // a hash table to remap materials to indices
- if (mat) {
- material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
- *totmat = 0;
- }
-
- // step through the face iterators
- for(i = 0; !face_it->Done(face_it->it); i++) {
- Mesh *orig_me;
- Object *orig_ob;
- Material *orig_mat;
- CSG_IFace csgface;
- MFace *mface;
- int orig_index, mat_nr;
-
- // retrieve a csg face from the boolean module
- face_it->Fill(face_it->it, &csgface);
- face_it->Step(face_it->it);
-
- // find the original mesh and data
- orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2;
- orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2;
- orig_me = (orig_ob == ob1)? me1: me2;
- orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1);
-
- // copy all face layers, including mface
- CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1);
-
- // set mface
- mface = CDDM_get_face(result, i);
- mface->v1 = csgface.vertex_index[0];
- mface->v2 = csgface.vertex_index[1];
- mface->v3 = csgface.vertex_index[2];
- mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0;
-
- // set material, based on lookup in hash table
- orig_mat= give_current_material(orig_ob, mface->mat_nr+1);
-
- if (mat && orig_mat) {
- if (!BLI_ghash_haskey(material_hash, orig_mat)) {
- mat[*totmat] = orig_mat;
- mat_nr = mface->mat_nr = (*totmat)++;
- BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
- }
- else
- mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
- }
- else
- mface->mat_nr = 0;
-
- InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number,
- (orig_me == me2)? mapmat: NULL);
-
- test_index_face(mface, &result->faceData, i, csgface.vertex_number);
- }
-
- if (material_hash)
- BLI_ghash_free(material_hash, NULL, NULL);
-
- CDDM_calc_edges(result);
- CDDM_calc_normals(result);
-
- return result;
-}
-
-static void BuildMeshDescriptors(
- struct DerivedMesh *dm,
- struct Object *ob,
- int face_offset,
- struct CSG_FaceIteratorDescriptor * face_it,
- struct CSG_VertexIteratorDescriptor * vertex_it)
-{
- VertexIt_Construct(vertex_it,dm, ob);
- FaceIt_Construct(face_it,dm,face_offset,ob);
-}
-
-static void FreeMeshDescriptors(
- struct CSG_FaceIteratorDescriptor *face_it,
- struct CSG_VertexIteratorDescriptor *vertex_it)
-{
- VertexIt_Destruct(vertex_it);
- FaceIt_Destruct(face_it);
-}
-
-DerivedMesh *NewBooleanDerivedMesh_intern(
- DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
- int int_op_type, Material **mat, int *totmat)
-{
-
- float inv_mat[4][4];
- float map_mat[4][4];
-
- DerivedMesh *result = NULL;
-
- if (dm == NULL || dm_select == NULL) return 0;
- if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0;
-
- // we map the final object back into ob's local coordinate space. For this
- // we need to compute the inverse transform from global to ob (inv_mat),
- // and the transform from ob to ob_select for use in interpolation (map_mat)
- invert_m4_m4(inv_mat, ob->obmat);
- mul_m4_m4m4(map_mat, ob_select->obmat, inv_mat);
- invert_m4_m4(inv_mat, ob_select->obmat);
-
- {
- // interface with the boolean module:
- //
- // the idea is, we pass the boolean module verts and faces using the
- // provided descriptors. once the boolean operation is performed, we
- // get back output descriptors, from which we then build a DerivedMesh
-
- CSG_VertexIteratorDescriptor vd_1, vd_2;
- CSG_FaceIteratorDescriptor fd_1, fd_2;
- CSG_OperationType op_type;
- CSG_BooleanOperation *bool_op;
-
- // work out the operation they chose and pick the appropriate
- // enum from the csg module.
- switch (int_op_type) {
- case 1 : op_type = e_csg_intersection; break;
- case 2 : op_type = e_csg_union; break;
- case 3 : op_type = e_csg_difference; break;
- case 4 : op_type = e_csg_classify; break;
- default : op_type = e_csg_intersection;
- }
-
- BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1);
- BuildMeshDescriptors(dm, ob, dm_select->getNumFaces(dm_select) , &fd_2, &vd_2);
-
- bool_op = CSG_NewBooleanFunction();
-
- // perform the operation
- if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) {
- CSG_VertexIteratorDescriptor vd_o;
- CSG_FaceIteratorDescriptor fd_o;
-
- CSG_OutputFaceDescriptor(bool_op, &fd_o);
- CSG_OutputVertexDescriptor(bool_op, &vd_o);
-
- // iterate through results of operation and insert
- // into new object
- result = ConvertCSGDescriptorsToDerivedMesh(
- &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob);
-
- // free up the memory
- CSG_FreeVertexDescriptor(&vd_o);
- CSG_FreeFaceDescriptor(&fd_o);
- }
- else
- printf("Unknown internal error in boolean");
-
- CSG_FreeBooleanOperation(bool_op);
-
- FreeMeshDescriptors(&fd_1, &vd_1);
- FreeMeshDescriptors(&fd_2, &vd_2);
- }
-
- return result;
-}
-
-int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
-{
- Mesh *me_new;
- int a, maxmat, totmat= 0;
- Object *ob_new, *ob, *ob_select;
- Material **mat;
- DerivedMesh *result;
- DerivedMesh *dm_select;
- DerivedMesh *dm;
-
- ob= base->object;
- ob_select= base_select->object;
-
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ??
-
- maxmat= ob->totcol + ob_select->totcol;
- mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat");
-
- /* put some checks in for nice user feedback */
- if (dm == NULL || dm_select == NULL) return 0;
- if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select))
- {
- MEM_freeN(mat);
- return -1;
- }
-
- result= NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat);
-
- if (result == NULL) {
- MEM_freeN(mat);
- return 0;
- }
-
- /* create a new blender mesh object - using 'base' as a template */
- ob_new= AddNewBlenderMesh(scene, base_select);
- me_new= ob_new->data;
-
- DM_to_mesh(result, me_new);
- result->release(result);
-
- dm->release(dm);
- dm_select->release(dm_select);
-
- /* add materials to object */
- for (a = 0; a < totmat; a++)
- assign_material(ob_new, mat[a], a+1);
-
- MEM_freeN(mat);
-
- /* update dag */
- DAG_id_flush_update(&ob_new->id, OB_RECALC_DATA);
-
- return 1;
-}
-
-DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
- int int_op_type)
-{
- return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL);
-}
-
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 118a44507c9..8a6f0af87d1 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -62,556 +62,15 @@
/* ************************* fluidsim bobj file handling **************************** */
-// -----------------------------------------
-// forward decleration
-// -----------------------------------------
-
-// -----------------------------------------
-
-void fluidsim_init(FluidsimModifierData *fluidmd)
-{
-#ifndef DISABLE_ELBEEM
- if(fluidmd)
- {
- FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");
-
- fluidmd->fss = fss;
-
- if(!fss)
- return;
-
- fss->fmd = fluidmd;
- fss->type = OB_FLUIDSIM_ENABLE;
- fss->show_advancedoptions = 0;
-
- fss->resolutionxyz = 65;
- fss->previewresxyz = 45;
- fss->realsize = 0.5;
- fss->guiDisplayMode = 2; // preview
- fss->renderDisplayMode = 3; // render
-
- fss->viscosityMode = 2; // default to water
- fss->viscosityValue = 1.0;
- fss->viscosityExponent = 6;
-
- // dg TODO: change this to []
- fss->gravx = 0.0;
- fss->gravy = 0.0;
- fss->gravz = -9.81;
- fss->animStart = 0.0;
- fss->animEnd = 4.0;
- fss->gstar = 0.005; // used as normgstar
- fss->maxRefine = -1;
- // maxRefine is set according to resolutionxyz during bake
-
- // fluid/inflow settings
- // fss->iniVel --> automatically set to 0
-
- /* elubie: changed this to default to the same dir as the render output
- to prevent saving to C:\ on Windows */
- BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX);
-
- // first init of bounding box
- // no bounding box needed
-
- // todo - reuse default init from elbeem!
- fss->typeFlags = OB_FSBND_PARTSLIP;
- fss->domainNovecgen = 0;
- fss->volumeInitType = 1; // volume
- fss->partSlipValue = 0.2;
-
- fss->generateTracers = 0;
- fss->generateParticles = 0.0;
- fss->surfaceSmoothing = 1.0;
- fss->surfaceSubdivs = 0.0;
- fss->particleInfSize = 0.0;
- fss->particleInfAlpha = 0.0;
-
- // init fluid control settings
- fss->attractforceStrength = 0.2;
- fss->attractforceRadius = 0.75;
- fss->velocityforceStrength = 0.2;
- fss->velocityforceRadius = 0.75;
- fss->cpsTimeStart = fss->animStart;
- fss->cpsTimeEnd = fss->animEnd;
- fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
-
- /*
- BAD TODO: this is done in buttons_object.c in the moment
- Mesh *mesh = ob->data;
- // calculate bounding box
- fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
- */
-
- // (ab)used to store velocities
- fss->meshSurfNormals = NULL;
-
- fss->lastgoodframe = -1;
-
- fss->flag |= OB_FLUIDSIM_ACTIVE;
-
- }
-#endif
- return;
-}
-
-void fluidsim_free(FluidsimModifierData *fluidmd)
-{
-#ifndef DISABLE_ELBEEM
- if(fluidmd)
- {
- if(fluidmd->fss->meshSurfNormals)
- {
- MEM_freeN(fluidmd->fss->meshSurfNormals);
- fluidmd->fss->meshSurfNormals = NULL;
- }
- MEM_freeN(fluidmd->fss);
- }
-#endif
- return;
-}
-
-DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
-{
-#ifndef DISABLE_ELBEEM
- DerivedMesh *result = NULL;
- int framenr;
- FluidsimSettings *fss = NULL;
-
- framenr= (int)scene->r.cfra;
-
- // only handle fluidsim domains
- if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN))
- return dm;
-
- // sanity check
- if(!fluidmd || (fluidmd && !fluidmd->fss))
- return dm;
-
- fss = fluidmd->fss;
-
- // timescale not supported yet
- // clmd->sim_parms->timescale= timescale;
-
- // support reversing of baked fluid frames here
- if((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0))
- {
- framenr = fss->lastgoodframe - framenr + 1;
- CLAMP(framenr, 1, fss->lastgoodframe);
- }
-
- /* try to read from cache */
- if(((fss->lastgoodframe >= framenr) || (fss->lastgoodframe < 0)) && (result = fluidsim_read_cache(ob, dm, fluidmd, framenr, useRenderParams)))
- {
- // fss->lastgoodframe = framenr; // set also in src/fluidsim.c
- return result;
- }
- else
- {
- // display last known good frame
- if(fss->lastgoodframe >= 0)
- {
- if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams)))
- {
- return result;
- }
-
- // it was supposed to be a valid frame but it isn't!
- fss->lastgoodframe = framenr - 1;
-
-
- // this could be likely the case when you load an old fluidsim
- if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams)))
- {
- return result;
- }
- }
-
- result = CDDM_copy(dm);
-
- if(result)
- {
- return result;
- }
- }
-
- return dm;
-#else
- return NULL;
-#endif
-}
-
-#ifndef DISABLE_ELBEEM
-/* read .bobj.gz file into a fluidsimDerivedMesh struct */
-static DerivedMesh *fluidsim_read_obj(char *filename)
-{
- int wri,i,j;
- float wrf;
- int gotBytes;
- gzFile gzf;
- int numverts = 0, numfaces = 0;
- DerivedMesh *dm = NULL;
- MFace *mface;
- MVert *mvert;
- short *normals;
-
- // ------------------------------------------------
- // get numverts + numfaces first
- // ------------------------------------------------
- gzf = gzopen(filename, "rb");
- if (!gzf)
- {
- return NULL;
- }
-
- // read numverts
- gotBytes = gzread(gzf, &wri, sizeof(wri));
- numverts = wri;
-
- // skip verts
- for(i=0; i<numverts*3; i++)
- {
- gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
- }
-
- // read number of normals
- gotBytes = gzread(gzf, &wri, sizeof(wri));
-
- // skip normals
- for(i=0; i<numverts*3; i++)
- {
- gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
- }
-
- /* get no. of triangles */
- gotBytes = gzread(gzf, &wri, sizeof(wri));
- numfaces = wri;
-
- gzclose( gzf );
- // ------------------------------------------------
-
- if(!numfaces || !numverts)
- return NULL;
-
- gzf = gzopen(filename, "rb");
- if (!gzf)
- {
- return NULL;
- }
-
- dm = CDDM_new(numverts, 0, numfaces);
-
- if(!dm)
- {
- gzclose( gzf );
- return NULL;
- }
-
- // read numverts
- gotBytes = gzread(gzf, &wri, sizeof(wri));
-
- // read vertex position from file
- mvert = CDDM_get_verts(dm);
- for(i=0; i<numverts; i++)
- {
- MVert *mv = &mvert[i];
-
- for(j=0; j<3; j++)
- {
- gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
- mv->co[j] = wrf;
- }
- }
-
- // should be the same as numverts
- gotBytes = gzread(gzf, &wri, sizeof(wri));
- if(wri != numverts)
- {
- if(dm)
- dm->release(dm);
- gzclose( gzf );
- return NULL;
- }
-
- normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" );
- if(!normals)
- {
- if(dm)
- dm->release(dm);
- gzclose( gzf );
- return NULL;
- }
-
- // read normals from file (but don't save them yet)
- for(i=0; i<numverts*3; i++)
- {
- gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
- normals[i] = (short)(wrf*32767.0f);
- }
-
- /* read no. of triangles */
- gotBytes = gzread(gzf, &wri, sizeof(wri));
-
- if(wri!=numfaces)
- printf("Fluidsim: error in reading data from file.\n");
-
- // read triangles from file
- mface = CDDM_get_faces(dm);
- for(i=0; i<numfaces; i++)
- {
- int face[4];
- MFace *mf = &mface[i];
-
- gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] ));
- gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] ));
- gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] ));
- face[3] = 0;
-
- // check if 3rd vertex has index 0 (not allowed in blender)
- if(face[2])
- {
- mf->v1 = face[0];
- mf->v2 = face[1];
- mf->v3 = face[2];
- }
- else
- {
- mf->v1 = face[1];
- mf->v2 = face[2];
- mf->v3 = face[0];
- }
- mf->v4 = face[3];
-
- test_index_face(mf, NULL, 0, 3);
- }
-
- gzclose( gzf );
-
- CDDM_calc_edges(dm);
-
- CDDM_apply_vert_normals(dm, (short (*)[3])normals);
- MEM_freeN(normals);
-
- // CDDM_calc_normals(result);
-
- return dm;
-}
-
-DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
-{
- int displaymode = 0;
- int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */
- char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
- FluidsimSettings *fss = fluidmd->fss;
- DerivedMesh *dm = NULL;
- MFace *mface;
- int numfaces;
- int mat_nr, flag, i;
-
- if(!useRenderParams) {
- displaymode = fss->guiDisplayMode;
- } else {
- displaymode = fss->renderDisplayMode;
- }
-
- strncpy(targetDir, fss->surfdataPath, FILE_MAXDIR);
-
- // use preview or final mesh?
- if(displaymode==1)
- {
- // just display original object
- return NULL;
- }
- else if(displaymode==2)
- {
- strcat(targetDir,"fluidsurface_preview_####");
- }
- else
- { // 3
- strcat(targetDir,"fluidsurface_final_####");
- }
-
- BLI_path_abs(targetDir, G.sce);
- BLI_path_frame(targetDir, curFrame, 0); // fixed #frame-no
-
- strcpy(targetFile,targetDir);
- strcat(targetFile, ".bobj.gz");
-
- dm = fluidsim_read_obj(targetFile);
-
- if(!dm)
- {
- // switch, abort background rendering when fluidsim mesh is missing
- const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
-
- if(G.background==1) {
- if(getenv(strEnvName2)) {
- int elevel = atoi(getenv(strEnvName2));
- if(elevel>0) {
- printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
- exit(1);
- }
- }
- }
-
- // display org. object upon failure which is in dm
- return NULL;
- }
-
- // assign material + flags to new dm
- mface = orgdm->getFaceArray(orgdm);
- mat_nr = mface[0].mat_nr;
- flag = mface[0].flag;
-
- mface = dm->getFaceArray(dm);
- numfaces = dm->getNumFaces(dm);
- for(i=0; i<numfaces; i++)
- {
- mface[i].mat_nr = mat_nr;
- mface[i].flag = flag;
- }
-
- // load vertex velocities, if they exist...
- // TODO? use generate flag as loading flag as well?
- // warning, needs original .bobj.gz mesh loading filename
- if(displaymode==3)
- {
- fluidsim_read_vel_cache(fluidmd, dm, targetFile);
- }
- else
- {
- if(fss->meshSurfNormals)
- MEM_freeN(fss->meshSurfNormals);
-
- fss->meshSurfNormals = NULL;
- }
-
- return dm;
-}
-
-
-/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
-void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh *dm, char *filename)
-{
- int wri, i, j;
- float wrf;
- gzFile gzf;
- FluidsimSettings *fss = fluidmd->fss;
- int len = strlen(filename);
- int totvert = dm->getNumVerts(dm);
- float *velarray = NULL;
-
- // mesh and vverts have to be valid from loading...
-
- if(fss->meshSurfNormals)
- MEM_freeN(fss->meshSurfNormals);
-
- if(len<7)
- {
- return;
- }
-
- if(fss->domainNovecgen>0) return;
-
- // abusing pointer to hold an array of 3d-velocities
- fss->meshSurfNormals = MEM_callocN(sizeof(float)*3*dm->getNumVerts(dm), "Fluidsim_velocities");
- // abusing pointer to hold an INT
- fss->meshSurface = SET_INT_IN_POINTER(totvert);
-
- velarray = (float *)fss->meshSurfNormals;
-
- // .bobj.gz , correct filename
- // 87654321
- filename[len-6] = 'v';
- filename[len-5] = 'e';
- filename[len-4] = 'l';
-
- gzf = gzopen(filename, "rb");
- if (!gzf)
- {
- MEM_freeN(fss->meshSurfNormals);
- fss->meshSurfNormals = NULL;
- return;
- }
-
- gzread(gzf, &wri, sizeof( wri ));
- if(wri != totvert)
- {
- MEM_freeN(fss->meshSurfNormals);
- fss->meshSurfNormals = NULL;
- return;
- }
-
- for(i=0; i<totvert;i++)
- {
- for(j=0; j<3; j++)
- {
- gzread(gzf, &wrf, sizeof( wrf ));
- velarray[3*i + j] = wrf;
- }
- }
-
- gzclose(gzf);
-}
-
-void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
- /*RET*/ float start[3], /*RET*/ float size[3] )
-{
- float bbsx=0.0, bbsy=0.0, bbsz=0.0;
- float bbex=1.0, bbey=1.0, bbez=1.0;
- int i;
- float vec[3];
-
- if(totvert == 0) {
- zero_v3(start);
- zero_v3(size);
- return;
- }
-
- VECCOPY(vec, mvert[0].co);
- mul_m4_v3(obmat, vec);
- bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
- bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
-
- for(i = 1; i < totvert; i++) {
- VECCOPY(vec, mvert[i].co);
- mul_m4_v3(obmat, vec);
-
- if(vec[0] < bbsx){ bbsx= vec[0]; }
- if(vec[1] < bbsy){ bbsy= vec[1]; }
- if(vec[2] < bbsz){ bbsz= vec[2]; }
- if(vec[0] > bbex){ bbex= vec[0]; }
- if(vec[1] > bbey){ bbey= vec[1]; }
- if(vec[2] > bbez){ bbez= vec[2]; }
- }
-
- // return values...
- if(start) {
- start[0] = bbsx;
- start[1] = bbsy;
- start[2] = bbsz;
- }
- if(size) {
- size[0] = bbex-bbsx;
- size[1] = bbey-bbsy;
- size[2] = bbez-bbsz;
- }
-}
-
-//-------------------------------------------------------------------------------
-// old interface
-//-------------------------------------------------------------------------------
-
-
//-------------------------------------------------------------------------------
// file handling
//-------------------------------------------------------------------------------
-void initElbeemMesh(struct Scene *scene, struct Object *ob,
- int *numVertices, float **vertices,
+void initElbeemMesh(struct Scene *scene, struct Object *ob,
+ int *numVertices, float **vertices,
int *numTriangles, int **triangles,
- int useGlobalCoords, int modifierIndex)
+ int useGlobalCoords, int modifierIndex)
{
DerivedMesh *dm = NULL;
MVert *mvert;
@@ -650,14 +109,14 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
face[2] = mface[i].v3;
face[3] = mface[i].v4;
- tris[countTris*3+0] = face[0];
- tris[countTris*3+1] = face[1];
- tris[countTris*3+2] = face[2];
+ tris[countTris*3+0] = face[0];
+ tris[countTris*3+1] = face[1];
+ tris[countTris*3+2] = face[2];
countTris++;
- if(face[3]) {
- tris[countTris*3+0] = face[0];
- tris[countTris*3+1] = face[2];
- tris[countTris*3+2] = face[3];
+ if(face[3]) {
+ tris[countTris*3+0] = face[0];
+ tris[countTris*3+1] = face[2];
+ tris[countTris*3+2] = face[3];
countTris++;
}
}
@@ -665,21 +124,3 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
dm->release(dm);
}
-
-void fluid_estimate_memory(Object *ob, FluidsimSettings *fss, char *value)
-{
- Mesh *mesh;
-
- value[0]= '\0';
-
- if(ob->type == OB_MESH) {
- /* use mesh bounding box and object scaling */
- mesh= ob->data;
-
- fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
- elbeemEstimateMemreq(fss->resolutionxyz, fss->bbSize[0],fss->bbSize[1],fss->bbSize[2], fss->maxRefine, value);
- }
-}
-
-#endif // DISABLE_ELBEEM
-
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index c8f98bbac56..d2d9d558b3c 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -81,9863 +81,73 @@
#include "depsgraph_private.h"
#include "BKE_deform.h"
#include "BKE_shrinkwrap.h"
-#include "BKE_simple_deform.h"
-
-#include "LOD_decimation.h"
#include "CCGSubSurf.h"
#include "RE_shader_ext.h"
-/* Utility */
-
-static int is_last_displist(Object *ob)
-{
- Curve *cu = ob->data;
- static int curvecount=0, totcurve=0;
-
- if(curvecount == 0){
- DispList *dl;
-
- totcurve = 0;
- for(dl=cu->disp.first; dl; dl=dl->next)
- totcurve++;
- }
-
- curvecount++;
-
- if(curvecount == totcurve){
- curvecount = 0;
- return 1;
- }
-
- return 0;
-}
-
-/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */
-static DerivedMesh *get_dm(Scene *scene, Object *ob, EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int orco)
-{
- if(dm)
- return dm;
-
- if(ob->type==OB_MESH) {
- if(em) dm= CDDM_from_editmesh(em, ob->data);
- else dm = CDDM_from_mesh((Mesh*)(ob->data), ob);
-
- if(vertexCos) {
- CDDM_apply_vert_coords(dm, vertexCos);
- //CDDM_calc_normals(dm);
- }
-
- if(orco)
- DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
- }
- else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) {
- if(is_last_displist(ob)) {
- dm= CDDM_from_curve(ob);
- }
- }
-
- return dm;
-}
-
-/* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */
-static DerivedMesh *get_cddm(Scene *scene, Object *ob, EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3])
-{
- if(dm && dm->type == DM_TYPE_CDDM)
- return dm;
-
- if(!dm) {
- dm= get_dm(scene, ob, em, dm, vertexCos, 0);
- }
- else {
- dm= CDDM_copy(dm);
- CDDM_apply_vert_coords(dm, vertexCos);
- }
-
- if(dm)
- CDDM_calc_normals(dm);
-
- return dm;
-}
-
-/***/
-
-static int noneModifier_isDisabled(ModifierData *md, int userRenderParams)
-{
- return 1;
-}
-
-/* Curve */
-
-static void curveModifier_initData(ModifierData *md)
-{
- CurveModifierData *cmd = (CurveModifierData*) md;
-
- cmd->defaxis = MOD_CURVE_POSX;
-}
-
-static void curveModifier_copyData(ModifierData *md, ModifierData *target)
-{
- CurveModifierData *cmd = (CurveModifierData*) md;
- CurveModifierData *tcmd = (CurveModifierData*) target;
-
- tcmd->defaxis = cmd->defaxis;
- tcmd->object = cmd->object;
- strncpy(tcmd->name, cmd->name, 32);
-}
-
-static CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- CurveModifierData *cmd = (CurveModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(cmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static int curveModifier_isDisabled(ModifierData *md, int userRenderParams)
-{
- CurveModifierData *cmd = (CurveModifierData*) md;
-
- return !cmd->object;
-}
-
-static void curveModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- CurveModifierData *cmd = (CurveModifierData*) md;
-
- walk(userData, ob, &cmd->object);
-}
-
-static void curveModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene,
- Object *ob, DagNode *obNode)
-{
- CurveModifierData *cmd = (CurveModifierData*) md;
-
- if (cmd->object) {
- DagNode *curNode = dag_get_node(forest, cmd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Modifier");
- }
-}
-
-static void curveModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- CurveModifierData *cmd = (CurveModifierData*) md;
-
- curve_deform_verts(md->scene, cmd->object, ob, derivedData, vertexCos, numVerts,
- cmd->name, cmd->defaxis);
-}
-
-static void curveModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm = derivedData;
-
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
- curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
-
- if(!derivedData) dm->release(dm);
-}
-
-/* Lattice */
-
-static void latticeModifier_copyData(ModifierData *md, ModifierData *target)
-{
- LatticeModifierData *lmd = (LatticeModifierData*) md;
- LatticeModifierData *tlmd = (LatticeModifierData*) target;
-
- tlmd->object = lmd->object;
- strncpy(tlmd->name, lmd->name, 32);
-}
-
-static CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- LatticeModifierData *lmd = (LatticeModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(lmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static int latticeModifier_isDisabled(ModifierData *md, int userRenderParams)
-{
- LatticeModifierData *lmd = (LatticeModifierData*) md;
-
- return !lmd->object;
-}
-
-static void latticeModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- LatticeModifierData *lmd = (LatticeModifierData*) md;
-
- walk(userData, ob, &lmd->object);
-}
-
-static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
- Object *ob, DagNode *obNode)
-{
- LatticeModifierData *lmd = (LatticeModifierData*) md;
-
- if(lmd->object) {
- DagNode *latNode = dag_get_node(forest, lmd->object);
-
- dag_add_relation(forest, latNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Lattice Modifier");
- }
-}
-
-static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3])
-{
- while((md=md->next) && md->type==eModifierType_Armature) {
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
- if(amd->multi && amd->prevCos==NULL)
- amd->prevCos= MEM_dupallocN(vertexCos);
- else
- break;
- }
- /* lattice/mesh modifier too */
-}
-
-
-static void latticeModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- LatticeModifierData *lmd = (LatticeModifierData*) md;
-
-
- modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
-
- lattice_deform_verts(lmd->object, ob, derivedData,
- vertexCos, numVerts, lmd->name);
-}
-
-static void latticeModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm = derivedData;
-
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
- latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
-
- if(!derivedData) dm->release(dm);
-}
-
-/* Subsurf */
-
-static void subsurfModifier_initData(ModifierData *md)
-{
- SubsurfModifierData *smd = (SubsurfModifierData*) md;
-
- smd->levels = 1;
- smd->renderLevels = 2;
- smd->flags |= eSubsurfModifierFlag_SubsurfUv;
-}
-
-static void subsurfModifier_copyData(ModifierData *md, ModifierData *target)
-{
- SubsurfModifierData *smd = (SubsurfModifierData*) md;
- SubsurfModifierData *tsmd = (SubsurfModifierData*) target;
-
- tsmd->flags = smd->flags;
- tsmd->levels = smd->levels;
- tsmd->renderLevels = smd->renderLevels;
- tsmd->subdivType = smd->subdivType;
-}
-
-static void subsurfModifier_freeData(ModifierData *md)
-{
- SubsurfModifierData *smd = (SubsurfModifierData*) md;
-
- if(smd->mCache) {
- ccgSubSurf_free(smd->mCache);
- }
- if(smd->emCache) {
- ccgSubSurf_free(smd->emCache);
- }
-}
-
-static int subsurfModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- SubsurfModifierData *smd = (SubsurfModifierData*) md;
- int levels= (useRenderParams)? smd->renderLevels: smd->levels;
-
- return get_render_subsurf_level(&md->scene->r, levels) == 0;
-}
-
-static DerivedMesh *subsurfModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- SubsurfModifierData *smd = (SubsurfModifierData*) md;
- DerivedMesh *result;
-
- result = subsurf_make_derived_from_derived(derivedData, smd,
- useRenderParams, NULL, isFinalCalc, 0);
-
- if(useRenderParams || !isFinalCalc) {
- DerivedMesh *cddm= CDDM_copy(result);
- result->release(result);
- result= cddm;
- }
-
- return result;
-}
-
-static DerivedMesh *subsurfModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData)
-{
- SubsurfModifierData *smd = (SubsurfModifierData*) md;
- DerivedMesh *result;
-
- result = subsurf_make_derived_from_derived(derivedData, smd, 0,
- NULL, 0, 1);
-
- return result;
-}
-
-/* Build */
-
-static void buildModifier_initData(ModifierData *md)
-{
- BuildModifierData *bmd = (BuildModifierData*) md;
-
- bmd->start = 1.0;
- bmd->length = 100.0;
-}
-
-static void buildModifier_copyData(ModifierData *md, ModifierData *target)
-{
- BuildModifierData *bmd = (BuildModifierData*) md;
- BuildModifierData *tbmd = (BuildModifierData*) target;
-
- tbmd->start = bmd->start;
- tbmd->length = bmd->length;
- tbmd->randomize = bmd->randomize;
- tbmd->seed = bmd->seed;
-}
-
-static int buildModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-
-static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm = derivedData;
- DerivedMesh *result;
- BuildModifierData *bmd = (BuildModifierData*) md;
- int i;
- int numFaces, numEdges;
- int maxVerts, maxEdges, maxFaces;
- int *vertMap, *edgeMap, *faceMap;
- float frac;
- GHashIterator *hashIter;
- /* maps vert indices in old mesh to indices in new mesh */
- GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
- BLI_ghashutil_intcmp);
- /* maps edge indices in new mesh to indices in old mesh */
- GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
- BLI_ghashutil_intcmp);
-
- maxVerts = dm->getNumVerts(dm);
- vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts,
- "build modifier vertMap");
- for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
-
- maxEdges = dm->getNumEdges(dm);
- edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges,
- "build modifier edgeMap");
- for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
-
- maxFaces = dm->getNumFaces(dm);
- faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces,
- "build modifier faceMap");
- for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
-
- if (ob) {
- frac = bsystem_time(md->scene, ob, md->scene->r.cfra,
- bmd->start - 1.0f) / bmd->length;
- } else {
- frac = md->scene->r.cfra - bmd->start / bmd->length;
- }
- CLAMP(frac, 0.0, 1.0);
-
- numFaces = dm->getNumFaces(dm) * frac;
- numEdges = dm->getNumEdges(dm) * frac;
-
- /* if there's at least one face, build based on faces */
- if(numFaces) {
- int maxEdges;
-
- if(bmd->randomize)
- BLI_array_randomize(faceMap, sizeof(*faceMap),
- maxFaces, bmd->seed);
-
- /* get the set of all vert indices that will be in the final mesh,
- * mapped to the new indices
- */
- for(i = 0; i < numFaces; ++i) {
- MFace mf;
- dm->getFace(dm, faceMap[i], &mf);
-
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- }
-
- /* get the set of edges that will be in the new mesh (i.e. all edges
- * that have both verts in the new mesh)
- */
- maxEdges = dm->getNumEdges(dm);
- for(i = 0; i < maxEdges; ++i) {
- MEdge me;
- dm->getEdge(dm, i, &me);
-
- if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))
- && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
- BLI_ghash_insert(edgeHash,
- SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i));
- }
- } else if(numEdges) {
- if(bmd->randomize)
- BLI_array_randomize(edgeMap, sizeof(*edgeMap),
- maxEdges, bmd->seed);
-
- /* get the set of all vert indices that will be in the final mesh,
- * mapped to the new indices
- */
- for(i = 0; i < numEdges; ++i) {
- MEdge me;
- dm->getEdge(dm, edgeMap[i], &me);
-
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- }
-
- /* get the set of edges that will be in the new mesh
- */
- for(i = 0; i < numEdges; ++i) {
- MEdge me;
- dm->getEdge(dm, edgeMap[i], &me);
-
- BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)),
- SET_INT_IN_POINTER(edgeMap[i]));
- }
- } else {
- int numVerts = dm->getNumVerts(dm) * frac;
-
- if(bmd->randomize)
- BLI_array_randomize(vertMap, sizeof(*vertMap),
- maxVerts, bmd->seed);
-
- /* get the set of all vert indices that will be in the final mesh,
- * mapped to the new indices
- */
- for(i = 0; i < numVerts; ++i)
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i));
- }
-
- /* now we know the number of verts, edges and faces, we can create
- * the mesh
- */
- result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
- BLI_ghash_size(edgeHash), numFaces);
-
- /* copy the vertices across */
- for(hashIter = BLI_ghashIterator_new(vertHash);
- !BLI_ghashIterator_isDone(hashIter);
- BLI_ghashIterator_step(hashIter)) {
- MVert source;
- MVert *dest;
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
- int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
-
- dm->getVert(dm, oldIndex, &source);
- dest = CDDM_get_vert(result, newIndex);
-
- DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
- *dest = source;
- }
- BLI_ghashIterator_free(hashIter);
-
- /* copy the edges across, remapping indices */
- for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
- MEdge source;
- MEdge *dest;
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i)));
-
- dm->getEdge(dm, oldIndex, &source);
- dest = CDDM_get_edge(result, i);
-
- source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
- source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
-
- DM_copy_edge_data(dm, result, oldIndex, i, 1);
- *dest = source;
- }
-
- /* copy the faces across, remapping indices */
- for(i = 0; i < numFaces; ++i) {
- MFace source;
- MFace *dest;
- int orig_v4;
-
- dm->getFace(dm, faceMap[i], &source);
- dest = CDDM_get_face(result, i);
-
- orig_v4 = source.v4;
-
- source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
- source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
- source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
- if(source.v4)
- source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
-
- DM_copy_face_data(dm, result, faceMap[i], i, 1);
- *dest = source;
-
- test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
- }
-
- CDDM_calc_normals(result);
-
- BLI_ghash_free(vertHash, NULL, NULL);
- BLI_ghash_free(edgeHash, NULL, NULL);
-
- MEM_freeN(vertMap);
- MEM_freeN(edgeMap);
- MEM_freeN(faceMap);
-
- return result;
-}
-
-/* Mask */
-
-static void maskModifier_copyData(ModifierData *md, ModifierData *target)
-{
- MaskModifierData *mmd = (MaskModifierData*) md;
- MaskModifierData *tmmd = (MaskModifierData*) target;
-
- strcpy(tmmd->vgroup, mmd->vgroup);
-}
-
-static CustomDataMask maskModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- return (1 << CD_MDEFORMVERT);
-}
-
-static void maskModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- MaskModifierData *mmd = (MaskModifierData *)md;
- walk(userData, ob, &mmd->ob_arm);
-}
-
-static void maskModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
- Object *ob, DagNode *obNode)
-{
- MaskModifierData *mmd = (MaskModifierData *)md;
-
- if (mmd->ob_arm)
- {
- DagNode *armNode = dag_get_node(forest, mmd->ob_arm);
-
- dag_add_relation(forest, armNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier");
- }
-}
-
-static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- MaskModifierData *mmd= (MaskModifierData *)md;
- DerivedMesh *dm= derivedData, *result= NULL;
- GHash *vertHash=NULL, *edgeHash, *faceHash;
- GHashIterator *hashIter;
- MDeformVert *dvert= NULL;
- int numFaces=0, numEdges=0, numVerts=0;
- int maxVerts, maxEdges, maxFaces;
- int i;
-
- /* Overview of Method:
- * 1. Get the vertices that are in the vertexgroup of interest
- * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices
- * 3. Make a new mesh containing only the mapping data
- */
-
- /* get original number of verts, edges, and faces */
- maxVerts= dm->getNumVerts(dm);
- maxEdges= dm->getNumEdges(dm);
- maxFaces= dm->getNumFaces(dm);
-
- /* check if we can just return the original mesh
- * - must have verts and therefore verts assigned to vgroups to do anything useful
- */
- if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) ||
- (maxVerts == 0) || (ob->defbase.first == NULL) )
- {
- return derivedData;
- }
-
- /* if mode is to use selected armature bones, aggregate the bone groups */
- if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */
- {
- GHash *vgroupHash, *boneHash;
- Object *oba= mmd->ob_arm;
- bPoseChannel *pchan;
- bDeformGroup *def;
-
- /* check that there is armature object with bones to use, otherwise return original mesh */
- if (ELEM(NULL, mmd->ob_arm, mmd->ob_arm->pose))
- return derivedData;
-
- /* hashes for finding mapping of:
- * - vgroups to indicies -> vgroupHash (string, int)
- * - bones to vgroup indices -> boneHash (index of vgroup, dummy)
- */
- vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
- boneHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-
- /* build mapping of names of vertex groups to indices */
- for (i = 0, def = ob->defbase.first; def; def = def->next, i++)
- BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i));
-
- /* get selected-posechannel <-> vertexgroup index mapping */
- for (pchan= oba->pose->chanbase.first; pchan; pchan= pchan->next)
- {
- /* check if bone is selected */
- // TODO: include checks for visibility too?
- // FIXME: the depsgraph needs extensions to make this work in realtime...
- if ( (pchan->bone) && (pchan->bone->flag & BONE_SELECTED) )
- {
- /* check if hash has group for this bone */
- if (BLI_ghash_haskey(vgroupHash, pchan->name))
- {
- int defgrp_index= GET_INT_FROM_POINTER(BLI_ghash_lookup(vgroupHash, pchan->name));
-
- /* add index to hash (store under key only) */
- BLI_ghash_insert(boneHash, SET_INT_IN_POINTER(defgrp_index), pchan);
- }
- }
- }
-
- /* if no bones selected, free hashes and return original mesh */
- if (BLI_ghash_size(boneHash) == 0)
- {
- BLI_ghash_free(vgroupHash, NULL, NULL);
- BLI_ghash_free(boneHash, NULL, NULL);
-
- return derivedData;
- }
-
- /* repeat the previous check, but for dverts */
- dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT);
- if (dvert == NULL)
- {
- BLI_ghash_free(vgroupHash, NULL, NULL);
- BLI_ghash_free(boneHash, NULL, NULL);
-
- return derivedData;
- }
-
- /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
- vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-
- /* add vertices which exist in vertexgroups into vertHash for filtering */
- for (i = 0; i < maxVerts; i++)
- {
- MDeformWeight *def_weight = NULL;
- int j;
-
- for (j= 0; j < dvert[i].totweight; j++)
- {
- if (BLI_ghash_haskey(boneHash, SET_INT_IN_POINTER(dvert[i].dw[j].def_nr)))
- {
- def_weight = &dvert[i].dw[j];
- break;
- }
- }
-
- /* check if include vert in vertHash */
- if (mmd->flag & MOD_MASK_INV) {
- /* if this vert is in the vgroup, don't include it in vertHash */
- if (def_weight) continue;
- }
- else {
- /* if this vert isn't in the vgroup, don't include it in vertHash */
- if (!def_weight) continue;
- }
-
- /* add to ghash for verts (numVerts acts as counter for mapping) */
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
- numVerts++;
- }
-
- /* free temp hashes */
- BLI_ghash_free(vgroupHash, NULL, NULL);
- BLI_ghash_free(boneHash, NULL, NULL);
- }
- else /* --- Using Nominated VertexGroup only --- */
- {
- int defgrp_index = defgroup_name_index(ob, mmd->vgroup);
-
- /* get dverts */
- if (defgrp_index >= 0)
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- /* if no vgroup (i.e. dverts) found, return the initial mesh */
- if ((defgrp_index < 0) || (dvert == NULL))
- return dm;
-
- /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
- vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-
- /* add vertices which exist in vertexgroup into ghash for filtering */
- for (i = 0; i < maxVerts; i++)
- {
- MDeformWeight *def_weight = NULL;
- int j;
-
- for (j= 0; j < dvert[i].totweight; j++)
- {
- if (dvert[i].dw[j].def_nr == defgrp_index)
- {
- def_weight = &dvert[i].dw[j];
- break;
- }
- }
-
- /* check if include vert in vertHash */
- if (mmd->flag & MOD_MASK_INV) {
- /* if this vert is in the vgroup, don't include it in vertHash */
- if (def_weight) continue;
- }
- else {
- /* if this vert isn't in the vgroup, don't include it in vertHash */
- if (!def_weight) continue;
- }
-
- /* add to ghash for verts (numVerts acts as counter for mapping) */
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
- numVerts++;
- }
- }
-
- /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
- edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
- faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-
- /* loop over edges and faces, and do the same thing to
- * ensure that they only reference existing verts
- */
- for (i = 0; i < maxEdges; i++)
- {
- MEdge me;
- dm->getEdge(dm, i, &me);
-
- /* only add if both verts will be in new mesh */
- if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) &&
- BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) )
- {
- BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
- numEdges++;
- }
- }
- for (i = 0; i < maxFaces; i++)
- {
- MFace mf;
- dm->getFace(dm, i, &mf);
-
- /* all verts must be available */
- if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) &&
- BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) &&
- BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) &&
- (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) )
- {
- BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces));
- numFaces++;
- }
- }
-
-
- /* now we know the number of verts, edges and faces,
- * we can create the new (reduced) mesh
- */
- result = CDDM_from_template(dm, numVerts, numEdges, numFaces);
-
-
- /* using ghash-iterators, map data into new mesh */
- /* vertices */
- for ( hashIter = BLI_ghashIterator_new(vertHash);
- !BLI_ghashIterator_isDone(hashIter);
- BLI_ghashIterator_step(hashIter) )
- {
- MVert source;
- MVert *dest;
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
- int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
-
- dm->getVert(dm, oldIndex, &source);
- dest = CDDM_get_vert(result, newIndex);
-
- DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
- *dest = source;
- }
- BLI_ghashIterator_free(hashIter);
-
- /* edges */
- for ( hashIter = BLI_ghashIterator_new(edgeHash);
- !BLI_ghashIterator_isDone(hashIter);
- BLI_ghashIterator_step(hashIter) )
- {
- MEdge source;
- MEdge *dest;
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
- int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
-
- dm->getEdge(dm, oldIndex, &source);
- dest = CDDM_get_edge(result, newIndex);
-
- source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
- source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
-
- DM_copy_edge_data(dm, result, oldIndex, newIndex, 1);
- *dest = source;
- }
- BLI_ghashIterator_free(hashIter);
-
- /* faces */
- for ( hashIter = BLI_ghashIterator_new(faceHash);
- !BLI_ghashIterator_isDone(hashIter);
- BLI_ghashIterator_step(hashIter) )
- {
- MFace source;
- MFace *dest;
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
- int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
- int orig_v4;
-
- dm->getFace(dm, oldIndex, &source);
- dest = CDDM_get_face(result, newIndex);
-
- orig_v4 = source.v4;
-
- source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
- source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
- source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
- if (source.v4)
- source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
-
- DM_copy_face_data(dm, result, oldIndex, newIndex, 1);
- *dest = source;
-
- test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3));
- }
- BLI_ghashIterator_free(hashIter);
-
- /* recalculate normals */
- CDDM_calc_normals(result);
-
- /* free hashes */
- BLI_ghash_free(vertHash, NULL, NULL);
- BLI_ghash_free(edgeHash, NULL, NULL);
- BLI_ghash_free(faceHash, NULL, NULL);
-
- /* return the new mesh */
- return result;
-}
-
-/* Array */
-/* Array modifier: duplicates the object multiple times along an axis
-*/
-
-static void arrayModifier_initData(ModifierData *md)
-{
- ArrayModifierData *amd = (ArrayModifierData*) md;
-
- /* default to 2 duplicates distributed along the x-axis by an
- offset of 1 object-width
- */
- amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
- amd->count = 2;
- amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
- amd->scale[0] = 1;
- amd->scale[1] = amd->scale[2] = 0;
- amd->length = 0;
- amd->merge_dist = 0.01;
- amd->fit_type = MOD_ARR_FIXEDCOUNT;
- amd->offset_type = MOD_ARR_OFF_RELATIVE;
- amd->flags = 0;
-}
-
-static void arrayModifier_copyData(ModifierData *md, ModifierData *target)
-{
- ArrayModifierData *amd = (ArrayModifierData*) md;
- ArrayModifierData *tamd = (ArrayModifierData*) target;
-
- tamd->start_cap = amd->start_cap;
- tamd->end_cap = amd->end_cap;
- tamd->curve_ob = amd->curve_ob;
- tamd->offset_ob = amd->offset_ob;
- tamd->count = amd->count;
- VECCOPY(tamd->offset, amd->offset);
- VECCOPY(tamd->scale, amd->scale);
- tamd->length = amd->length;
- tamd->merge_dist = amd->merge_dist;
- tamd->fit_type = amd->fit_type;
- tamd->offset_type = amd->offset_type;
- tamd->flags = amd->flags;
-}
-
-static void arrayModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- ArrayModifierData *amd = (ArrayModifierData*) md;
-
- walk(userData, ob, &amd->start_cap);
- walk(userData, ob, &amd->end_cap);
- walk(userData, ob, &amd->curve_ob);
- walk(userData, ob, &amd->offset_ob);
-}
-
-static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
- Object *ob, DagNode *obNode)
-{
- ArrayModifierData *amd = (ArrayModifierData*) md;
-
- if (amd->start_cap) {
- DagNode *curNode = dag_get_node(forest, amd->start_cap);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->end_cap) {
- DagNode *curNode = dag_get_node(forest, amd->end_cap);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->curve_ob) {
- DagNode *curNode = dag_get_node(forest, amd->curve_ob);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->offset_ob) {
- DagNode *curNode = dag_get_node(forest, amd->offset_ob);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
-}
-
-static float vertarray_size(MVert *mvert, int numVerts, int axis)
-{
- int i;
- float min_co, max_co;
-
- /* if there are no vertices, width is 0 */
- if(numVerts == 0) return 0;
-
- /* find the minimum and maximum coordinates on the desired axis */
- min_co = max_co = mvert->co[axis];
- ++mvert;
- for(i = 1; i < numVerts; ++i, ++mvert) {
- if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
- if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
- }
-
- return max_co - min_co;
-}
-
-typedef struct IndexMapEntry {
- /* the new vert index that this old vert index maps to */
- int new;
- /* -1 if this vert isn't merged, otherwise the old vert index it
- * should be replaced with
- */
- int merge;
- /* 1 if this vert's first copy is merged with the last copy of its
- * merge target, otherwise 0
- */
- short merge_final;
-} IndexMapEntry;
-
-/* indexMap - an array of IndexMap entries
- * oldIndex - the old index to map
- * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
- */
-static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
-{
- if(indexMap[oldIndex].merge < 0) {
- /* vert wasn't merged, so use copy of this vert */
- return indexMap[oldIndex].new + copyNum;
- } else if(indexMap[oldIndex].merge == oldIndex) {
- /* vert was merged with itself */
- return indexMap[oldIndex].new;
- } else {
- /* vert was merged with another vert */
- /* follow the chain of merges to the end, or until we've passed
- * a number of vertices equal to the copy number
- */
- if(copyNum <= 0)
- return indexMap[oldIndex].new;
- else
- return calc_mapping(indexMap, indexMap[oldIndex].merge,
- copyNum - 1);
- }
-}
-
-static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
- Scene *scene, Object *ob, DerivedMesh *dm,
- int initFlags)
-{
- int i, j;
- /* offset matrix */
- float offset[4][4];
- float final_offset[4][4];
- float tmp_mat[4][4];
- float length = amd->length;
- int count = amd->count;
- int numVerts, numEdges, numFaces;
- int maxVerts, maxEdges, maxFaces;
- int finalVerts, finalEdges, finalFaces;
- DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
- MVert *mvert, *src_mvert;
- MEdge *medge;
- MFace *mface;
-
- IndexMapEntry *indexMap;
-
- EdgeHash *edges;
-
- /* need to avoid infinite recursion here */
- if(amd->start_cap && amd->start_cap != ob)
- start_cap = amd->start_cap->derivedFinal;
- if(amd->end_cap && amd->end_cap != ob)
- end_cap = amd->end_cap->derivedFinal;
-
- unit_m4(offset);
-
- indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
- "indexmap");
-
- src_mvert = dm->getVertArray(dm);
-
- maxVerts = dm->getNumVerts(dm);
-
- if(amd->offset_type & MOD_ARR_OFF_CONST)
- add_v3_v3v3(offset[3], offset[3], amd->offset);
- if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
- for(j = 0; j < 3; j++)
- offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
- maxVerts, j);
- }
-
- if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
- float obinv[4][4];
- float result_mat[4][4];
-
- if(ob)
- invert_m4_m4(obinv, ob->obmat);
- else
- unit_m4(obinv);
-
- mul_serie_m4(result_mat, offset,
- obinv, amd->offset_ob->obmat,
- NULL, NULL, NULL, NULL, NULL);
- copy_m4_m4(offset, result_mat);
- }
-
- if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
- Curve *cu = amd->curve_ob->data;
- if(cu) {
- float tmp_mat[3][3];
- float scale;
-
- object_to_mat3(amd->curve_ob, tmp_mat);
- scale = mat3_to_scale(tmp_mat);
-
- if(!cu->path) {
- cu->flag |= CU_PATH; // needed for path & bevlist
- makeDispListCurveTypes(scene, amd->curve_ob, 0);
- }
- if(cu->path)
- length = scale*cu->path->totdist;
- }
- }
-
- /* calculate the maximum number of copies which will fit within the
- prescribed length */
- if(amd->fit_type == MOD_ARR_FITLENGTH
- || amd->fit_type == MOD_ARR_FITCURVE) {
- float dist = sqrt(dot_v3v3(offset[3], offset[3]));
-
- if(dist > 1e-6f)
- /* this gives length = first copy start to last copy end
- add a tiny offset for floating point rounding errors */
- count = (length + 1e-6f) / dist;
- else
- /* if the offset has no translation, just make one copy */
- count = 1;
- }
-
- if(count < 1)
- count = 1;
-
- /* allocate memory for count duplicates (including original) plus
- * start and end caps
- */
- finalVerts = dm->getNumVerts(dm) * count;
- finalEdges = dm->getNumEdges(dm) * count;
- finalFaces = dm->getNumFaces(dm) * count;
- if(start_cap) {
- finalVerts += start_cap->getNumVerts(start_cap);
- finalEdges += start_cap->getNumEdges(start_cap);
- finalFaces += start_cap->getNumFaces(start_cap);
- }
- if(end_cap) {
- finalVerts += end_cap->getNumVerts(end_cap);
- finalEdges += end_cap->getNumEdges(end_cap);
- finalFaces += end_cap->getNumFaces(end_cap);
- }
- result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
-
- /* calculate the offset matrix of the final copy (for merging) */
- unit_m4(final_offset);
-
- for(j=0; j < count - 1; j++) {
- mul_m4_m4m4(tmp_mat, final_offset, offset);
- copy_m4_m4(final_offset, tmp_mat);
- }
-
- numVerts = numEdges = numFaces = 0;
- mvert = CDDM_get_verts(result);
-
- for (i = 0; i < maxVerts; i++) {
- indexMap[i].merge = -1; /* default to no merge */
- indexMap[i].merge_final = 0; /* default to no merge */
- }
-
- for (i = 0; i < maxVerts; i++) {
- MVert *inMV;
- MVert *mv = &mvert[numVerts];
- MVert *mv2;
- float co[3];
-
- inMV = &src_mvert[i];
-
- DM_copy_vert_data(dm, result, i, numVerts, 1);
- *mv = *inMV;
- numVerts++;
-
- indexMap[i].new = numVerts - 1;
-
- VECCOPY(co, mv->co);
-
- /* Attempts to merge verts from one duplicate with verts from the
- * next duplicate which are closer than amd->merge_dist.
- * Only the first such vert pair is merged.
- * If verts are merged in the first duplicate pair, they are merged
- * in all pairs.
- */
- if((count > 1) && (amd->flags & MOD_ARR_MERGE)) {
- float tmp_co[3];
- VECCOPY(tmp_co, mv->co);
- mul_m4_v3(offset, tmp_co);
-
- for(j = 0; j < maxVerts; j++) {
- /* if vertex already merged, don't use it */
- if( indexMap[j].merge != -1 ) continue;
-
- inMV = &src_mvert[j];
- /* if this vert is within merge limit, merge */
- if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist)) {
- indexMap[i].merge = j;
-
- /* test for merging with final copy of merge target */
- if(amd->flags & MOD_ARR_MERGEFINAL) {
- VECCOPY(tmp_co, inMV->co);
- inMV = &src_mvert[i];
- mul_m4_v3(final_offset, tmp_co);
- if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist))
- indexMap[i].merge_final = 1;
- }
- break;
- }
- }
- }
-
- /* if no merging, generate copies of this vert */
- if(indexMap[i].merge < 0) {
- for(j=0; j < count - 1; j++) {
- mv2 = &mvert[numVerts];
-
- DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
- *mv2 = *mv;
- numVerts++;
-
- mul_m4_v3(offset, co);
- VECCOPY(mv2->co, co);
- }
- } else if(indexMap[i].merge != i && indexMap[i].merge_final) {
- /* if this vert is not merging with itself, and it is merging
- * with the final copy of its merge target, remove the first copy
- */
- numVerts--;
- DM_free_vert_data(result, numVerts, 1);
- }
- }
-
- /* make a hashtable so we can avoid duplicate edges from merging */
- edges = BLI_edgehash_new();
-
- maxEdges = dm->getNumEdges(dm);
- medge = CDDM_get_edges(result);
- for(i = 0; i < maxEdges; i++) {
- MEdge inMED;
- MEdge med;
- MEdge *med2;
- int vert1, vert2;
-
- dm->getEdge(dm, i, &inMED);
-
- med = inMED;
- med.v1 = indexMap[inMED.v1].new;
- med.v2 = indexMap[inMED.v2].new;
-
- /* if vertices are to be merged with the final copies of their
- * merge targets, calculate that final copy
- */
- if(indexMap[inMED.v1].merge_final) {
- med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
- count - 1);
- }
- if(indexMap[inMED.v2].merge_final) {
- med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
- count - 1);
- }
-
- if(med.v1 == med.v2) continue;
-
- if (initFlags) {
- med.flag |= ME_EDGEDRAW | ME_EDGERENDER;
- }
-
- if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) {
- DM_copy_edge_data(dm, result, i, numEdges, 1);
- medge[numEdges] = med;
- numEdges++;
-
- BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
- }
-
- for(j = 1; j < count; j++)
- {
- vert1 = calc_mapping(indexMap, inMED.v1, j);
- vert2 = calc_mapping(indexMap, inMED.v2, j);
- /* avoid duplicate edges */
- if(!BLI_edgehash_haskey(edges, vert1, vert2)) {
- med2 = &medge[numEdges];
-
- DM_copy_edge_data(dm, result, i, numEdges, 1);
- *med2 = med;
- numEdges++;
-
- med2->v1 = vert1;
- med2->v2 = vert2;
-
- BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL);
- }
- }
- }
-
- maxFaces = dm->getNumFaces(dm);
- mface = CDDM_get_faces(result);
- for (i=0; i < maxFaces; i++) {
- MFace inMF;
- MFace *mf = &mface[numFaces];
-
- dm->getFace(dm, i, &inMF);
-
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf = inMF;
-
- mf->v1 = indexMap[inMF.v1].new;
- mf->v2 = indexMap[inMF.v2].new;
- mf->v3 = indexMap[inMF.v3].new;
- if(inMF.v4)
- mf->v4 = indexMap[inMF.v4].new;
-
- /* if vertices are to be merged with the final copies of their
- * merge targets, calculate that final copy
- */
- if(indexMap[inMF.v1].merge_final)
- mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
- if(indexMap[inMF.v2].merge_final)
- mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
- if(indexMap[inMF.v3].merge_final)
- mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
- if(inMF.v4 && indexMap[inMF.v4].merge_final)
- mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
-
- if(test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3) < 3)
- continue;
-
- numFaces++;
-
- /* if the face has fewer than 3 vertices, don't create it */
- if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) {
- numFaces--;
- DM_free_face_data(result, numFaces, 1);
- }
-
- for(j = 1; j < count; j++)
- {
- MFace *mf2 = &mface[numFaces];
-
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf2 = *mf;
-
- mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
- mf2->v2 = calc_mapping(indexMap, inMF.v2, j);
- mf2->v3 = calc_mapping(indexMap, inMF.v3, j);
- if (inMF.v4)
- mf2->v4 = calc_mapping(indexMap, inMF.v4, j);
-
- test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
- numFaces++;
-
- /* if the face has fewer than 3 vertices, don't create it */
- if(mf2->v3 == 0 || (mf2->v1 && (mf2->v1 == mf2->v3 || mf2->v1 ==
- mf2->v4))) {
- numFaces--;
- DM_free_face_data(result, numFaces, 1);
- }
- }
- }
-
- /* add start and end caps */
- if(start_cap) {
- float startoffset[4][4];
- MVert *cap_mvert;
- MEdge *cap_medge;
- MFace *cap_mface;
- int *origindex;
- int *vert_map;
- int capVerts, capEdges, capFaces;
-
- capVerts = start_cap->getNumVerts(start_cap);
- capEdges = start_cap->getNumEdges(start_cap);
- capFaces = start_cap->getNumFaces(start_cap);
- cap_mvert = start_cap->getVertArray(start_cap);
- cap_medge = start_cap->getEdgeArray(start_cap);
- cap_mface = start_cap->getFaceArray(start_cap);
-
- invert_m4_m4(startoffset, offset);
-
- vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
- "arrayModifier_doArray vert_map");
-
- origindex = result->getVertDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capVerts; i++) {
- MVert *mv = &cap_mvert[i];
- short merged = 0;
-
- if(amd->flags & MOD_ARR_MERGE) {
- float tmp_co[3];
- MVert *in_mv;
- int j;
-
- VECCOPY(tmp_co, mv->co);
- mul_m4_v3(startoffset, tmp_co);
-
- for(j = 0; j < maxVerts; j++) {
- in_mv = &src_mvert[j];
- /* if this vert is within merge limit, merge */
- if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
- vert_map[i] = calc_mapping(indexMap, j, 0);
- merged = 1;
- break;
- }
- }
- }
-
- if(!merged) {
- DM_copy_vert_data(start_cap, result, i, numVerts, 1);
- mvert[numVerts] = *mv;
- mul_m4_v3(startoffset, mvert[numVerts].co);
- origindex[numVerts] = ORIGINDEX_NONE;
-
- vert_map[i] = numVerts;
-
- numVerts++;
- }
- }
- origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capEdges; i++) {
- int v1, v2;
-
- v1 = vert_map[cap_medge[i].v1];
- v2 = vert_map[cap_medge[i].v2];
-
- if(!BLI_edgehash_haskey(edges, v1, v2)) {
- DM_copy_edge_data(start_cap, result, i, numEdges, 1);
- medge[numEdges] = cap_medge[i];
- medge[numEdges].v1 = v1;
- medge[numEdges].v2 = v2;
- origindex[numEdges] = ORIGINDEX_NONE;
-
- numEdges++;
- }
- }
- origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capFaces; i++) {
- DM_copy_face_data(start_cap, result, i, numFaces, 1);
- mface[numFaces] = cap_mface[i];
- mface[numFaces].v1 = vert_map[mface[numFaces].v1];
- mface[numFaces].v2 = vert_map[mface[numFaces].v2];
- mface[numFaces].v3 = vert_map[mface[numFaces].v3];
- if(mface[numFaces].v4) {
- mface[numFaces].v4 = vert_map[mface[numFaces].v4];
-
- test_index_face(&mface[numFaces], &result->faceData,
- numFaces, 4);
- }
- else
- {
- test_index_face(&mface[numFaces], &result->faceData,
- numFaces, 3);
- }
-
- origindex[numFaces] = ORIGINDEX_NONE;
-
- numFaces++;
- }
-
- MEM_freeN(vert_map);
- start_cap->release(start_cap);
- }
-
- if(end_cap) {
- float endoffset[4][4];
- MVert *cap_mvert;
- MEdge *cap_medge;
- MFace *cap_mface;
- int *origindex;
- int *vert_map;
- int capVerts, capEdges, capFaces;
-
- capVerts = end_cap->getNumVerts(end_cap);
- capEdges = end_cap->getNumEdges(end_cap);
- capFaces = end_cap->getNumFaces(end_cap);
- cap_mvert = end_cap->getVertArray(end_cap);
- cap_medge = end_cap->getEdgeArray(end_cap);
- cap_mface = end_cap->getFaceArray(end_cap);
-
- mul_m4_m4m4(endoffset, final_offset, offset);
-
- vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
- "arrayModifier_doArray vert_map");
-
- origindex = result->getVertDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capVerts; i++) {
- MVert *mv = &cap_mvert[i];
- short merged = 0;
-
- if(amd->flags & MOD_ARR_MERGE) {
- float tmp_co[3];
- MVert *in_mv;
- int j;
-
- VECCOPY(tmp_co, mv->co);
- mul_m4_v3(offset, tmp_co);
-
- for(j = 0; j < maxVerts; j++) {
- in_mv = &src_mvert[j];
- /* if this vert is within merge limit, merge */
- if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
- vert_map[i] = calc_mapping(indexMap, j, count - 1);
- merged = 1;
- break;
- }
- }
- }
-
- if(!merged) {
- DM_copy_vert_data(end_cap, result, i, numVerts, 1);
- mvert[numVerts] = *mv;
- mul_m4_v3(endoffset, mvert[numVerts].co);
- origindex[numVerts] = ORIGINDEX_NONE;
-
- vert_map[i] = numVerts;
-
- numVerts++;
- }
- }
- origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capEdges; i++) {
- int v1, v2;
-
- v1 = vert_map[cap_medge[i].v1];
- v2 = vert_map[cap_medge[i].v2];
-
- if(!BLI_edgehash_haskey(edges, v1, v2)) {
- DM_copy_edge_data(end_cap, result, i, numEdges, 1);
- medge[numEdges] = cap_medge[i];
- medge[numEdges].v1 = v1;
- medge[numEdges].v2 = v2;
- origindex[numEdges] = ORIGINDEX_NONE;
-
- numEdges++;
- }
- }
- origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capFaces; i++) {
- DM_copy_face_data(end_cap, result, i, numFaces, 1);
- mface[numFaces] = cap_mface[i];
- mface[numFaces].v1 = vert_map[mface[numFaces].v1];
- mface[numFaces].v2 = vert_map[mface[numFaces].v2];
- mface[numFaces].v3 = vert_map[mface[numFaces].v3];
- if(mface[numFaces].v4) {
- mface[numFaces].v4 = vert_map[mface[numFaces].v4];
-
- test_index_face(&mface[numFaces], &result->faceData,
- numFaces, 4);
- }
- else
- {
- test_index_face(&mface[numFaces], &result->faceData,
- numFaces, 3);
- }
- origindex[numFaces] = ORIGINDEX_NONE;
-
- numFaces++;
- }
-
- MEM_freeN(vert_map);
- end_cap->release(end_cap);
- }
-
- BLI_edgehash_free(edges, NULL);
- MEM_freeN(indexMap);
-
- CDDM_lower_num_verts(result, numVerts);
- CDDM_lower_num_edges(result, numEdges);
- CDDM_lower_num_faces(result, numFaces);
-
- return result;
-}
-
-static DerivedMesh *arrayModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *result;
- ArrayModifierData *amd = (ArrayModifierData*) md;
-
- result = arrayModifier_doArray(amd, md->scene, ob, derivedData, 0);
-
- if(result != derivedData)
- CDDM_calc_normals(result);
-
- return result;
-}
-
-static DerivedMesh *arrayModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData)
-{
- return arrayModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Mirror */
-
-static void mirrorModifier_initData(ModifierData *md)
-{
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
- mmd->tolerance = 0.001;
- mmd->mirror_ob = NULL;
-}
-
-static void mirrorModifier_copyData(ModifierData *md, ModifierData *target)
-{
- MirrorModifierData *mmd = (MirrorModifierData*) md;
- MirrorModifierData *tmmd = (MirrorModifierData*) target;
-
- tmmd->axis = mmd->axis;
- tmmd->flag = mmd->flag;
- tmmd->tolerance = mmd->tolerance;
- tmmd->mirror_ob = mmd->mirror_ob;;
-}
-
-static void mirrorModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- walk(userData, ob, &mmd->mirror_ob);
-}
-
-static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
- Object *ob, DagNode *obNode)
-{
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- if(mmd->mirror_ob) {
- DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
-
- dag_add_relation(forest, latNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
- }
-}
-
-static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
- Object *ob,
- DerivedMesh *dm,
- int initFlags,
- int axis)
-{
- int i;
- float tolerance = mmd->tolerance;
- DerivedMesh *result;
- int numVerts, numEdges, numFaces;
- int maxVerts = dm->getNumVerts(dm);
- int maxEdges = dm->getNumEdges(dm);
- int maxFaces = dm->getNumFaces(dm);
- int *flip_map= NULL;
- int do_vgroup_mirr= (mmd->flag & MOD_MIR_VGROUP);
- int (*indexMap)[2];
- float mtx[4][4], imtx[4][4];
-
- numVerts = numEdges = numFaces = 0;
-
- indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
-
- result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
-
-
- if (do_vgroup_mirr) {
- flip_map= defgroup_flip_map(ob, 0);
- if(flip_map == NULL)
- do_vgroup_mirr= 0;
- }
-
- if (mmd->mirror_ob) {
- float obinv[4][4];
-
- invert_m4_m4(obinv, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, ob->obmat, obinv);
- invert_m4_m4(imtx, mtx);
- }
-
- for(i = 0; i < maxVerts; i++) {
- MVert inMV;
- MVert *mv = CDDM_get_vert(result, numVerts);
- int isShared;
- float co[3];
-
- dm->getVert(dm, i, &inMV);
-
- copy_v3_v3(co, inMV.co);
-
- if (mmd->mirror_ob) {
- mul_v3_m4v3(co, mtx, co);
- }
- isShared = ABS(co[axis])<=tolerance;
-
- /* Because the topology result (# of vertices) must be the same if
- * the mesh data is overridden by vertex cos, have to calc sharedness
- * based on original coordinates. This is why we test before copy.
- */
- DM_copy_vert_data(dm, result, i, numVerts, 1);
- *mv = inMV;
- numVerts++;
-
- indexMap[i][0] = numVerts - 1;
- indexMap[i][1] = !isShared;
-
- if(isShared) {
- co[axis] = 0;
- if (mmd->mirror_ob) {
- mul_v3_m4v3(co, imtx, co);
- }
- copy_v3_v3(mv->co, co);
-
- mv->flag |= ME_VERT_MERGED;
- } else {
- MVert *mv2 = CDDM_get_vert(result, numVerts);
-
- DM_copy_vert_data(dm, result, i, numVerts, 1);
- *mv2 = *mv;
-
- co[axis] = -co[axis];
- if (mmd->mirror_ob) {
- mul_v3_m4v3(co, imtx, co);
- }
- copy_v3_v3(mv2->co, co);
-
- if (do_vgroup_mirr) {
- MDeformVert *dvert= DM_get_vert_data(result, numVerts, CD_MDEFORMVERT);
- if(dvert) {
- defvert_flip(dvert, flip_map);
- }
- }
-
- numVerts++;
- }
- }
-
- for(i = 0; i < maxEdges; i++) {
- MEdge inMED;
- MEdge *med = CDDM_get_edge(result, numEdges);
-
- dm->getEdge(dm, i, &inMED);
-
- DM_copy_edge_data(dm, result, i, numEdges, 1);
- *med = inMED;
- numEdges++;
-
- med->v1 = indexMap[inMED.v1][0];
- med->v2 = indexMap[inMED.v2][0];
- if(initFlags)
- med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
-
- if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
- MEdge *med2 = CDDM_get_edge(result, numEdges);
-
- DM_copy_edge_data(dm, result, i, numEdges, 1);
- *med2 = *med;
- numEdges++;
-
- med2->v1 += indexMap[inMED.v1][1];
- med2->v2 += indexMap[inMED.v2][1];
- }
- }
-
- for(i = 0; i < maxFaces; i++) {
- MFace inMF;
- MFace *mf = CDDM_get_face(result, numFaces);
-
- dm->getFace(dm, i, &inMF);
-
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf = inMF;
- numFaces++;
-
- mf->v1 = indexMap[inMF.v1][0];
- mf->v2 = indexMap[inMF.v2][0];
- mf->v3 = indexMap[inMF.v3][0];
- mf->v4 = indexMap[inMF.v4][0];
-
- if(indexMap[inMF.v1][1]
- || indexMap[inMF.v2][1]
- || indexMap[inMF.v3][1]
- || (mf->v4 && indexMap[inMF.v4][1])) {
- MFace *mf2 = CDDM_get_face(result, numFaces);
- static int corner_indices[4] = {2, 1, 0, 3};
-
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf2 = *mf;
-
- mf2->v1 += indexMap[inMF.v1][1];
- mf2->v2 += indexMap[inMF.v2][1];
- mf2->v3 += indexMap[inMF.v3][1];
- if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
-
- /* mirror UVs if enabled */
- if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
- MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
- if(tf) {
- int j;
- for(j = 0; j < 4; ++j) {
- if(mmd->flag & MOD_MIR_MIRROR_U)
- tf->uv[j][0] = 1.0f - tf->uv[j][0];
- if(mmd->flag & MOD_MIR_MIRROR_V)
- tf->uv[j][1] = 1.0f - tf->uv[j][1];
- }
- }
- }
-
- /* Flip face normal */
- SWAP(int, mf2->v1, mf2->v3);
- DM_swap_face_data(result, numFaces, corner_indices);
-
- test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
- numFaces++;
- }
- }
-
- if (flip_map) MEM_freeN(flip_map);
-
- MEM_freeN(indexMap);
-
- CDDM_lower_num_verts(result, numVerts);
- CDDM_lower_num_edges(result, numEdges);
- CDDM_lower_num_faces(result, numFaces);
-
- return result;
-}
-
-static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
- Object *ob, DerivedMesh *dm,
- int initFlags)
-{
- DerivedMesh *result = dm;
-
- /* check which axes have been toggled and mirror accordingly */
- if(mmd->flag & MOD_MIR_AXIS_X) {
- result = doMirrorOnAxis(mmd, ob, result, initFlags, 0);
- }
- if(mmd->flag & MOD_MIR_AXIS_Y) {
- DerivedMesh *tmp = result;
- result = doMirrorOnAxis(mmd, ob, result, initFlags, 1);
- if(tmp != dm) tmp->release(tmp); /* free intermediate results */
- }
- if(mmd->flag & MOD_MIR_AXIS_Z) {
- DerivedMesh *tmp = result;
- result = doMirrorOnAxis(mmd, ob, result, initFlags, 2);
- if(tmp != dm) tmp->release(tmp); /* free intermediate results */
- }
-
- return result;
-}
-
-static DerivedMesh *mirrorModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *result;
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- result = mirrorModifier__doMirror(mmd, ob, derivedData, 0);
-
- if(result != derivedData)
- CDDM_calc_normals(result);
-
- return result;
-}
-
-static DerivedMesh *mirrorModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData)
-{
- return mirrorModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* EdgeSplit */
-/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
- * or edge angle (can be used to achieve autosmoothing)
-*/
-#if 0
-#define EDGESPLIT_DEBUG_3
-#define EDGESPLIT_DEBUG_2
-#define EDGESPLIT_DEBUG_1
-#define EDGESPLIT_DEBUG_0
-#endif
-
-static void edgesplitModifier_initData(ModifierData *md)
-{
- EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
-
- /* default to 30-degree split angle, sharpness from both angle & flag
- */
- emd->split_angle = 30;
- emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
-}
-
-static void edgesplitModifier_copyData(ModifierData *md, ModifierData *target)
-{
- EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
- EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
-
- temd->split_angle = emd->split_angle;
- temd->flags = emd->flags;
-}
-
-/* Mesh data for edgesplit operation */
-typedef struct SmoothVert {
- LinkNode *faces; /* all faces which use this vert */
- int oldIndex; /* the index of the original DerivedMesh vert */
- int newIndex; /* the index of the new DerivedMesh vert */
-} SmoothVert;
-
-#define SMOOTHEDGE_NUM_VERTS 2
-
-typedef struct SmoothEdge {
- SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
- LinkNode *faces; /* all faces which use this edge */
- int oldIndex; /* the index of the original DerivedMesh edge */
- int newIndex; /* the index of the new DerivedMesh edge */
- short flag; /* the flags from the original DerivedMesh edge */
-} SmoothEdge;
-
-#define SMOOTHFACE_MAX_EDGES 4
-
-typedef struct SmoothFace {
- SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
- int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
- float normal[3]; /* the normal of this face */
- int oldIndex; /* the index of the original DerivedMesh face */
- int newIndex; /* the index of the new DerivedMesh face */
-} SmoothFace;
-
-typedef struct SmoothMesh {
- SmoothVert *verts;
- SmoothEdge *edges;
- SmoothFace *faces;
- int num_verts, num_edges, num_faces;
- int max_verts, max_edges, max_faces;
- DerivedMesh *dm;
- float threshold; /* the cosine of the smoothing angle */
- int flags;
- MemArena *arena;
- ListBase propagatestack, reusestack;
-} SmoothMesh;
-
-static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
-{
- SmoothVert *copy = &mesh->verts[mesh->num_verts];
-
- if(mesh->num_verts >= mesh->max_verts) {
- printf("Attempted to add a SmoothMesh vert beyond end of array\n");
- return NULL;
- }
-
- *copy = *vert;
- copy->faces = NULL;
- copy->newIndex = mesh->num_verts;
- ++mesh->num_verts;
-
-#ifdef EDGESPLIT_DEBUG_2
- printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
-#endif
- return copy;
-}
-
-static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
-{
- SmoothEdge *copy = &mesh->edges[mesh->num_edges];
-
- if(mesh->num_edges >= mesh->max_edges) {
- printf("Attempted to add a SmoothMesh edge beyond end of array\n");
- return NULL;
- }
-
- *copy = *edge;
- copy->faces = NULL;
- copy->newIndex = mesh->num_edges;
- ++mesh->num_edges;
-
-#ifdef EDGESPLIT_DEBUG_2
- printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
-#endif
- return copy;
-}
-
-static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
-{
- int i;
- for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
- if(edge->verts[i] == vert) return 1;
-
- return 0;
-}
-
-static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
- int max_verts, int max_edges, int max_faces)
-{
- SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
- mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
- "SmoothMesh.verts");
- mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
- "SmoothMesh.edges");
- mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
- "SmoothMesh.faces");
-
- mesh->num_verts = num_verts;
- mesh->num_edges = num_edges;
- mesh->num_faces = num_faces;
-
- mesh->max_verts = max_verts;
- mesh->max_edges = max_edges;
- mesh->max_faces = max_faces;
-
- return mesh;
-}
-
-static void smoothmesh_free(SmoothMesh *mesh)
-{
- int i;
-
- for(i = 0; i < mesh->num_verts; ++i)
- BLI_linklist_free(mesh->verts[i].faces, NULL);
-
- for(i = 0; i < mesh->num_edges; ++i)
- BLI_linklist_free(mesh->edges[i].faces, NULL);
-
- if(mesh->arena)
- BLI_memarena_free(mesh->arena);
-
- MEM_freeN(mesh->verts);
- MEM_freeN(mesh->edges);
- MEM_freeN(mesh->faces);
- MEM_freeN(mesh);
-}
-
-static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
-{
- int i;
- SmoothVert *tmp;
-
- if(max_verts <= mesh->max_verts) return;
-
- tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
-
- memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
-
- /* remap vert pointers in edges */
- for(i = 0; i < mesh->num_edges; ++i) {
- int j;
- SmoothEdge *edge = &mesh->edges[i];
-
- for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
- /* pointer arithmetic to get vert array index */
- edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
- }
-
- MEM_freeN(mesh->verts);
- mesh->verts = tmp;
- mesh->max_verts = max_verts;
-}
-
-static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
-{
- int i;
- SmoothEdge *tmp;
-
- if(max_edges <= mesh->max_edges) return;
-
- tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
-
- memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
-
- /* remap edge pointers in faces */
- for(i = 0; i < mesh->num_faces; ++i) {
- int j;
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
- if(face->edges[j])
- /* pointer arithmetic to get edge array index */
- face->edges[j] = &tmp[face->edges[j] - mesh->edges];
- }
-
- MEM_freeN(mesh->edges);
- mesh->edges = tmp;
- mesh->max_edges = max_edges;
-}
-
-#ifdef EDGESPLIT_DEBUG_0
-static void smoothmesh_print(SmoothMesh *mesh)
-{
- int i, j;
- DerivedMesh *dm = mesh->dm;
-
- printf("--- SmoothMesh ---\n");
- printf("--- Vertices ---\n");
- for(i = 0; i < mesh->num_verts; i++) {
- SmoothVert *vert = &mesh->verts[i];
- LinkNode *node;
- MVert mv;
-
- dm->getVert(dm, vert->oldIndex, &mv);
-
- printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
- i, vert->oldIndex, vert->newIndex,
- mv.co[0], mv.co[1], mv.co[2]);
- printf(", faces={");
- for(node = vert->faces; node != NULL; node = node->next) {
- printf(" %d", ((SmoothFace *)node->link)->newIndex);
- }
- printf("}\n");
- }
-
- printf("\n--- Edges ---\n");
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- LinkNode *node;
-
- printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
- i,
- edge->oldIndex, edge->newIndex,
- edge->verts[0]->newIndex, edge->verts[1]->newIndex);
- if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
- printf(", faces={");
- for(node = edge->faces; node != NULL; node = node->next) {
- printf(" %d", ((SmoothFace *)node->link)->newIndex);
- }
- printf("}\n");
- }
-
- printf("\n--- Faces ---\n");
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- printf("%4d: indices={%4d, %4d}, edges={", i,
- face->oldIndex, face->newIndex);
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- if(face->flip[j])
- printf(" -%-2d", face->edges[j]->newIndex);
- else
- printf(" %-2d", face->edges[j]->newIndex);
- }
- printf("}, verts={");
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
- }
- printf("}\n");
- }
-}
-#endif
-
-static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
-{
- SmoothMesh *mesh;
- EdgeHash *edges = BLI_edgehash_new();
- int i;
- int totvert, totedge, totface;
-
- totvert = dm->getNumVerts(dm);
- totedge = dm->getNumEdges(dm);
- totface = dm->getNumFaces(dm);
-
- mesh = smoothmesh_new(totvert, totedge, totface,
- totvert, totedge, totface);
-
- mesh->dm = dm;
-
- for(i = 0; i < totvert; i++) {
- SmoothVert *vert = &mesh->verts[i];
-
- vert->oldIndex = vert->newIndex = i;
- }
-
- for(i = 0; i < totedge; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- MEdge med;
-
- dm->getEdge(dm, i, &med);
- edge->verts[0] = &mesh->verts[med.v1];
- edge->verts[1] = &mesh->verts[med.v2];
- edge->oldIndex = edge->newIndex = i;
- edge->flag = med.flag;
-
- BLI_edgehash_insert(edges, med.v1, med.v2, edge);
- }
-
- for(i = 0; i < totface; i++) {
- SmoothFace *face = &mesh->faces[i];
- MFace mf;
- MVert v1, v2, v3;
- int j;
-
- dm->getFace(dm, i, &mf);
-
- dm->getVert(dm, mf.v1, &v1);
- dm->getVert(dm, mf.v2, &v2);
- dm->getVert(dm, mf.v3, &v3);
- face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
- if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
- face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
- if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
- if(mf.v4) {
- MVert v4;
- dm->getVert(dm, mf.v4, &v4);
- face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
- if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
- face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
- if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
- normal_quad_v3( face->normal,v1.co, v2.co, v3.co, v4.co);
- } else {
- face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
- if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
- face->edges[3] = NULL;
- normal_tri_v3( face->normal,v1.co, v2.co, v3.co);
- }
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- BLI_linklist_prepend(&edge->faces, face);
- BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
- }
-
- face->oldIndex = face->newIndex = i;
- }
-
- BLI_edgehash_free(edges, NULL);
-
- return mesh;
-}
-
-static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
-{
- DerivedMesh *result = CDDM_from_template(mesh->dm,
- mesh->num_verts,
- mesh->num_edges,
- mesh->num_faces);
- MVert *new_verts = CDDM_get_verts(result);
- MEdge *new_edges = CDDM_get_edges(result);
- MFace *new_faces = CDDM_get_faces(result);
- int i;
-
- for(i = 0; i < mesh->num_verts; ++i) {
- SmoothVert *vert = &mesh->verts[i];
- MVert *newMV = &new_verts[vert->newIndex];
-
- DM_copy_vert_data(mesh->dm, result,
- vert->oldIndex, vert->newIndex, 1);
- mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
- }
-
- for(i = 0; i < mesh->num_edges; ++i) {
- SmoothEdge *edge = &mesh->edges[i];
- MEdge *newME = &new_edges[edge->newIndex];
-
- DM_copy_edge_data(mesh->dm, result,
- edge->oldIndex, edge->newIndex, 1);
- mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
- newME->v1 = edge->verts[0]->newIndex;
- newME->v2 = edge->verts[1]->newIndex;
- }
-
- for(i = 0; i < mesh->num_faces; ++i) {
- SmoothFace *face = &mesh->faces[i];
- MFace *newMF = &new_faces[face->newIndex];
-
- DM_copy_face_data(mesh->dm, result,
- face->oldIndex, face->newIndex, 1);
- mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
-
- newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
- newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
- newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
-
- if(face->edges[3]) {
- newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
- } else {
- newMF->v4 = 0;
- }
- }
-
- return result;
-}
-
-/* returns the other vert in the given edge
- */
-static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
-{
- if(edge->verts[0] == vert) return edge->verts[1];
- else return edge->verts[0];
-}
-
-/* returns the other edge in the given face that uses the given vert
- * returns NULL if no other edge in the given face uses the given vert
- * (this should never happen)
- */
-static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
- SmoothEdge *edge)
-{
- int i,j;
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
- SmoothEdge *tmp_edge = face->edges[i];
- if(tmp_edge == edge) continue;
-
- for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
- if(tmp_edge->verts[j] == vert) return tmp_edge;
- }
-
- /* if we get to here, something's wrong (there should always be 2 edges
- * which use the same vert in a face)
- */
- return NULL;
-}
-
-/* returns a face attached to the given edge which is not the given face.
- * returns NULL if no other faces use this edge.
- */
-static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
-{
- LinkNode *node;
-
- for(node = edge->faces; node != NULL; node = node->next)
- if(node->link != face) return node->link;
-
- return NULL;
-}
-
-#if 0
-/* copies source list to target, overwriting target (target is not freed)
- * nodes in the copy will be in the same order as in source
- */
-static void linklist_copy(LinkNode **target, LinkNode *source)
-{
- LinkNode *node = NULL;
- *target = NULL;
-
- for(; source; source = source->next) {
- if(node) {
- node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
- node = node->next;
-} else {
- node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
-}
- node->link = source->link;
- node->next = NULL;
-}
-}
-#endif
-
- /* appends source to target if it's not already in target */
- static void linklist_append_unique(LinkNode **target, void *source)
-{
- LinkNode *node;
- LinkNode *prev = NULL;
-
- /* check if source value is already in the list */
- for(node = *target; node; prev = node, node = node->next)
- if(node->link == source) return;
-
- node = MEM_mallocN(sizeof(*node), "nlink");
- node->next = NULL;
- node->link = source;
-
- if(prev) prev->next = node;
- else *target = node;
-}
-
-/* appends elements of source which aren't already in target to target */
-static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
-{
- for(; source; source = source->next)
- linklist_append_unique(target, source->link);
-}
-
-#if 0 /* this is no longer used, it should possibly be removed */
-/* prepends prepend to list - doesn't copy nodes, just joins the lists */
-static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
-{
- if(prepend) {
- LinkNode *node = prepend;
- while(node->next) node = node->next;
-
- node->next = *list;
- *list = prepend;
-}
-}
-#endif
-
-/* returns 1 if the linked list contains the given pointer, 0 otherwise
- */
-static int linklist_contains(LinkNode *list, void *ptr)
-{
- LinkNode *node;
-
- for(node = list; node; node = node->next)
- if(node->link == ptr) return 1;
-
- return 0;
-}
-
-/* returns 1 if the first linked list is a subset of the second (comparing
- * pointer values), 0 if not
- */
-static int linklist_subset(LinkNode *list1, LinkNode *list2)
-{
- for(; list1; list1 = list1->next)
- if(!linklist_contains(list2, list1->link))
- return 0;
-
- return 1;
-}
-
-#if 0
-/* empties the linked list
- * frees pointers with freefunc if freefunc is not NULL
- */
-static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
-{
- BLI_linklist_free(*list, freefunc);
- *list = NULL;
-}
-#endif
-
-/* removes the first instance of value from the linked list
- * frees the pointer with freefunc if freefunc is not NULL
- */
-static void linklist_remove_first(LinkNode **list, void *value,
- LinkNodeFreeFP freefunc)
-{
- LinkNode *node = *list;
- LinkNode *prev = NULL;
-
- while(node && node->link != value) {
- prev = node;
- node = node->next;
- }
-
- if(node) {
- if(prev)
- prev->next = node->next;
- else
- *list = node->next;
-
- if(freefunc)
- freefunc(node->link);
-
- MEM_freeN(node);
- }
-}
-
-/* removes all elements in source from target */
-static void linklist_remove_list(LinkNode **target, LinkNode *source,
- LinkNodeFreeFP freefunc)
-{
- for(; source; source = source->next)
- linklist_remove_first(target, source->link, freefunc);
-}
-
-#ifdef EDGESPLIT_DEBUG_0
-static void print_ptr(void *ptr)
-{
- printf("%p\n", ptr);
-}
-
-static void print_edge(void *ptr)
-{
- SmoothEdge *edge = ptr;
- printf(" %4d", edge->newIndex);
-}
-
-static void print_face(void *ptr)
-{
- SmoothFace *face = ptr;
- printf(" %4d", face->newIndex);
-}
-#endif
-
-typedef struct ReplaceData {
- void *find;
- void *replace;
-} ReplaceData;
-
-static void edge_replace_vert(void *ptr, void *userdata)
-{
- SmoothEdge *edge = ptr;
- SmoothVert *find = ((ReplaceData *)userdata)->find;
- SmoothVert *replace = ((ReplaceData *)userdata)->replace;
- int i;
-
-#ifdef EDGESPLIT_DEBUG_3
- printf("replacing vert %4d with %4d in edge %4d",
- find->newIndex, replace->newIndex, edge->newIndex);
- printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-
- for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
- if(edge->verts[i] == find) {
- linklist_append_list_unique(&replace->faces, edge->faces);
- linklist_remove_list(&find->faces, edge->faces, NULL);
-
- edge->verts[i] = replace;
- }
- }
-
-#ifdef EDGESPLIT_DEBUG_3
- printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-}
-
-static void face_replace_vert(void *ptr, void *userdata)
-{
- SmoothFace *face = ptr;
- int i;
-
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
- edge_replace_vert(face->edges[i], userdata);
-}
-
-static void face_replace_edge(void *ptr, void *userdata)
-{
- SmoothFace *face = ptr;
- SmoothEdge *find = ((ReplaceData *)userdata)->find;
- SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
- int i;
-
-#ifdef EDGESPLIT_DEBUG_3
- printf("replacing edge %4d with %4d in face %4d",
- find->newIndex, replace->newIndex, face->newIndex);
- if(face->edges[3])
- printf(": {%2d %2d %2d %2d}",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex, face->edges[3]->newIndex);
- else
- printf(": {%2d %2d %2d}",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex);
-#endif
-
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
- if(face->edges[i] == find) {
- linklist_remove_first(&face->edges[i]->faces, face, NULL);
- BLI_linklist_prepend(&replace->faces, face);
- face->edges[i] = replace;
- }
- }
-
-#ifdef EDGESPLIT_DEBUG_3
- if(face->edges[3])
- printf(" -> {%2d %2d %2d %2d}\n",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex, face->edges[3]->newIndex);
- else
- printf(" -> {%2d %2d %2d}\n",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex);
-#endif
-}
-
-static int edge_is_loose(SmoothEdge *edge)
-{
- return !(edge->faces && edge->faces->next);
-}
-
-static int edge_is_sharp(SmoothEdge *edge, int flags,
- float threshold)
-{
-#ifdef EDGESPLIT_DEBUG_1
- printf("edge %d: ", edge->newIndex);
-#endif
- if(edge->flag & ME_SHARP) {
- /* edge can only be sharp if it has at least 2 faces */
- if(!edge_is_loose(edge)) {
-#ifdef EDGESPLIT_DEBUG_1
- printf("sharp\n");
-#endif
- return 1;
- } else {
- /* edge is loose, so it can't be sharp */
- edge->flag &= ~ME_SHARP;
- }
- }
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("not sharp\n");
-#endif
- return 0;
-}
-
-/* finds another sharp edge which uses vert, by traversing faces around the
- * vert until it does one of the following:
- * - hits a loose edge (the edge is returned)
- * - hits a sharp edge (the edge is returned)
- * - returns to the start edge (NULL is returned)
- */
-static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge,
- LinkNode **visited_faces, float threshold, int flags)
-{
- SmoothFace *face = NULL;
- SmoothEdge *edge2 = NULL;
- /* holds the edges we've seen so we can avoid looping indefinitely */
- LinkNode *visited_edges = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-
- /* get a face on which to start */
- if(edge->faces) face = edge->faces->link;
- else return NULL;
-
- /* record this edge as visited */
- BLI_linklist_prepend(&visited_edges, edge);
-
- /* get the next edge */
- edge2 = other_edge(face, vert, edge);
-
- /* record this face as visited */
- if(visited_faces)
- BLI_linklist_prepend(visited_faces, face);
-
- /* search until we hit a loose edge or a sharp edge or an edge we've
- * seen before
- */
- while(face && !edge_is_sharp(edge2, flags, threshold)
- && !linklist_contains(visited_edges, edge2)) {
-#ifdef EDGESPLIT_DEBUG_3
- printf("current face %4d; current edge %4d\n", face->newIndex,
- edge2->newIndex);
-#endif
- /* get the next face */
- face = other_face(edge2, face);
-
- /* if face == NULL, edge2 is a loose edge */
- if(face) {
- /* record this face as visited */
- if(visited_faces)
- BLI_linklist_prepend(visited_faces, face);
-
- /* record this edge as visited */
- BLI_linklist_prepend(&visited_edges, edge2);
-
- /* get the next edge */
- edge2 = other_edge(face, vert, edge2);
-#ifdef EDGESPLIT_DEBUG_3
- printf("next face %4d; next edge %4d\n",
- face->newIndex, edge2->newIndex);
- } else {
- printf("loose edge: %4d\n", edge2->newIndex);
-#endif
- }
- }
-
- /* either we came back to the start edge or we found a sharp/loose edge */
- if(linklist_contains(visited_edges, edge2))
- /* we came back to the start edge */
- edge2 = NULL;
-
- BLI_linklist_free(visited_edges, NULL);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
- "returning edge %d\n",
- edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
-#endif
- return edge2;
-}
-
-static void split_single_vert(SmoothVert *vert, SmoothFace *face,
- SmoothMesh *mesh)
-{
- SmoothVert *copy_vert;
- ReplaceData repdata;
-
- copy_vert = smoothvert_copy(vert, mesh);
-
- repdata.find = vert;
- repdata.replace = copy_vert;
- face_replace_vert(face, &repdata);
-}
-
-typedef struct PropagateEdge {
- struct PropagateEdge *next, *prev;
- SmoothEdge *edge;
- SmoothVert *vert;
-} PropagateEdge;
-
-static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
- PropagateEdge *pedge = mesh->reusestack.first;
-
- if(pedge) {
- BLI_remlink(&mesh->reusestack, pedge);
- }
- else {
- if(!mesh->arena) {
- mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
- BLI_memarena_use_calloc(mesh->arena);
- }
-
- pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
- }
-
- pedge->edge = edge;
- pedge->vert = vert;
- BLI_addhead(&mesh->propagatestack, pedge);
-}
-
-static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh)
-{
- PropagateEdge *pedge = mesh->propagatestack.first;
-
- if(pedge) {
- *edge = pedge->edge;
- *vert = pedge->vert;
- BLI_remlink(&mesh->propagatestack, pedge);
- BLI_addhead(&mesh->reusestack, pedge);
- }
- else {
- *edge = NULL;
- *vert = NULL;
- }
-}
-
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
-
-static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
- SmoothMesh *mesh)
-{
- SmoothEdge *edge2;
- LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-
- edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
- mesh->threshold, mesh->flags);
-
- if(!edge2) {
- /* didn't find a sharp or loose edge, so we've hit a dead end */
- } else if(!edge_is_loose(edge2)) {
- /* edge2 is not loose, so it must be sharp */
- if(edge_is_loose(edge)) {
- /* edge is loose, so we can split edge2 at this vert */
- split_edge(edge2, vert, mesh);
- } else if(edge_is_sharp(edge, mesh->flags, mesh->threshold)) {
- /* both edges are sharp, so we can split the pair at vert */
- split_edge(edge, vert, mesh);
- } else {
- /* edge is not sharp, so try to split edge2 at its other vert */
- split_edge(edge2, other_vert(edge2, vert), mesh);
- }
- } else { /* edge2 is loose */
- if(edge_is_loose(edge)) {
- SmoothVert *vert2;
- ReplaceData repdata;
-
- /* can't split edge, what should we do with vert? */
- if(linklist_subset(vert->faces, visited_faces)) {
- /* vert has only one fan of faces attached; don't split it */
- } else {
- /* vert has more than one fan of faces attached; split it */
- vert2 = smoothvert_copy(vert, mesh);
-
- /* replace vert with its copy in visited_faces */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
- }
- } else {
- /* edge is not loose, so it must be sharp; split it */
- split_edge(edge, vert, mesh);
- }
- }
-
- BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-}
-
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
- SmoothEdge *edge2;
- SmoothVert *vert2;
- ReplaceData repdata;
- /* the list of faces traversed while looking for a sharp edge */
- LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-
- edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
- mesh->threshold, mesh->flags);
-
- if(!edge2) {
- /* didn't find a sharp or loose edge, so try the other vert */
- vert2 = other_vert(edge, vert);
- push_propagate_stack(edge, vert2, mesh);
- } else if(!edge_is_loose(edge2)) {
- /* edge2 is not loose, so it must be sharp */
- SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
- SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
- SmoothVert *vert2;
-
- /* replace edge with its copy in visited_faces */
- repdata.find = edge;
- repdata.replace = copy_edge;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- /* replace edge2 with its copy in visited_faces */
- repdata.find = edge2;
- repdata.replace = copy_edge2;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- vert2 = smoothvert_copy(vert, mesh);
-
- /* replace vert with its copy in visited_faces (must be done after
- * edge replacement so edges have correct vertices)
- */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
- /* all copying and replacing is done; the mesh should be consistent.
- * now propagate the split to the vertices at either end
- */
- push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
- push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh);
-
- if(smoothedge_has_vert(edge, vert))
- push_propagate_stack(edge, vert, mesh);
- } else {
- /* edge2 is loose */
- SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
- SmoothVert *vert2;
-
- /* replace edge with its copy in visited_faces */
- repdata.find = edge;
- repdata.replace = copy_edge;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- vert2 = smoothvert_copy(vert, mesh);
-
- /* replace vert with its copy in visited_faces (must be done after
- * edge replacement so edges have correct vertices)
- */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
- /* copying and replacing is done; the mesh should be consistent.
- * now propagate the split to the vertex at the other end
- */
- push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
-
- if(smoothedge_has_vert(edge, vert))
- push_propagate_stack(edge, vert, mesh);
- }
-
- BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-}
-
-static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
- int flags, int *extra_edges)
-{
- /* if normal1 dot normal2 < threshold, angle is greater, so split */
- /* FIXME not sure if this always works */
- /* 0.00001 added for floating-point rounding */
- float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
- int i;
-
- *extra_edges = 0;
-
- /* loop through edges, counting potential new ones */
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- int sharp = 0;
-
- /* treat all non-manifold edges (3 or more faces) as sharp */
- if(edge->faces && edge->faces->next && edge->faces->next->next) {
- LinkNode *node;
-
- /* this edge is sharp */
- sharp = 1;
-
- /* add an extra edge for every face beyond the first */
- *extra_edges += 2;
- for(node = edge->faces->next->next->next; node; node = node->next)
- (*extra_edges)++;
- } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
- && !edge_is_loose(edge)) {
- /* (the edge can only be sharp if we're checking angle or flag,
- * and it has at least 2 faces) */
-
- /* if we're checking the sharp flag and it's set, good */
- if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
- /* this edge is sharp */
- sharp = 1;
-
- (*extra_edges)++;
- } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
- /* we know the edge has 2 faces, so check the angle */
- SmoothFace *face1 = edge->faces->link;
- SmoothFace *face2 = edge->faces->next->link;
- float edge_angle_cos = dot_v3v3(face1->normal,
- face2->normal);
-
- if(edge_angle_cos < threshold) {
- /* this edge is sharp */
- sharp = 1;
-
- (*extra_edges)++;
- }
- }
- }
-
- /* set/clear sharp flag appropriately */
- if(sharp) edge->flag |= ME_SHARP;
- else edge->flag &= ~ME_SHARP;
- }
-}
-
-static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
-{
- SmoothVert *vert;
- int i;
- /* if normal1 dot normal2 < threshold, angle is greater, so split */
- /* FIXME not sure if this always works */
- /* 0.00001 added for floating-point rounding */
- mesh->threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
- mesh->flags = flags;
-
- /* loop through edges, splitting sharp ones */
- /* can't use an iterator here, because we'll be adding edges */
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
-
- if(edge_is_sharp(edge, flags, mesh->threshold)) {
- split_edge(edge, edge->verts[0], mesh);
-
- do {
- pop_propagate_stack(&edge, &vert, mesh);
- if(edge && smoothedge_has_vert(edge, vert))
- propagate_split(edge, vert, mesh);
- } while(edge);
- }
- }
-}
-
-static int count_bridge_verts(SmoothMesh *mesh)
-{
- int i, j, count = 0;
-
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- SmoothEdge *next_edge;
- SmoothVert *vert = edge->verts[1 - face->flip[j]];
- int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
- /* wrap next around if at last edge */
- if(!face->edges[next]) next = 0;
-
- next_edge = face->edges[next];
-
- /* if there are other faces sharing this vertex but not
- * these edges, the vertex will be split, so count it
- */
- /* vert has to have at least one face (this one), so faces != 0 */
- if(!edge->faces->next && !next_edge->faces->next
- && vert->faces->next) {
- count++;
- }
- }
- }
-
- /* each bridge vert will be counted once per face that uses it,
- * so count is too high, but it's ok for now
- */
- return count;
-}
-
-static void split_bridge_verts(SmoothMesh *mesh)
-{
- int i,j;
-
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- SmoothEdge *next_edge;
- SmoothVert *vert = edge->verts[1 - face->flip[j]];
- int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
- /* wrap next around if at last edge */
- if(!face->edges[next]) next = 0;
-
- next_edge = face->edges[next];
-
- /* if there are other faces sharing this vertex but not
- * these edges, split the vertex
- */
- /* vert has to have at least one face (this one), so faces != 0 */
- if(!edge->faces->next && !next_edge->faces->next
- && vert->faces->next)
- /* FIXME this needs to find all faces that share edges with
- * this one and split off together
- */
- split_single_vert(vert, face, mesh);
- }
- }
-}
-
-static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
- Object *ob, DerivedMesh *dm)
-{
- SmoothMesh *mesh;
- DerivedMesh *result;
- int max_verts, max_edges;
-
- if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
- return dm;
-
- /* 1. make smoothmesh with initial number of elements */
- mesh = smoothmesh_from_derivedmesh(dm);
-
- /* 2. count max number of elements to add */
- tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
- max_verts = max_edges * 2 + mesh->max_verts;
- max_verts += count_bridge_verts(mesh);
- max_edges += mesh->max_edges;
-
- /* 3. reallocate smoothmesh arrays & copy elements across */
- /* 4. remap copied elements' pointers to point into the new arrays */
- smoothmesh_resize_verts(mesh, max_verts);
- smoothmesh_resize_edges(mesh, max_edges);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Pre-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
- split_sharp_edges(mesh, emd->split_angle, emd->flags);
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Post-edge-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
- split_bridge_verts(mesh);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Post-vert-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
-#ifdef EDGESPLIT_DEBUG_0
- printf("Edgesplit: Estimated %d verts & %d edges, "
- "found %d verts & %d edges\n", max_verts, max_edges,
- mesh->num_verts, mesh->num_edges);
-#endif
-
- result = CDDM_from_smoothmesh(mesh);
- smoothmesh_free(mesh);
-
- return result;
-}
-
-static DerivedMesh *edgesplitModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *result;
- EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
-
- result = edgesplitModifier_do(emd, ob, derivedData);
-
- if(result != derivedData)
- CDDM_calc_normals(result);
-
- return result;
-}
-
-static DerivedMesh *edgesplitModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData)
-{
- return edgesplitModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Bevel */
-
-static void bevelModifier_initData(ModifierData *md)
-{
- BevelModifierData *bmd = (BevelModifierData*) md;
-
- bmd->value = 0.1f;
- bmd->res = 1;
- bmd->flags = 0;
- bmd->val_flags = 0;
- bmd->lim_flags = 0;
- bmd->e_flags = 0;
- bmd->bevel_angle = 30;
- bmd->defgrp_name[0] = '\0';
-}
-
-static void bevelModifier_copyData(ModifierData *md, ModifierData *target)
-{
- BevelModifierData *bmd = (BevelModifierData*) md;
- BevelModifierData *tbmd = (BevelModifierData*) target;
-
- tbmd->value = bmd->value;
- tbmd->res = bmd->res;
- tbmd->flags = bmd->flags;
- tbmd->val_flags = bmd->val_flags;
- tbmd->lim_flags = bmd->lim_flags;
- tbmd->e_flags = bmd->e_flags;
- tbmd->bevel_angle = bmd->bevel_angle;
- strncpy(tbmd->defgrp_name, bmd->defgrp_name, 32);
-}
-
-static CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- BevelModifierData *bmd = (BevelModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(bmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static DerivedMesh *bevelModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *result;
- BME_Mesh *bm;
-
- /*bDeformGroup *def;*/
- int /*i,*/ options, defgrp_index = -1;
- BevelModifierData *bmd = (BevelModifierData*) md;
-
- options = bmd->flags|bmd->val_flags|bmd->lim_flags|bmd->e_flags;
-
- /*if ((options & BME_BEVEL_VWEIGHT) && bmd->defgrp_name[0]) {
- defgrp_index = defgroup_name_index(ob, bmd->defgrp_name);
- if (defgrp_index < 0) {
- options &= ~BME_BEVEL_VWEIGHT;
- }
- }*/
-
- bm = BME_derivedmesh_to_bmesh(derivedData);
- BME_bevel(bm,bmd->value,bmd->res,options,defgrp_index,bmd->bevel_angle,NULL);
- result = BME_bmesh_to_derivedmesh(bm,derivedData);
- BME_free_mesh(bm);
-
- CDDM_calc_normals(result);
-
- return result;
-}
-
-static DerivedMesh *bevelModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData)
-{
- return bevelModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Displace */
-
-static void displaceModifier_initData(ModifierData *md)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
- dmd->texture = NULL;
- dmd->strength = 1;
- dmd->direction = MOD_DISP_DIR_NOR;
- dmd->midlevel = 0.5;
-}
-
-static void displaceModifier_copyData(ModifierData *md, ModifierData *target)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData*) md;
- DisplaceModifierData *tdmd = (DisplaceModifierData*) target;
-
- tdmd->texture = dmd->texture;
- tdmd->strength = dmd->strength;
- tdmd->direction = dmd->direction;
- strncpy(tdmd->defgrp_name, dmd->defgrp_name, 32);
- tdmd->midlevel = dmd->midlevel;
- tdmd->texmapping = dmd->texmapping;
- tdmd->map_object = dmd->map_object;
- strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32);
-}
-
-static CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(dmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
- /* ask for UV coordinates if we need them */
- if(dmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE);
-
- return dataMask;
-}
-
-static int displaceModifier_dependsOnTime(ModifierData *md)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData *)md;
-
- if(dmd->texture)
- {
- return BKE_texture_dependsOnTime(dmd->texture);
- }
- else
- {
- return 0;
- }
-}
-
-static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob,
- ObjectWalkFunc walk, void *userData)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
- walk(userData, ob, &dmd->map_object);
-}
-
-static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob,
- IDWalkFunc walk, void *userData)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
- walk(userData, ob, (ID **)&dmd->texture);
-
- displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
-}
-
-static int displaceModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
- return !dmd->texture;
-}
-
-static void displaceModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene,
- Object *ob, DagNode *obNode)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
- if(dmd->map_object) {
- DagNode *curNode = dag_get_node(forest, dmd->map_object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier");
- }
-}
-
-static void validate_layer_name(const CustomData *data, int type, char *name, char *outname)
-{
- int index = -1;
-
- /* if a layer name was given, try to find that layer */
- if(name[0])
- index = CustomData_get_named_layer_index(data, CD_MTFACE, name);
-
- if(index < 0) {
- /* either no layer was specified, or the layer we want has been
- * deleted, so assign the active layer to name
- */
- index = CustomData_get_active_layer_index(data, CD_MTFACE);
- strcpy(outname, data->layers[index].name);
- }
- else
- strcpy(outname, name);
-}
-
-static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
- DerivedMesh *dm,
- float (*co)[3], float (*texco)[3],
- int numVerts)
-{
- int i;
- int texmapping = dmd->texmapping;
- float mapob_imat[4][4];
-
- if(texmapping == MOD_DISP_MAP_OBJECT) {
- if(dmd->map_object)
- invert_m4_m4(mapob_imat, dmd->map_object->obmat);
- else /* if there is no map object, default to local */
- texmapping = MOD_DISP_MAP_LOCAL;
- }
-
- /* UVs need special handling, since they come from faces */
- if(texmapping == MOD_DISP_MAP_UV) {
- if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
- MFace *mface = dm->getFaceArray(dm);
- MFace *mf;
- char *done = MEM_callocN(sizeof(*done) * numVerts,
- "get_texture_coords done");
- int numFaces = dm->getNumFaces(dm);
- char uvname[32];
- MTFace *tf;
-
- validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname);
- tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
-
- /* verts are given the UV from the first face that uses them */
- for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
- if(!done[mf->v1]) {
- texco[mf->v1][0] = tf->uv[0][0];
- texco[mf->v1][1] = tf->uv[0][1];
- texco[mf->v1][2] = 0;
- done[mf->v1] = 1;
- }
- if(!done[mf->v2]) {
- texco[mf->v2][0] = tf->uv[1][0];
- texco[mf->v2][1] = tf->uv[1][1];
- texco[mf->v2][2] = 0;
- done[mf->v2] = 1;
- }
- if(!done[mf->v3]) {
- texco[mf->v3][0] = tf->uv[2][0];
- texco[mf->v3][1] = tf->uv[2][1];
- texco[mf->v3][2] = 0;
- done[mf->v3] = 1;
- }
- if(!done[mf->v4]) {
- texco[mf->v4][0] = tf->uv[3][0];
- texco[mf->v4][1] = tf->uv[3][1];
- texco[mf->v4][2] = 0;
- done[mf->v4] = 1;
- }
- }
-
- /* remap UVs from [0, 1] to [-1, 1] */
- for(i = 0; i < numVerts; ++i) {
- texco[i][0] = texco[i][0] * 2 - 1;
- texco[i][1] = texco[i][1] * 2 - 1;
- }
-
- MEM_freeN(done);
- return;
- } else /* if there are no UVs, default to local */
- texmapping = MOD_DISP_MAP_LOCAL;
- }
-
- for(i = 0; i < numVerts; ++i, ++co, ++texco) {
- switch(texmapping) {
- case MOD_DISP_MAP_LOCAL:
- VECCOPY(*texco, *co);
- break;
- case MOD_DISP_MAP_GLOBAL:
- VECCOPY(*texco, *co);
- mul_m4_v3(ob->obmat, *texco);
- break;
- case MOD_DISP_MAP_OBJECT:
- VECCOPY(*texco, *co);
- mul_m4_v3(ob->obmat, *texco);
- mul_m4_v3(mapob_imat, *texco);
- break;
- }
- }
-}
-
-static void get_texture_value(Tex *texture, float *tex_co, TexResult *texres)
-{
- int result_type;
-
- result_type = multitex_ext(texture, tex_co, NULL, NULL, 0, texres);
-
- /* if the texture gave an RGB value, we assume it didn't give a valid
- * intensity, so calculate one (formula from do_material_tex).
- * if the texture didn't give an RGB value, copy the intensity across
- */
- if(result_type & TEX_RGB)
- texres->tin = (0.35f * texres->tr + 0.45f * texres->tg
- + 0.2f * texres->tb);
- else
- texres->tr = texres->tg = texres->tb = texres->tin;
-}
-
-/* dm must be a CDDerivedMesh */
-static void displaceModifier_do(
- DisplaceModifierData *dmd, Object *ob,
- DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
-{
- int i;
- MVert *mvert;
- MDeformVert *dvert = NULL;
- int defgrp_index;
- float (*tex_co)[3];
-
- if(!dmd->texture) return;
-
- defgrp_index = defgroup_name_index(ob, dmd->defgrp_name);
-
- mvert = CDDM_get_verts(dm);
- if(defgrp_index >= 0)
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- tex_co = MEM_callocN(sizeof(*tex_co) * numVerts,
- "displaceModifier_do tex_co");
- get_texture_coords(dmd, ob, dm, vertexCos, tex_co, numVerts);
-
- for(i = 0; i < numVerts; ++i) {
- TexResult texres;
- float delta = 0, strength = dmd->strength;
- MDeformWeight *def_weight = NULL;
-
- if(dvert) {
- int j;
- for(j = 0; j < dvert[i].totweight; ++j) {
- if(dvert[i].dw[j].def_nr == defgrp_index) {
- def_weight = &dvert[i].dw[j];
- break;
- }
- }
- if(!def_weight) continue;
- }
-
- texres.nor = NULL;
- get_texture_value(dmd->texture, tex_co[i], &texres);
-
- delta = texres.tin - dmd->midlevel;
-
- if(def_weight) strength *= def_weight->weight;
-
- delta *= strength;
-
- switch(dmd->direction) {
- case MOD_DISP_DIR_X:
- vertexCos[i][0] += delta;
- break;
- case MOD_DISP_DIR_Y:
- vertexCos[i][1] += delta;
- break;
- case MOD_DISP_DIR_Z:
- vertexCos[i][2] += delta;
- break;
- case MOD_DISP_DIR_RGB_XYZ:
- vertexCos[i][0] += (texres.tr - dmd->midlevel) * strength;
- vertexCos[i][1] += (texres.tg - dmd->midlevel) * strength;
- vertexCos[i][2] += (texres.tb - dmd->midlevel) * strength;
- break;
- case MOD_DISP_DIR_NOR:
- vertexCos[i][0] += delta * mvert[i].no[0] / 32767.0f;
- vertexCos[i][1] += delta * mvert[i].no[1] / 32767.0f;
- vertexCos[i][2] += delta * mvert[i].no[2] / 32767.0f;
- break;
- }
- }
-
- MEM_freeN(tex_co);
-}
-
-static void displaceModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm= get_cddm(md->scene, ob, NULL, derivedData, vertexCos);
-
- displaceModifier_do((DisplaceModifierData *)md, ob, dm,
- vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static void displaceModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm= get_cddm(md->scene, ob, editData, derivedData, vertexCos);
-
- displaceModifier_do((DisplaceModifierData *)md, ob, dm,
- vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-/* UVProject */
-/* UV Project modifier: Generates UVs projected from an object
-*/
-
-static void uvprojectModifier_initData(ModifierData *md)
-{
- UVProjectModifierData *umd = (UVProjectModifierData*) md;
- int i;
-
- for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
- umd->projectors[i] = NULL;
- umd->image = NULL;
- umd->flags = 0;
- umd->num_projectors = 1;
- umd->aspectx = umd->aspecty = 1.0f;
- umd->scalex = umd->scaley = 1.0f;
-}
-
-static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target)
-{
- UVProjectModifierData *umd = (UVProjectModifierData*) md;
- UVProjectModifierData *tumd = (UVProjectModifierData*) target;
- int i;
-
- for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
- tumd->projectors[i] = umd->projectors[i];
- tumd->image = umd->image;
- tumd->flags = umd->flags;
- tumd->num_projectors = umd->num_projectors;
- tumd->aspectx = umd->aspectx;
- tumd->aspecty = umd->aspecty;
- tumd->scalex = umd->scalex;
- tumd->scaley = umd->scaley;
-}
-
-static CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- CustomDataMask dataMask = 0;
-
- /* ask for UV coordinates */
- dataMask |= (1 << CD_MTFACE);
-
- return dataMask;
-}
-
-static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob,
- ObjectWalkFunc walk, void *userData)
-{
- UVProjectModifierData *umd = (UVProjectModifierData*) md;
- int i;
-
- for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
- walk(userData, ob, &umd->projectors[i]);
-}
-
-static void uvprojectModifier_foreachIDLink(ModifierData *md, Object *ob,
- IDWalkFunc walk, void *userData)
-{
- UVProjectModifierData *umd = (UVProjectModifierData*) md;
-
- walk(userData, ob, (ID **)&umd->image);
-
- uvprojectModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk,
- userData);
-}
-
-static void uvprojectModifier_updateDepgraph(ModifierData *md,
- DagForest *forest, Scene *scene, Object *ob, DagNode *obNode)
-{
- UVProjectModifierData *umd = (UVProjectModifierData*) md;
- int i;
-
- for(i = 0; i < umd->num_projectors; ++i) {
- if(umd->projectors[i]) {
- DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "UV Project Modifier");
- }
- }
-}
-
-typedef struct Projector {
- Object *ob; /* object this projector is derived from */
- float projmat[4][4]; /* projection matrix */
- float normal[3]; /* projector normal in world space */
- void *uci; /* optional uv-project info (panorama projection) */
-} Projector;
-
-static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
- Object *ob, DerivedMesh *dm)
-{
- float (*coords)[3], (*co)[3];
- MTFace *tface;
- int i, numVerts, numFaces;
- Image *image = umd->image;
- MFace *mface, *mf;
- int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
- Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
- int num_projectors = 0;
- float aspect;
- char uvname[32];
- float aspx= umd->aspectx ? umd->aspectx : 1.0f;
- float aspy= umd->aspecty ? umd->aspecty : 1.0f;
- float scax= umd->scalex ? umd->scalex : 1.0f;
- float scay= umd->scaley ? umd->scaley : 1.0f;
- int free_uci= 0;
-
- aspect = aspx / aspy;
-
- for(i = 0; i < umd->num_projectors; ++i)
- if(umd->projectors[i])
- projectors[num_projectors++].ob = umd->projectors[i];
-
- if(num_projectors == 0) return dm;
-
- /* make sure there are UV layers available */
-
- if(!CustomData_has_layer(&dm->faceData, CD_MTFACE)) return dm;
-
- /* make sure we're using an existing layer */
- validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname);
-
- /* calculate a projection matrix and normal for each projector */
- for(i = 0; i < num_projectors; ++i) {
- float tmpmat[4][4];
- float offsetmat[4][4];
- Camera *cam = NULL;
- /* calculate projection matrix */
- invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat);
-
- projectors[i].uci= NULL;
-
- if(projectors[i].ob->type == OB_CAMERA) {
- cam = (Camera *)projectors[i].ob->data;
-
- if(cam->flag & CAM_PANORAMA) {
- projectors[i].uci= project_camera_info(projectors[i].ob, NULL, aspx, aspy);
- free_uci= 1;
- }
- else if(cam->type == CAM_PERSP) {
- float perspmat[4][4];
- float xmax;
- float xmin;
- float ymax;
- float ymin;
- float pixsize = cam->clipsta * 32.0 / cam->lens;
-
- if(aspect > 1.0f) {
- xmax = 0.5f * pixsize;
- ymax = xmax / aspect;
- } else {
- ymax = 0.5f * pixsize;
- xmax = ymax * aspect;
- }
- xmin = -xmax;
- ymin = -ymax;
-
- perspective_m4( perspmat,xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend);
- mul_m4_m4m4(tmpmat, projectors[i].projmat, perspmat);
- } else if(cam->type == CAM_ORTHO) {
- float orthomat[4][4];
- float xmax;
- float xmin;
- float ymax;
- float ymin;
-
- if(aspect > 1.0f) {
- xmax = 0.5f * cam->ortho_scale;
- ymax = xmax / aspect;
- } else {
- ymax = 0.5f * cam->ortho_scale;
- xmax = ymax * aspect;
- }
- xmin = -xmax;
- ymin = -ymax;
-
- orthographic_m4( orthomat,xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend);
- mul_m4_m4m4(tmpmat, projectors[i].projmat, orthomat);
- }
- } else {
- copy_m4_m4(tmpmat, projectors[i].projmat);
- }
-
- unit_m4(offsetmat);
- mul_mat3_m4_fl(offsetmat, 0.5);
- offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5;
-
- if (cam) {
- if (aspx == aspy) {
- offsetmat[3][0] -= cam->shiftx;
- offsetmat[3][1] -= cam->shifty;
- } else if (aspx < aspy) {
- offsetmat[3][0] -=(cam->shiftx * aspy/aspx);
- offsetmat[3][1] -= cam->shifty;
- } else {
- offsetmat[3][0] -= cam->shiftx;
- offsetmat[3][1] -=(cam->shifty * aspx/aspy);
- }
- }
-
- mul_m4_m4m4(projectors[i].projmat, tmpmat, offsetmat);
-
- /* calculate worldspace projector normal (for best projector test) */
- projectors[i].normal[0] = 0;
- projectors[i].normal[1] = 0;
- projectors[i].normal[2] = 1;
- mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal);
- }
-
- /* make sure we are not modifying the original UV layer */
- tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
- CD_MTFACE, uvname);
-
-
- numVerts = dm->getNumVerts(dm);
-
- coords = MEM_callocN(sizeof(*coords) * numVerts,
- "uvprojectModifier_do coords");
- dm->getVertCos(dm, coords);
-
- /* convert coords to world space */
- for(i = 0, co = coords; i < numVerts; ++i, ++co)
- mul_m4_v3(ob->obmat, *co);
-
- /* if only one projector, project coords to UVs */
- if(num_projectors == 1 && projectors[0].uci==NULL)
- for(i = 0, co = coords; i < numVerts; ++i, ++co)
- mul_project_m4_v4(projectors[0].projmat, *co);
-
- mface = dm->getFaceArray(dm);
- numFaces = dm->getNumFaces(dm);
-
- /* apply coords as UVs, and apply image if tfaces are new */
- for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) {
- if(override_image || !image || tface->tpage == image) {
- if(num_projectors == 1) {
- if(projectors[0].uci) {
- project_from_camera(tface->uv[0], coords[mf->v1], projectors[0].uci);
- project_from_camera(tface->uv[1], coords[mf->v2], projectors[0].uci);
- project_from_camera(tface->uv[2], coords[mf->v3], projectors[0].uci);
- if(mf->v3)
- project_from_camera(tface->uv[3], coords[mf->v4], projectors[0].uci);
-
- if(scax != 1.0f) {
- tface->uv[0][0] = ((tface->uv[0][0] - 0.5f) * scax) + 0.5f;
- tface->uv[1][0] = ((tface->uv[1][0] - 0.5f) * scax) + 0.5f;
- tface->uv[2][0] = ((tface->uv[2][0] - 0.5f) * scax) + 0.5f;
- if(mf->v3)
- tface->uv[3][0] = ((tface->uv[3][0] - 0.5f) * scax) + 0.5f;
- }
-
- if(scay != 1.0f) {
- tface->uv[0][1] = ((tface->uv[0][1] - 0.5f) * scay) + 0.5f;
- tface->uv[1][1] = ((tface->uv[1][1] - 0.5f) * scay) + 0.5f;
- tface->uv[2][1] = ((tface->uv[2][1] - 0.5f) * scay) + 0.5f;
- if(mf->v3)
- tface->uv[3][1] = ((tface->uv[3][1] - 0.5f) * scay) + 0.5f;
- }
- }
- else {
- /* apply transformed coords as UVs */
- tface->uv[0][0] = coords[mf->v1][0];
- tface->uv[0][1] = coords[mf->v1][1];
- tface->uv[1][0] = coords[mf->v2][0];
- tface->uv[1][1] = coords[mf->v2][1];
- tface->uv[2][0] = coords[mf->v3][0];
- tface->uv[2][1] = coords[mf->v3][1];
- if(mf->v4) {
- tface->uv[3][0] = coords[mf->v4][0];
- tface->uv[3][1] = coords[mf->v4][1];
- }
- }
- } else {
- /* multiple projectors, select the closest to face normal
- * direction
- */
- float co1[3], co2[3], co3[3], co4[3];
- float face_no[3];
- int j;
- Projector *best_projector;
- float best_dot;
-
- VECCOPY(co1, coords[mf->v1]);
- VECCOPY(co2, coords[mf->v2]);
- VECCOPY(co3, coords[mf->v3]);
-
- /* get the untransformed face normal */
- if(mf->v4) {
- VECCOPY(co4, coords[mf->v4]);
- normal_quad_v3( face_no,co1, co2, co3, co4);
- } else {
- normal_tri_v3( face_no,co1, co2, co3);
- }
-
- /* find the projector which the face points at most directly
- * (projector normal with largest dot product is best)
- */
- best_dot = dot_v3v3(projectors[0].normal, face_no);
- best_projector = &projectors[0];
-
- for(j = 1; j < num_projectors; ++j) {
- float tmp_dot = dot_v3v3(projectors[j].normal,
- face_no);
- if(tmp_dot > best_dot) {
- best_dot = tmp_dot;
- best_projector = &projectors[j];
- }
- }
-
- if(best_projector->uci) {
- project_from_camera(tface->uv[0], coords[mf->v1], best_projector->uci);
- project_from_camera(tface->uv[1], coords[mf->v2], best_projector->uci);
- project_from_camera(tface->uv[2], coords[mf->v3], best_projector->uci);
- if(mf->v3)
- project_from_camera(tface->uv[3], coords[mf->v4], best_projector->uci);
- }
- else {
- mul_project_m4_v4(best_projector->projmat, co1);
- mul_project_m4_v4(best_projector->projmat, co2);
- mul_project_m4_v4(best_projector->projmat, co3);
- if(mf->v4)
- mul_project_m4_v4(best_projector->projmat, co4);
-
- /* apply transformed coords as UVs */
- tface->uv[0][0] = co1[0];
- tface->uv[0][1] = co1[1];
- tface->uv[1][0] = co2[0];
- tface->uv[1][1] = co2[1];
- tface->uv[2][0] = co3[0];
- tface->uv[2][1] = co3[1];
- if(mf->v4) {
- tface->uv[3][0] = co4[0];
- tface->uv[3][1] = co4[1];
- }
- }
- }
- }
-
- if(override_image) {
- tface->mode = TF_TEX;
- tface->tpage = image;
- }
- }
-
- MEM_freeN(coords);
-
- if(free_uci) {
- int j;
- for(j = 0; j < num_projectors; ++j) {
- if(projectors[j].uci) {
- MEM_freeN(projectors[j].uci);
- }
- }
- }
- return dm;
-}
-
-static DerivedMesh *uvprojectModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *result;
- UVProjectModifierData *umd = (UVProjectModifierData*) md;
-
- result = uvprojectModifier_do(umd, ob, derivedData);
-
- return result;
-}
-
-static DerivedMesh *uvprojectModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData)
-{
- return uvprojectModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Decimate */
-
-static void decimateModifier_initData(ModifierData *md)
-{
- DecimateModifierData *dmd = (DecimateModifierData*) md;
-
- dmd->percent = 1.0;
-}
-
-static void decimateModifier_copyData(ModifierData *md, ModifierData *target)
-{
- DecimateModifierData *dmd = (DecimateModifierData*) md;
- DecimateModifierData *tdmd = (DecimateModifierData*) target;
-
- tdmd->percent = dmd->percent;
-}
-
-static DerivedMesh *decimateModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DecimateModifierData *dmd = (DecimateModifierData*) md;
- DerivedMesh *dm = derivedData, *result = NULL;
- MVert *mvert;
- MFace *mface;
- LOD_Decimation_Info lod;
- int totvert, totface;
- int a, numTris;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
- totvert = dm->getNumVerts(dm);
- totface = dm->getNumFaces(dm);
-
- numTris = 0;
- for (a=0; a<totface; a++) {
- MFace *mf = &mface[a];
- numTris++;
- if (mf->v4) numTris++;
- }
-
- if(numTris<3) {
- modifier_setError(md,
- "Modifier requires more than 3 input faces (triangles).");
- goto exit;
- }
-
- lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices");
- lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*totvert, "normals");
- lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*numTris, "trias");
- lod.vertex_num= totvert;
- lod.face_num= numTris;
-
- for(a=0; a<totvert; a++) {
- MVert *mv = &mvert[a];
- float *vbCo = &lod.vertex_buffer[a*3];
- float *vbNo = &lod.vertex_normal_buffer[a*3];
-
- VECCOPY(vbCo, mv->co);
-
- vbNo[0] = mv->no[0]/32767.0f;
- vbNo[1] = mv->no[1]/32767.0f;
- vbNo[2] = mv->no[2]/32767.0f;
- }
-
- numTris = 0;
- for(a=0; a<totface; a++) {
- MFace *mf = &mface[a];
- int *tri = &lod.triangle_index_buffer[3*numTris++];
- tri[0]= mf->v1;
- tri[1]= mf->v2;
- tri[2]= mf->v3;
-
- if(mf->v4) {
- tri = &lod.triangle_index_buffer[3*numTris++];
- tri[0]= mf->v1;
- tri[1]= mf->v3;
- tri[2]= mf->v4;
- }
- }
-
- dmd->faceCount = 0;
- if(LOD_LoadMesh(&lod) ) {
- if( LOD_PreprocessMesh(&lod) ) {
- /* we assume the decim_faces tells how much to reduce */
-
- while(lod.face_num > numTris*dmd->percent) {
- if( LOD_CollapseEdge(&lod)==0) break;
- }
-
- if(lod.vertex_num>2) {
- result = CDDM_new(lod.vertex_num, 0, lod.face_num);
- dmd->faceCount = lod.face_num;
- }
- else
- result = CDDM_new(lod.vertex_num, 0, 0);
-
- mvert = CDDM_get_verts(result);
- for(a=0; a<lod.vertex_num; a++) {
- MVert *mv = &mvert[a];
- float *vbCo = &lod.vertex_buffer[a*3];
-
- VECCOPY(mv->co, vbCo);
- }
-
- if(lod.vertex_num>2) {
- mface = CDDM_get_faces(result);
- for(a=0; a<lod.face_num; a++) {
- MFace *mf = &mface[a];
- int *tri = &lod.triangle_index_buffer[a*3];
- mf->v1 = tri[0];
- mf->v2 = tri[1];
- mf->v3 = tri[2];
- test_index_face(mf, NULL, 0, 3);
- }
- }
-
- CDDM_calc_edges(result);
- CDDM_calc_normals(result);
- }
- else
- modifier_setError(md, "Out of memory.");
-
- LOD_FreeDecimationData(&lod);
- }
- else
- modifier_setError(md, "Non-manifold mesh as input.");
-
- MEM_freeN(lod.vertex_buffer);
- MEM_freeN(lod.vertex_normal_buffer);
- MEM_freeN(lod.triangle_index_buffer);
-
-exit:
- return result;
-}
-
-/* Smooth */
-
-static void smoothModifier_initData(ModifierData *md)
-{
- SmoothModifierData *smd = (SmoothModifierData*) md;
-
- smd->fac = 0.5f;
- smd->repeat = 1;
- smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
- smd->defgrp_name[0] = '\0';
-}
-
-static void smoothModifier_copyData(ModifierData *md, ModifierData *target)
-{
- SmoothModifierData *smd = (SmoothModifierData*) md;
- SmoothModifierData *tsmd = (SmoothModifierData*) target;
-
- tsmd->fac = smd->fac;
- tsmd->repeat = smd->repeat;
- tsmd->flag = smd->flag;
- strncpy(tsmd->defgrp_name, smd->defgrp_name, 32);
-}
-
-static int smoothModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- SmoothModifierData *smd = (SmoothModifierData*) md;
- short flag;
-
- flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
-
- /* disable if modifier is off for X, Y and Z or if factor is 0 */
- if((smd->fac == 0.0f) || flag == 0) return 1;
-
- return 0;
-}
-
-static CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- SmoothModifierData *smd = (SmoothModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(smd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static void smoothModifier_do(
- SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts)
-{
- MDeformVert *dvert = NULL;
- MEdge *medges = NULL;
-
- int i, j, numDMEdges, defgrp_index;
- unsigned char *uctmp;
- float *ftmp, fac, facm;
-
- ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
- "smoothmodifier_f");
- if (!ftmp) return;
- uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
- "smoothmodifier_uc");
- if (!uctmp) {
- if (ftmp) MEM_freeN(ftmp);
- return;
- }
-
- fac = smd->fac;
- facm = 1 - fac;
-
- medges = dm->getEdgeArray(dm);
- numDMEdges = dm->getNumEdges(dm);
-
- defgrp_index = defgroup_name_index(ob, smd->defgrp_name);
-
- if (defgrp_index >= 0)
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- /* NOTICE: this can be optimized a little bit by moving the
- * if (dvert) out of the loop, if needed */
- for (j = 0; j < smd->repeat; j++) {
- for (i = 0; i < numDMEdges; i++) {
- float fvec[3];
- float *v1, *v2;
- unsigned int idx1, idx2;
-
- idx1 = medges[i].v1;
- idx2 = medges[i].v2;
-
- v1 = vertexCos[idx1];
- v2 = vertexCos[idx2];
-
- fvec[0] = (v1[0] + v2[0]) / 2.0;
- fvec[1] = (v1[1] + v2[1]) / 2.0;
- fvec[2] = (v1[2] + v2[2]) / 2.0;
-
- v1 = &ftmp[idx1*3];
- v2 = &ftmp[idx2*3];
-
- if (uctmp[idx1] < 255) {
- uctmp[idx1]++;
- add_v3_v3v3(v1, v1, fvec);
- }
- if (uctmp[idx2] < 255) {
- uctmp[idx2]++;
- add_v3_v3v3(v2, v2, fvec);
- }
- }
-
- if (dvert) {
- for (i = 0; i < numVerts; i++) {
- MDeformWeight *dw = NULL;
- float f, fm, facw, *fp, *v;
- int k;
- short flag = smd->flag;
-
- v = vertexCos[i];
- fp = &ftmp[i*3];
-
- for (k = 0; k < dvert[i].totweight; ++k) {
- if(dvert[i].dw[k].def_nr == defgrp_index) {
- dw = &dvert[i].dw[k];
- break;
- }
- }
- if (!dw) continue;
-
- f = fac * dw->weight;
- fm = 1.0f - f;
-
- /* fp is the sum of uctmp[i] verts, so must be averaged */
- facw = 0.0f;
- if (uctmp[i])
- facw = f / (float)uctmp[i];
-
- if (flag & MOD_SMOOTH_X)
- v[0] = fm * v[0] + facw * fp[0];
- if (flag & MOD_SMOOTH_Y)
- v[1] = fm * v[1] + facw * fp[1];
- if (flag & MOD_SMOOTH_Z)
- v[2] = fm * v[2] + facw * fp[2];
- }
- }
- else { /* no vertex group */
- for (i = 0; i < numVerts; i++) {
- float facw, *fp, *v;
- short flag = smd->flag;
-
- v = vertexCos[i];
- fp = &ftmp[i*3];
-
- /* fp is the sum of uctmp[i] verts, so must be averaged */
- facw = 0.0f;
- if (uctmp[i])
- facw = fac / (float)uctmp[i];
-
- if (flag & MOD_SMOOTH_X)
- v[0] = facm * v[0] + facw * fp[0];
- if (flag & MOD_SMOOTH_Y)
- v[1] = facm * v[1] + facw * fp[1];
- if (flag & MOD_SMOOTH_Z)
- v[2] = facm * v[2] + facw * fp[2];
- }
-
- }
-
- memset(ftmp, 0, 3*sizeof(float)*numVerts);
- memset(uctmp, 0, sizeof(unsigned char)*numVerts);
- }
-
- MEM_freeN(ftmp);
- MEM_freeN(uctmp);
-}
-
-static void smoothModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm= get_dm(md->scene, ob, NULL, derivedData, NULL, 0);
-
- smoothModifier_do((SmoothModifierData *)md, ob, dm,
- vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static void smoothModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm= get_dm(md->scene, ob, editData, derivedData, NULL, 0);
-
- smoothModifier_do((SmoothModifierData *)md, ob, dm,
- vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-/* Cast */
-
-static void castModifier_initData(ModifierData *md)
-{
- CastModifierData *cmd = (CastModifierData*) md;
-
- cmd->fac = 0.5f;
- cmd->radius = 0.0f;
- cmd->size = 0.0f;
- cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z
- | MOD_CAST_SIZE_FROM_RADIUS;
- cmd->type = MOD_CAST_TYPE_SPHERE;
- cmd->defgrp_name[0] = '\0';
- cmd->object = NULL;
-}
-
-
-static void castModifier_copyData(ModifierData *md, ModifierData *target)
-{
- CastModifierData *cmd = (CastModifierData*) md;
- CastModifierData *tcmd = (CastModifierData*) target;
-
- tcmd->fac = cmd->fac;
- tcmd->radius = cmd->radius;
- tcmd->size = cmd->size;
- tcmd->flag = cmd->flag;
- tcmd->type = cmd->type;
- tcmd->object = cmd->object;
- strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32);
-}
-
-static int castModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- CastModifierData *cmd = (CastModifierData*) md;
- short flag;
-
- flag = cmd->flag & (MOD_CAST_X|MOD_CAST_Y|MOD_CAST_Z);
-
- if((cmd->fac == 0.0f) || flag == 0) return 1;
-
- return 0;
-}
-
-static CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- CastModifierData *cmd = (CastModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(cmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static void castModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- CastModifierData *cmd = (CastModifierData*) md;
-
- walk (userData, ob, &cmd->object);
-}
-
-static void castModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
- DagNode *obNode)
-{
- CastModifierData *cmd = (CastModifierData*) md;
-
- if (cmd->object) {
- DagNode *curNode = dag_get_node(forest, cmd->object);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Cast Modifier");
- }
-}
-
-static void castModifier_sphere_do(
- CastModifierData *cmd, Object *ob, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts)
-{
- MDeformVert *dvert = NULL;
-
- Object *ctrl_ob = NULL;
-
- int i, defgrp_index;
- int has_radius = 0;
- short flag, type;
- float fac, facm, len = 0.0f;
- float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
- float mat[4][4], imat[4][4];
-
- fac = cmd->fac;
- facm = 1.0f - fac;
-
- flag = cmd->flag;
- type = cmd->type; /* projection type: sphere or cylinder */
-
- if (type == MOD_CAST_TYPE_CYLINDER)
- flag &= ~MOD_CAST_Z;
-
- ctrl_ob = cmd->object;
-
- /* spherify's center is {0, 0, 0} (the ob's own center in its local
- * space), by default, but if the user defined a control object,
- * we use its location, transformed to ob's local space */
- if (ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
- mul_m4_m4m4(mat, ob->obmat, ctrl_ob->imat);
- invert_m4_m4(imat, mat);
- }
-
- invert_m4_m4(ob->imat, ob->obmat);
- VECCOPY(center, ctrl_ob->obmat[3]);
- mul_m4_v3(ob->imat, center);
- }
-
- /* now we check which options the user wants */
-
- /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
- /* 2) cmd->radius > 0.0f: only the vertices within this radius from
- * the center of the effect should be deformed */
- if (cmd->radius > FLT_EPSILON) has_radius = 1;
-
- /* 3) if we were given a vertex group name,
- * only those vertices should be affected */
- defgrp_index = defgroup_name_index(ob, cmd->defgrp_name);
-
- if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- if(flag & MOD_CAST_SIZE_FROM_RADIUS) {
- len = cmd->radius;
- }
- else {
- len = cmd->size;
- }
-
- if(len <= 0) {
- for (i = 0; i < numVerts; i++) {
- len += len_v3v3(center, vertexCos[i]);
- }
- len /= numVerts;
-
- if (len == 0.0f) len = 10.0f;
- }
-
- /* ready to apply the effect, one vertex at a time;
- * tiny optimization: the code is separated (with parts repeated)
- * in two possible cases:
- * with or w/o a vgroup. With lots of if's in the code below,
- * further optimizations are possible, if needed */
- if (dvert) { /* with a vgroup */
- float fac_orig = fac;
- for (i = 0; i < numVerts; i++) {
- MDeformWeight *dw = NULL;
- int j;
- float tmp_co[3];
-
- VECCOPY(tmp_co, vertexCos[i]);
- if(ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(mat, tmp_co);
- } else {
- sub_v3_v3v3(tmp_co, tmp_co, center);
- }
- }
-
- VECCOPY(vec, tmp_co);
-
- if (type == MOD_CAST_TYPE_CYLINDER)
- vec[2] = 0.0f;
-
- if (has_radius) {
- if (len_v3(vec) > cmd->radius) continue;
- }
-
- for (j = 0; j < dvert[i].totweight; ++j) {
- if(dvert[i].dw[j].def_nr == defgrp_index) {
- dw = &dvert[i].dw[j];
- break;
- }
- }
- if (!dw) continue;
-
- fac = fac_orig * dw->weight;
- facm = 1.0f - fac;
-
- normalize_v3(vec);
-
- if (flag & MOD_CAST_X)
- tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
- if (flag & MOD_CAST_Y)
- tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
- if (flag & MOD_CAST_Z)
- tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
-
- if(ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(imat, tmp_co);
- } else {
- add_v3_v3v3(tmp_co, tmp_co, center);
- }
- }
-
- VECCOPY(vertexCos[i], tmp_co);
- }
- return;
- }
-
- /* no vgroup */
- for (i = 0; i < numVerts; i++) {
- float tmp_co[3];
-
- VECCOPY(tmp_co, vertexCos[i]);
- if(ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(mat, tmp_co);
- } else {
- sub_v3_v3v3(tmp_co, tmp_co, center);
- }
- }
-
- VECCOPY(vec, tmp_co);
-
- if (type == MOD_CAST_TYPE_CYLINDER)
- vec[2] = 0.0f;
-
- if (has_radius) {
- if (len_v3(vec) > cmd->radius) continue;
- }
-
- normalize_v3(vec);
-
- if (flag & MOD_CAST_X)
- tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
- if (flag & MOD_CAST_Y)
- tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
- if (flag & MOD_CAST_Z)
- tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
-
- if(ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(imat, tmp_co);
- } else {
- add_v3_v3v3(tmp_co, tmp_co, center);
- }
- }
-
- VECCOPY(vertexCos[i], tmp_co);
- }
-}
-
-static void castModifier_cuboid_do(
- CastModifierData *cmd, Object *ob, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts)
-{
- MDeformVert *dvert = NULL;
- Object *ctrl_ob = NULL;
-
- int i, defgrp_index;
- int has_radius = 0;
- short flag;
- float fac, facm;
- float min[3], max[3], bb[8][3];
- float center[3] = {0.0f, 0.0f, 0.0f};
- float mat[4][4], imat[4][4];
-
- fac = cmd->fac;
- facm = 1.0f - fac;
-
- flag = cmd->flag;
-
- ctrl_ob = cmd->object;
-
- /* now we check which options the user wants */
-
- /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
- /* 2) cmd->radius > 0.0f: only the vertices within this radius from
- * the center of the effect should be deformed */
- if (cmd->radius > FLT_EPSILON) has_radius = 1;
-
- /* 3) if we were given a vertex group name,
- * only those vertices should be affected */
- defgrp_index = defgroup_name_index(ob, cmd->defgrp_name);
-
- if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- if (ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
- mul_m4_m4m4(mat, ob->obmat, ctrl_ob->imat);
- invert_m4_m4(imat, mat);
- }
-
- invert_m4_m4(ob->imat, ob->obmat);
- VECCOPY(center, ctrl_ob->obmat[3]);
- mul_m4_v3(ob->imat, center);
- }
-
- if((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
- for(i = 0; i < 3; i++) {
- min[i] = -cmd->radius;
- max[i] = cmd->radius;
- }
- } else if(!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
- for(i = 0; i < 3; i++) {
- min[i] = -cmd->size;
- max[i] = cmd->size;
- }
- } else {
- /* get bound box */
- /* We can't use the object's bound box because other modifiers
- * may have changed the vertex data. */
- INIT_MINMAX(min, max);
-
- /* Cast's center is the ob's own center in its local space,
- * by default, but if the user defined a control object, we use
- * its location, transformed to ob's local space. */
- if (ctrl_ob) {
- float vec[3];
-
- /* let the center of the ctrl_ob be part of the bound box: */
- DO_MINMAX(center, min, max);
-
- for (i = 0; i < numVerts; i++) {
- sub_v3_v3v3(vec, vertexCos[i], center);
- DO_MINMAX(vec, min, max);
- }
- }
- else {
- for (i = 0; i < numVerts; i++) {
- DO_MINMAX(vertexCos[i], min, max);
- }
- }
-
- /* we want a symmetric bound box around the origin */
- if (fabs(min[0]) > fabs(max[0])) max[0] = fabs(min[0]);
- if (fabs(min[1]) > fabs(max[1])) max[1] = fabs(min[1]);
- if (fabs(min[2]) > fabs(max[2])) max[2] = fabs(min[2]);
- min[0] = -max[0];
- min[1] = -max[1];
- min[2] = -max[2];
- }
-
- /* building our custom bounding box */
- bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
- bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
- bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
- bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
- bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
- bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
-
- /* ready to apply the effect, one vertex at a time;
- * tiny optimization: the code is separated (with parts repeated)
- * in two possible cases:
- * with or w/o a vgroup. With lots of if's in the code below,
- * further optimizations are possible, if needed */
- if (dvert) { /* with a vgroup */
- float fac_orig = fac;
- for (i = 0; i < numVerts; i++) {
- MDeformWeight *dw = NULL;
- int j, octant, coord;
- float d[3], dmax, apex[3], fbb;
- float tmp_co[3];
-
- VECCOPY(tmp_co, vertexCos[i]);
- if(ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(mat, tmp_co);
- } else {
- sub_v3_v3v3(tmp_co, tmp_co, center);
- }
- }
-
- if (has_radius) {
- if (fabs(tmp_co[0]) > cmd->radius ||
- fabs(tmp_co[1]) > cmd->radius ||
- fabs(tmp_co[2]) > cmd->radius) continue;
- }
-
- for (j = 0; j < dvert[i].totweight; ++j) {
- if(dvert[i].dw[j].def_nr == defgrp_index) {
- dw = &dvert[i].dw[j];
- break;
- }
- }
- if (!dw) continue;
-
- fac = fac_orig * dw->weight;
- facm = 1.0f - fac;
-
- /* The algo used to project the vertices to their
- * bounding box (bb) is pretty simple:
- * for each vertex v:
- * 1) find in which octant v is in;
- * 2) find which outer "wall" of that octant is closer to v;
- * 3) calculate factor (var fbb) to project v to that wall;
- * 4) project. */
-
- /* find in which octant this vertex is in */
- octant = 0;
- if (tmp_co[0] > 0.0f) octant += 1;
- if (tmp_co[1] > 0.0f) octant += 2;
- if (tmp_co[2] > 0.0f) octant += 4;
-
- /* apex is the bb's vertex at the chosen octant */
- copy_v3_v3(apex, bb[octant]);
-
- /* find which bb plane is closest to this vertex ... */
- d[0] = tmp_co[0] / apex[0];
- d[1] = tmp_co[1] / apex[1];
- d[2] = tmp_co[2] / apex[2];
-
- /* ... (the closest has the higher (closer to 1) d value) */
- dmax = d[0];
- coord = 0;
- if (d[1] > dmax) {
- dmax = d[1];
- coord = 1;
- }
- if (d[2] > dmax) {
- /* dmax = d[2]; */ /* commented, we don't need it */
- coord = 2;
- }
-
- /* ok, now we know which coordinate of the vertex to use */
-
- if (fabs(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
- continue;
-
- /* finally, this is the factor we wanted, to project the vertex
- * to its bounding box (bb) */
- fbb = apex[coord] / tmp_co[coord];
-
- /* calculate the new vertex position */
- if (flag & MOD_CAST_X)
- tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
- if (flag & MOD_CAST_Y)
- tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
- if (flag & MOD_CAST_Z)
- tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
-
- if(ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(imat, tmp_co);
- } else {
- add_v3_v3v3(tmp_co, tmp_co, center);
- }
- }
-
- VECCOPY(vertexCos[i], tmp_co);
- }
- return;
- }
-
- /* no vgroup (check previous case for comments about the code) */
- for (i = 0; i < numVerts; i++) {
- int octant, coord;
- float d[3], dmax, fbb, apex[3];
- float tmp_co[3];
-
- VECCOPY(tmp_co, vertexCos[i]);
- if(ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(mat, tmp_co);
- } else {
- sub_v3_v3v3(tmp_co, tmp_co, center);
- }
- }
-
- if (has_radius) {
- if (fabs(tmp_co[0]) > cmd->radius ||
- fabs(tmp_co[1]) > cmd->radius ||
- fabs(tmp_co[2]) > cmd->radius) continue;
- }
-
- octant = 0;
- if (tmp_co[0] > 0.0f) octant += 1;
- if (tmp_co[1] > 0.0f) octant += 2;
- if (tmp_co[2] > 0.0f) octant += 4;
-
- copy_v3_v3(apex, bb[octant]);
-
- d[0] = tmp_co[0] / apex[0];
- d[1] = tmp_co[1] / apex[1];
- d[2] = tmp_co[2] / apex[2];
-
- dmax = d[0];
- coord = 0;
- if (d[1] > dmax) {
- dmax = d[1];
- coord = 1;
- }
- if (d[2] > dmax) {
- /* dmax = d[2]; */ /* commented, we don't need it */
- coord = 2;
- }
-
- if (fabs(tmp_co[coord]) < FLT_EPSILON)
- continue;
-
- fbb = apex[coord] / tmp_co[coord];
-
- if (flag & MOD_CAST_X)
- tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
- if (flag & MOD_CAST_Y)
- tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
- if (flag & MOD_CAST_Z)
- tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
-
- if(ctrl_ob) {
- if(flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(imat, tmp_co);
- } else {
- add_v3_v3v3(tmp_co, tmp_co, center);
- }
- }
-
- VECCOPY(vertexCos[i], tmp_co);
- }
-}
-
-static void castModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm = NULL;
- CastModifierData *cmd = (CastModifierData *)md;
-
- dm = get_dm(md->scene, ob, NULL, derivedData, NULL, 0);
-
- if (cmd->type == MOD_CAST_TYPE_CUBOID) {
- castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
- } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
- castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
- }
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static void castModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm = get_dm(md->scene, ob, editData, derivedData, NULL, 0);
- CastModifierData *cmd = (CastModifierData *)md;
-
- if (cmd->type == MOD_CAST_TYPE_CUBOID) {
- castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
- } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
- castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
- }
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-/* Wave */
-
-static void waveModifier_initData(ModifierData *md)
-{
- WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
-
- wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
- | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
-
- wmd->objectcenter = NULL;
- wmd->texture = NULL;
- wmd->map_object = NULL;
- wmd->height= 0.5f;
- wmd->width= 1.5f;
- wmd->speed= 0.25f;
- wmd->narrow= 1.5f;
- wmd->lifetime= 0.0f;
- wmd->damp= 10.0f;
- wmd->falloff= 0.0f;
- wmd->texmapping = MOD_WAV_MAP_LOCAL;
- wmd->defgrp_name[0] = 0;
-}
-
-static void waveModifier_copyData(ModifierData *md, ModifierData *target)
-{
- WaveModifierData *wmd = (WaveModifierData*) md;
- WaveModifierData *twmd = (WaveModifierData*) target;
-
- twmd->damp = wmd->damp;
- twmd->flag = wmd->flag;
- twmd->height = wmd->height;
- twmd->lifetime = wmd->lifetime;
- twmd->narrow = wmd->narrow;
- twmd->speed = wmd->speed;
- twmd->startx = wmd->startx;
- twmd->starty = wmd->starty;
- twmd->timeoffs = wmd->timeoffs;
- twmd->width = wmd->width;
- twmd->falloff = wmd->falloff;
- twmd->objectcenter = wmd->objectcenter;
- twmd->texture = wmd->texture;
- twmd->map_object = wmd->map_object;
- twmd->texmapping = wmd->texmapping;
- strncpy(twmd->defgrp_name, wmd->defgrp_name, 32);
-}
-
-static int waveModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-
-static void waveModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- ObjectWalkFunc walk, void *userData)
-{
- WaveModifierData *wmd = (WaveModifierData*) md;
-
- walk(userData, ob, &wmd->objectcenter);
- walk(userData, ob, &wmd->map_object);
-}
-
-static void waveModifier_foreachIDLink(ModifierData *md, Object *ob,
- IDWalkFunc walk, void *userData)
-{
- WaveModifierData *wmd = (WaveModifierData*) md;
-
- walk(userData, ob, (ID **)&wmd->texture);
-
- waveModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
-}
-
-static void waveModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
- DagNode *obNode)
-{
- WaveModifierData *wmd = (WaveModifierData*) md;
-
- if(wmd->objectcenter) {
- DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Wave Modifier");
- }
-
- if(wmd->map_object) {
- DagNode *curNode = dag_get_node(forest, wmd->map_object);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Wave Modifer");
- }
-}
-
-static CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- WaveModifierData *wmd = (WaveModifierData *)md;
- CustomDataMask dataMask = 0;
-
-
- /* ask for UV coordinates if we need them */
- if(wmd->texture && wmd->texmapping == MOD_WAV_MAP_UV)
- dataMask |= (1 << CD_MTFACE);
-
- /* ask for vertexgroups if we need them */
- if(wmd->defgrp_name[0])
- dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
- DerivedMesh *dm,
- float (*co)[3], float (*texco)[3],
- int numVerts)
-{
- int i;
- int texmapping = wmd->texmapping;
-
- if(texmapping == MOD_WAV_MAP_OBJECT) {
- if(wmd->map_object)
- invert_m4_m4(wmd->map_object->imat, wmd->map_object->obmat);
- else /* if there is no map object, default to local */
- texmapping = MOD_WAV_MAP_LOCAL;
- }
-
- /* UVs need special handling, since they come from faces */
- if(texmapping == MOD_WAV_MAP_UV) {
- if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
- MFace *mface = dm->getFaceArray(dm);
- MFace *mf;
- char *done = MEM_callocN(sizeof(*done) * numVerts,
- "get_texture_coords done");
- int numFaces = dm->getNumFaces(dm);
- char uvname[32];
- MTFace *tf;
-
- validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name, uvname);
- tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
-
- /* verts are given the UV from the first face that uses them */
- for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
- if(!done[mf->v1]) {
- texco[mf->v1][0] = tf->uv[0][0];
- texco[mf->v1][1] = tf->uv[0][1];
- texco[mf->v1][2] = 0;
- done[mf->v1] = 1;
- }
- if(!done[mf->v2]) {
- texco[mf->v2][0] = tf->uv[1][0];
- texco[mf->v2][1] = tf->uv[1][1];
- texco[mf->v2][2] = 0;
- done[mf->v2] = 1;
- }
- if(!done[mf->v3]) {
- texco[mf->v3][0] = tf->uv[2][0];
- texco[mf->v3][1] = tf->uv[2][1];
- texco[mf->v3][2] = 0;
- done[mf->v3] = 1;
- }
- if(!done[mf->v4]) {
- texco[mf->v4][0] = tf->uv[3][0];
- texco[mf->v4][1] = tf->uv[3][1];
- texco[mf->v4][2] = 0;
- done[mf->v4] = 1;
- }
- }
-
- /* remap UVs from [0, 1] to [-1, 1] */
- for(i = 0; i < numVerts; ++i) {
- texco[i][0] = texco[i][0] * 2 - 1;
- texco[i][1] = texco[i][1] * 2 - 1;
- }
-
- MEM_freeN(done);
- return;
- } else /* if there are no UVs, default to local */
- texmapping = MOD_WAV_MAP_LOCAL;
- }
-
- for(i = 0; i < numVerts; ++i, ++co, ++texco) {
- switch(texmapping) {
- case MOD_WAV_MAP_LOCAL:
- VECCOPY(*texco, *co);
- break;
- case MOD_WAV_MAP_GLOBAL:
- VECCOPY(*texco, *co);
- mul_m4_v3(ob->obmat, *texco);
- break;
- case MOD_WAV_MAP_OBJECT:
- VECCOPY(*texco, *co);
- mul_m4_v3(ob->obmat, *texco);
- mul_m4_v3(wmd->map_object->imat, *texco);
- break;
- }
- }
-}
-
-static void waveModifier_do(WaveModifierData *md,
- Scene *scene, Object *ob, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts)
-{
- WaveModifierData *wmd = (WaveModifierData*) md;
- MVert *mvert = NULL;
- MDeformVert *dvert = NULL;
- int defgrp_index;
- float ctime = bsystem_time(scene, ob, (float)scene->r.cfra, 0.0);
- float minfac =
- (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
- float lifefac = wmd->height;
- float (*tex_co)[3] = NULL;
-
- if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH)
- mvert = dm->getVertArray(dm);
-
- if(wmd->objectcenter){
- float mat[4][4];
- /* get the control object's location in local coordinates */
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_m4m4(mat, wmd->objectcenter->obmat, ob->imat);
-
- wmd->startx = mat[3][0];
- wmd->starty = mat[3][1];
- }
-
- /* get the index of the deform group */
- defgrp_index = defgroup_name_index(ob, wmd->defgrp_name);
-
- if(defgrp_index >= 0){
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
- }
-
- if(wmd->damp == 0) wmd->damp = 10.0f;
-
- if(wmd->lifetime != 0.0) {
- float x = ctime - wmd->timeoffs;
-
- if(x > wmd->lifetime) {
- lifefac = x - wmd->lifetime;
-
- if(lifefac > wmd->damp) lifefac = 0.0;
- else lifefac =
- (float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp)));
- }
- }
-
- if(wmd->texture) {
- tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
- "waveModifier_do tex_co");
- wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts);
- }
-
- if(lifefac != 0.0) {
- int i;
-
- for(i = 0; i < numVerts; i++) {
- float *co = vertexCos[i];
- float x = co[0] - wmd->startx;
- float y = co[1] - wmd->starty;
- float amplit= 0.0f;
- float dist = 0.0f;
- float falloff_fac = 0.0f;
- TexResult texres;
- MDeformWeight *def_weight = NULL;
-
- /* get weights */
- if(dvert) {
- int j;
- for(j = 0; j < dvert[i].totweight; ++j) {
- if(dvert[i].dw[j].def_nr == defgrp_index) {
- def_weight = &dvert[i].dw[j];
- break;
- }
- }
-
- /* if this vert isn't in the vgroup, don't deform it */
- if(!def_weight) continue;
- }
-
- if(wmd->texture) {
- texres.nor = NULL;
- get_texture_value(wmd->texture, tex_co[i], &texres);
- }
-
- /*get dist*/
- if(wmd->flag & MOD_WAVE_X) {
- if(wmd->flag & MOD_WAVE_Y){
- dist = (float)sqrt(x*x + y*y);
- }
- else{
- dist = fabs(x);
- }
- }
- else if(wmd->flag & MOD_WAVE_Y) {
- dist = fabs(y);
- }
-
- falloff_fac = (1.0-(dist / wmd->falloff));
- CLAMP(falloff_fac,0,1);
-
- if(wmd->flag & MOD_WAVE_X) {
- if(wmd->flag & MOD_WAVE_Y) amplit = (float)sqrt(x*x + y*y);
- else amplit = x;
- }
- else if(wmd->flag & MOD_WAVE_Y)
- amplit= y;
-
- /* this way it makes nice circles */
- amplit -= (ctime - wmd->timeoffs) * wmd->speed;
-
- if(wmd->flag & MOD_WAVE_CYCL) {
- amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width)
- + wmd->width;
- }
-
- /* GAUSSIAN */
- if(amplit > -wmd->width && amplit < wmd->width) {
- amplit = amplit * wmd->narrow;
- amplit = (float)(1.0 / exp(amplit * amplit) - minfac);
-
- /*apply texture*/
- if(wmd->texture)
- amplit = amplit * texres.tin;
-
- /*apply weight*/
- if(def_weight)
- amplit = amplit * def_weight->weight;
-
- /*apply falloff*/
- if (wmd->falloff > 0)
- amplit = amplit * falloff_fac;
-
- if(mvert) {
- /* move along normals */
- if(wmd->flag & MOD_WAVE_NORM_X) {
- co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
- }
- if(wmd->flag & MOD_WAVE_NORM_Y) {
- co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
- }
- if(wmd->flag & MOD_WAVE_NORM_Z) {
- co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
- }
- }
- else {
- /* move along local z axis */
- co[2] += lifefac * amplit;
- }
- }
- }
- }
-
- if(wmd->texture) MEM_freeN(tex_co);
-}
-
-static void waveModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm= derivedData;
- WaveModifierData *wmd = (WaveModifierData *)md;
-
- if(wmd->flag & MOD_WAVE_NORM)
- dm= get_cddm(md->scene, ob, NULL, dm, vertexCos);
- else if(wmd->texture || wmd->defgrp_name[0])
- dm= get_dm(md->scene, ob, NULL, dm, NULL, 0);
-
- waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static void waveModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm= derivedData;
- WaveModifierData *wmd = (WaveModifierData *)md;
-
- if(wmd->flag & MOD_WAVE_NORM)
- dm= get_cddm(md->scene, ob, editData, dm, vertexCos);
- else if(wmd->texture || wmd->defgrp_name[0])
- dm= get_dm(md->scene, ob, editData, dm, NULL, 0);
-
- waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-/* Armature */
-
-static void armatureModifier_initData(ModifierData *md)
-{
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
- amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP;
-}
-
-static void armatureModifier_copyData(ModifierData *md, ModifierData *target)
-{
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
- ArmatureModifierData *tamd = (ArmatureModifierData*) target;
-
- tamd->object = amd->object;
- tamd->deformflag = amd->deformflag;
- strncpy(tamd->defgrp_name, amd->defgrp_name, 32);
-}
-
-static CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups */
- dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static int armatureModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
- return !amd->object;
-}
-
-static void armatureModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
- walk(userData, ob, &amd->object);
-}
-
-static void armatureModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
- DagNode *obNode)
-{
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
- if (amd->object) {
- DagNode *curNode = dag_get_node(forest, amd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Armature Modifier");
- }
-}
-
-static void armatureModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
- modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
-
- armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL,
- numVerts, amd->deformflag,
- (float(*)[3])amd->prevCos, amd->defgrp_name);
- /* free cache */
- if(amd->prevCos) {
- MEM_freeN(amd->prevCos);
- amd->prevCos= NULL;
- }
-}
-
-static void armatureModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
- DerivedMesh *dm = derivedData;
-
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
- armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts,
- amd->deformflag, NULL, amd->defgrp_name);
-
- if(!derivedData) dm->release(dm);
-}
-
-static void armatureModifier_deformMatricesEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3],
- float (*defMats)[3][3], int numVerts)
-{
- ArmatureModifierData *amd = (ArmatureModifierData*) md;
- DerivedMesh *dm = derivedData;
-
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
- armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts,
- amd->deformflag, NULL, amd->defgrp_name);
-
- if(!derivedData) dm->release(dm);
-}
-
-/* Hook */
-
-static void hookModifier_initData(ModifierData *md)
-{
- HookModifierData *hmd = (HookModifierData*) md;
-
- hmd->force= 1.0;
-}
-
-static void hookModifier_copyData(ModifierData *md, ModifierData *target)
-{
- HookModifierData *hmd = (HookModifierData*) md;
- HookModifierData *thmd = (HookModifierData*) target;
-
- VECCOPY(thmd->cent, hmd->cent);
- thmd->falloff = hmd->falloff;
- thmd->force = hmd->force;
- thmd->object = hmd->object;
- thmd->totindex = hmd->totindex;
- thmd->indexar = MEM_dupallocN(hmd->indexar);
- memcpy(thmd->parentinv, hmd->parentinv, sizeof(hmd->parentinv));
- strncpy(thmd->name, hmd->name, 32);
- strncpy(thmd->subtarget, hmd->subtarget, 32);
-}
-
-static CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- HookModifierData *hmd = (HookModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(!hmd->indexar && hmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static void hookModifier_freeData(ModifierData *md)
-{
- HookModifierData *hmd = (HookModifierData*) md;
-
- if (hmd->indexar) MEM_freeN(hmd->indexar);
-}
-
-static int hookModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- HookModifierData *hmd = (HookModifierData*) md;
-
- return !hmd->object;
-}
-
-static void hookModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- HookModifierData *hmd = (HookModifierData*) md;
-
- walk(userData, ob, &hmd->object);
-}
-
-static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
- Object *ob, DagNode *obNode)
-{
- HookModifierData *hmd = (HookModifierData*) md;
-
- if (hmd->object) {
- DagNode *curNode = dag_get_node(forest, hmd->object);
-
- if (hmd->subtarget[0])
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA|DAG_RL_DATA_DATA, "Hook Modifier");
- else
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "Hook Modifier");
- }
-}
-
-static void hookModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- HookModifierData *hmd = (HookModifierData*) md;
- bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget);
- float vec[3], mat[4][4], dmat[4][4];
- int i;
- DerivedMesh *dm = derivedData;
-
- /* get world-space matrix of target, corrected for the space the verts are in */
- if (hmd->subtarget[0] && pchan) {
- /* bone target if there's a matching pose-channel */
- mul_m4_m4m4(dmat, pchan->pose_mat, hmd->object->obmat);
- }
- else {
- /* just object target */
- copy_m4_m4(dmat, hmd->object->obmat);
- }
- invert_m4_m4(ob->imat, ob->obmat);
- mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv,
- NULL, NULL, NULL, NULL, NULL);
-
- /* vertex indices? */
- if(hmd->indexar) {
- for(i = 0; i < hmd->totindex; i++) {
- int index = hmd->indexar[i];
-
- /* This should always be true and I don't generally like
- * "paranoid" style code like this, but old files can have
- * indices that are out of range because old blender did
- * not correct them on exit editmode. - zr
- */
- if(index < numVerts) {
- float *co = vertexCos[index];
- float fac = hmd->force;
-
- /* if DerivedMesh is present and has original index data,
- * use it
- */
- if(dm && dm->getVertDataArray(dm, CD_ORIGINDEX)) {
- int j;
- int orig_index;
- for(j = 0; j < numVerts; ++j) {
- fac = hmd->force;
- orig_index = *(int *)dm->getVertData(dm, j,
- CD_ORIGINDEX);
- if(orig_index == index) {
- co = vertexCos[j];
- if(hmd->falloff != 0.0) {
- float len = len_v3v3(co, hmd->cent);
- if(len > hmd->falloff) fac = 0.0;
- else if(len > 0.0)
- fac *= sqrt(1.0 - len / hmd->falloff);
- }
-
- if(fac != 0.0) {
- mul_v3_m4v3(vec, mat, co);
- interp_v3_v3v3(co, co, vec, fac);
- }
- }
- }
- } else {
- if(hmd->falloff != 0.0) {
- float len = len_v3v3(co, hmd->cent);
- if(len > hmd->falloff) fac = 0.0;
- else if(len > 0.0)
- fac *= sqrt(1.0 - len / hmd->falloff);
- }
-
- if(fac != 0.0) {
- mul_v3_m4v3(vec, mat, co);
- interp_v3_v3v3(co, co, vec, fac);
- }
- }
- }
- }
- }
- else if(hmd->name[0]) { /* vertex group hook */
- Mesh *me = ob->data;
- int use_dverts = 0;
- int maxVerts = 0;
- int defgrp_index = defgroup_name_index(ob, hmd->name);
-
- if(dm) {
- if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) {
- maxVerts = dm->getNumVerts(dm);
- use_dverts = 1;
- }
- }
- else if(me->dvert) {
- maxVerts = me->totvert;
- use_dverts = 1;
- }
-
- if(defgrp_index >= 0 && use_dverts) {
- MDeformVert *dvert = me->dvert;
- int i, j;
-
- for(i = 0; i < maxVerts; i++, dvert++) {
- if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT);
- for(j = 0; j < dvert->totweight; j++) {
- if(dvert->dw[j].def_nr == defgrp_index) {
- float fac = hmd->force*dvert->dw[j].weight;
- float *co = vertexCos[i];
-
- if(hmd->falloff != 0.0) {
- float len = len_v3v3(co, hmd->cent);
- if(len > hmd->falloff) fac = 0.0;
- else if(len > 0.0)
- fac *= sqrt(1.0 - len / hmd->falloff);
- }
-
- mul_v3_m4v3(vec, mat, co);
- interp_v3_v3v3(co, co, vec, fac);
- }
- }
- }
- }
- }
-}
-
-static void hookModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm = derivedData;
-
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
- hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
-
- if(!derivedData) dm->release(dm);
-}
-
-/* Softbody */
-
-static void softbodyModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- sbObjectStep(md->scene, ob, (float)md->scene->r.cfra, vertexCos, numVerts);
-}
-
-static int softbodyModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-
-/* Solidify */
-
-
-typedef struct EdgeFaceRef {
- int f1; /* init as -1 */
- int f2;
-} EdgeFaceRef;
-
-static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
-{
- int i, numVerts, numEdges, numFaces;
- MFace *mface, *mf;
- MVert *mvert, *mv;
-
- float (*face_nors)[3];
- float *f_no;
- int calc_face_nors= 0;
-
- numVerts = dm->getNumVerts(dm);
- numEdges = dm->getNumEdges(dm);
- numFaces = dm->getNumFaces(dm);
- mface = dm->getFaceArray(dm);
- mvert = dm->getVertArray(dm);
-
- /* we don't want to overwrite any referenced layers */
-
- /*
- Dosnt work here!
- mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
- cddm->mvert = mv;
- */
-
- face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
- if(!face_nors) {
- calc_face_nors = 1;
- face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, numFaces);
- }
-
- mv = mvert;
- mf = mface;
-
- {
- EdgeHash *edge_hash = BLI_edgehash_new();
- EdgeHashIterator *edge_iter;
- int edge_ref_count = 0;
- int ed_v1, ed_v2; /* use when getting the key */
- EdgeFaceRef *edge_ref_array = MEM_callocN(numEdges * sizeof(EdgeFaceRef), "Edge Connectivity");
- EdgeFaceRef *edge_ref;
- float edge_normal[3];
-
- /* This function adds an edge hash if its not there, and adds the face index */
-#define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \
- edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \
- if (!edge_ref) { \
- edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \
- edge_ref->f1=i; \
- edge_ref->f2=-1; \
- BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \
- } else { \
- edge_ref->f2=i; \
- }
-
- for(i = 0; i < numFaces; i++, mf++) {
- f_no = face_nors[i];
-
- if(mf->v4) {
- if(calc_face_nors)
- normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
-
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v4);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v4, mf->v1);
- } else {
- if(calc_face_nors)
- normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
-
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v1);
- }
- }
-
- for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) {
- /* Get the edge vert indicies, and edge value (the face indicies that use it)*/
- BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2);
- edge_ref = BLI_edgehashIterator_getValue(edge_iter);
-
- if (edge_ref->f2 != -1) {
- /* We have 2 faces using this edge, calculate the edges normal
- * using the angle between the 2 faces as a weighting */
- add_v3_v3v3(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]);
- normalize_v3(edge_normal);
- mul_v3_fl(edge_normal, angle_normalized_v3v3(face_nors[edge_ref->f1], face_nors[edge_ref->f2]));
- } else {
- /* only one face attached to that edge */
- /* an edge without another attached- the weight on this is
- * undefined, M_PI/2 is 90d in radians and that seems good enough */
- VECCOPY(edge_normal, face_nors[edge_ref->f1])
- mul_v3_fl(edge_normal, M_PI/2);
- }
- add_v3_v3(temp_nors[ed_v1], edge_normal);
- add_v3_v3(temp_nors[ed_v2], edge_normal);
- }
- BLI_edgehashIterator_free(edge_iter);
- BLI_edgehash_free(edge_hash, NULL);
- MEM_freeN(edge_ref_array);
- }
-
- /* normalize vertex normals and assign */
- for(i = 0; i < numVerts; i++, mv++) {
- if(normalize_v3(temp_nors[i]) == 0.0f) {
- normal_short_to_float_v3(temp_nors[i], mv->no);
- }
- }
-}
-
-static void solidifyModifier_initData(ModifierData *md)
-{
- SolidifyModifierData *smd = (SolidifyModifierData*) md;
- smd->offset = 0.01f;
- smd->flag = MOD_SOLIDIFY_RIM;
-}
-
-static void solidifyModifier_copyData(ModifierData *md, ModifierData *target)
-{
- SolidifyModifierData *smd = (SolidifyModifierData*) md;
- SolidifyModifierData *tsmd = (SolidifyModifierData*) target;
- tsmd->offset = smd->offset;
- tsmd->offset_fac = smd->offset_fac;
- tsmd->crease_inner = smd->crease_inner;
- tsmd->crease_outer = smd->crease_outer;
- tsmd->crease_rim = smd->crease_rim;
- tsmd->flag = smd->flag;
- strcpy(tsmd->defgrp_name, smd->defgrp_name);
-}
-
-static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md,
- Object *ob,
- DerivedMesh *dm,
- int useRenderParams,
- int isFinalCalc)
-{
- int i;
- DerivedMesh *result;
- SolidifyModifierData *smd = (SolidifyModifierData*) md;
-
- MFace *mf, *mface, *orig_mface;
- MEdge *ed, *medge, *orig_medge;
- MVert *mv, *mvert, *orig_mvert;
-
- int numVerts = dm->getNumVerts(dm);
- int numEdges = dm->getNumEdges(dm);
- int numFaces = dm->getNumFaces(dm);
-
- /* use for edges */
- int *new_vert_arr= NULL;
- int newFaces = 0;
-
- int *new_edge_arr= NULL;
- int newEdges = 0;
-
- int *edge_users= NULL;
- char *edge_order= NULL;
-
- float (*vert_nors)[3]= NULL;
-
- float ofs_orig= - (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset);
- float ofs_new= smd->offset - (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset);
-
- /* weights */
- MDeformVert *dvert= NULL, *dv= NULL;
- int defgrp_index= -1;
- int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0);
-
- defgrp_index= defgroup_name_index(ob, smd->defgrp_name);
-
- if (defgrp_index >= 0)
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- orig_mface = dm->getFaceArray(dm);
- orig_medge = dm->getEdgeArray(dm);
- orig_mvert = dm->getVertArray(dm);
-
- if(smd->flag & MOD_SOLIDIFY_RIM) {
- EdgeHash *edgehash = BLI_edgehash_new();
- EdgeHashIterator *ehi;
- int v1, v2;
- int eidx;
-
- for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) {
- mv->flag &= ~ME_VERT_TMP_TAG;
- }
-
- for(i=0, ed=orig_medge; i<numEdges; i++, ed++) {
- BLI_edgehash_insert(edgehash, ed->v1, ed->v2, SET_INT_IN_POINTER(i));
- }
-
-#define INVALID_UNUSED -1
-#define INVALID_PAIR -2
-
-#define ADD_EDGE_USER(_v1, _v2, edge_ord) \
- eidx= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, _v1, _v2)); \
- if(edge_users[eidx] == INVALID_UNUSED) { \
- ed= orig_medge + eidx; \
- edge_users[eidx]= (_v1 < _v2) == (ed->v1 < ed->v2) ? i:(i+numFaces); \
- edge_order[eidx]= edge_ord; \
- } else { \
- edge_users[eidx]= INVALID_PAIR; \
- } \
-
-
- edge_users= MEM_mallocN(sizeof(int) * numEdges, "solid_mod edges");
- edge_order= MEM_mallocN(sizeof(char) * numEdges, "solid_mod eorder");
- memset(edge_users, INVALID_UNUSED, sizeof(int) * numEdges);
-
- for(i=0, mf=orig_mface; i<numFaces; i++, mf++) {
- if(mf->v4) {
- ADD_EDGE_USER(mf->v1, mf->v2, 0);
- ADD_EDGE_USER(mf->v2, mf->v3, 1);
- ADD_EDGE_USER(mf->v3, mf->v4, 2);
- ADD_EDGE_USER(mf->v4, mf->v1, 3);
- }
- else {
- ADD_EDGE_USER(mf->v1, mf->v2, 0);
- ADD_EDGE_USER(mf->v2, mf->v3, 1);
- ADD_EDGE_USER(mf->v3, mf->v1, 2);
- }
- }
-
-#undef ADD_EDGE_USER
-#undef INVALID_UNUSED
-#undef INVALID_PAIR
-
-
- new_edge_arr= MEM_callocN(sizeof(int) * numEdges, "solid_mod arr");
-
- ehi= BLI_edgehashIterator_new(edgehash);
- for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- int eidx= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
- if(edge_users[eidx] >= 0) {
- BLI_edgehashIterator_getKey(ehi, &v1, &v2);
- orig_mvert[v1].flag |= ME_VERT_TMP_TAG;
- orig_mvert[v2].flag |= ME_VERT_TMP_TAG;
- new_edge_arr[newFaces]= eidx;
- newFaces++;
- }
- }
- BLI_edgehashIterator_free(ehi);
-
-
-
- new_vert_arr= MEM_callocN(sizeof(int) * numVerts, "solid_mod new_varr");
- for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) {
- if(mv->flag & ME_VERT_TMP_TAG) {
- new_vert_arr[newEdges] = i;
- newEdges++;
-
- mv->flag &= ~ME_VERT_TMP_TAG;
- }
- }
-
- BLI_edgehash_free(edgehash, NULL);
- }
-
- if(smd->flag & MOD_SOLIDIFY_NORMAL_CALC) {
- vert_nors= MEM_callocN(sizeof(float) * numVerts * 3, "mod_solid_vno_hq");
- dm_calc_normal(dm, vert_nors);
- }
-
- result = CDDM_from_template(dm, numVerts * 2, (numEdges * 2) + newEdges, (numFaces * 2) + newFaces);
-
- mface = result->getFaceArray(result);
- medge = result->getEdgeArray(result);
- mvert = result->getVertArray(result);
-
- DM_copy_face_data(dm, result, 0, 0, numFaces);
- DM_copy_face_data(dm, result, 0, numFaces, numFaces);
-
- DM_copy_edge_data(dm, result, 0, 0, numEdges);
- DM_copy_edge_data(dm, result, 0, numEdges, numEdges);
-
- DM_copy_vert_data(dm, result, 0, 0, numVerts);
- DM_copy_vert_data(dm, result, 0, numVerts, numVerts);
-
- {
- static int corner_indices[4] = {2, 1, 0, 3};
- int is_quad;
-
- for(i=0, mf=mface+numFaces; i<numFaces; i++, mf++) {
- mf->v1 += numVerts;
- mf->v2 += numVerts;
- mf->v3 += numVerts;
- if(mf->v4)
- mf->v4 += numVerts;
-
- /* Flip face normal */
- {
- is_quad = mf->v4;
- SWAP(int, mf->v1, mf->v3);
- DM_swap_face_data(result, i+numFaces, corner_indices);
- test_index_face(mf, &result->faceData, numFaces, is_quad ? 4:3);
- }
- }
- }
-
- for(i=0, ed=medge+numEdges; i<numEdges; i++, ed++) {
- ed->v1 += numVerts;
- ed->v2 += numVerts;
- }
-
- /* note, copied vertex layers dont have flipped normals yet. do this after applying offset */
- if((smd->flag & MOD_SOLIDIFY_EVEN) == 0) {
- /* no even thickness, very simple */
- float scalar_short;
- float scalar_short_vgroup;
-
-
- if(ofs_new != 0.0f) {
- scalar_short= scalar_short_vgroup= ofs_new / 32767.0f;
- mv= mvert + ((ofs_new >= ofs_orig) ? 0 : numVerts);
- dv= dvert;
- for(i=0; i<numVerts; i++, mv++) {
- if(dv) {
- if(defgrp_invert) scalar_short_vgroup = scalar_short * (1.0f - defvert_find_weight(dv, defgrp_index));
- else scalar_short_vgroup = scalar_short * defvert_find_weight(dv, defgrp_index);
- dv++;
- }
- VECADDFAC(mv->co, mv->co, mv->no, scalar_short_vgroup);
- }
- }
-
- if(ofs_orig != 0.0f) {
- scalar_short= scalar_short_vgroup= ofs_orig / 32767.0f;
- mv= mvert + ((ofs_new >= ofs_orig) ? numVerts : 0); /* same as above but swapped, intentional use of 'ofs_new' */
- dv= dvert;
- for(i=0; i<numVerts; i++, mv++) {
- if(dv) {
- if(defgrp_invert) scalar_short_vgroup = scalar_short * (1.0f - defvert_find_weight(dv, defgrp_index));
- else scalar_short_vgroup = scalar_short * defvert_find_weight(dv, defgrp_index);
- dv++;
- }
- VECADDFAC(mv->co, mv->co, mv->no, scalar_short_vgroup);
- }
- }
-
- }
- else {
- /* make a face normal layer if not present */
- float (*face_nors)[3];
- int face_nors_calc= 0;
-
- /* same as EM_solidify() in editmesh_lib.c */
- float *vert_angles= MEM_callocN(sizeof(float) * numVerts * 2, "mod_solid_pair"); /* 2 in 1 */
- float *vert_accum= vert_angles + numVerts;
- float face_angles[4];
- int i, j, vidx;
-
- face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
- if(!face_nors) {
- face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, dm->numFaceData);
- face_nors_calc= 1;
- }
-
- if(vert_nors==NULL) {
- vert_nors= MEM_mallocN(sizeof(float) * numVerts * 3, "mod_solid_vno");
- for(i=0, mv=mvert; i<numVerts; i++, mv++) {
- normal_short_to_float_v3(vert_nors[i], mv->no);
- }
- }
-
- for(i=0, mf=mface; i<numFaces; i++, mf++) {
-
- /* just added, calc the normal */
- if(face_nors_calc) {
- if(mf->v4)
- normal_quad_v3(face_nors[i], mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
- else
- normal_tri_v3(face_nors[i] , mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
- }
-
- if(mf->v4) {
- angle_quad_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
- j= 3;
- }
- else {
- angle_tri_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
- j= 2;
- }
-
- for(; j>=0; j--) {
- vidx = *(&mf->v1 + j);
- vert_accum[vidx] += face_angles[j];
- vert_angles[vidx]+= shell_angle_to_dist(angle_normalized_v3v3(vert_nors[vidx], face_nors[i])) * face_angles[j];
- }
- }
-
- /* vertex group support */
- if(dvert) {
- dv= dvert;
- if(defgrp_invert) {
- for(i=0; i<numVerts; i++, dv++) {
- vert_angles[i] *= (1.0f - defvert_find_weight(dv, defgrp_index));
- }
- }
- else {
- for(i=0; i<numVerts; i++, dv++) {
- vert_angles[i] *= defvert_find_weight(dv, defgrp_index);
- }
- }
- }
-
- if(ofs_new) {
- mv= mvert + ((ofs_new >= ofs_orig) ? 0 : numVerts);
-
- for(i=0; i<numVerts; i++, mv++) {
- if(vert_accum[i]) { /* zero if unselected */
- madd_v3_v3fl(mv->co, vert_nors[i], ofs_new * (vert_angles[i] / vert_accum[i]));
- }
- }
- }
-
- if(ofs_orig) {
- mv= mvert + ((ofs_new >= ofs_orig) ? numVerts : 0); /* same as above but swapped, intentional use of 'ofs_new' */
-
- for(i=0; i<numVerts; i++, mv++) {
- if(vert_accum[i]) { /* zero if unselected */
- madd_v3_v3fl(mv->co, vert_nors[i], ofs_orig * (vert_angles[i] / vert_accum[i]));
- }
- }
- }
-
- MEM_freeN(vert_angles);
- }
-
- if(vert_nors)
- MEM_freeN(vert_nors);
-
- /* flip vertex normals for copied verts */
- mv= mvert + numVerts;
- for(i=0; i<numVerts; i++, mv++) {
- mv->no[0]= -mv->no[0];
- mv->no[1]= -mv->no[1];
- mv->no[2]= -mv->no[2];
- }
-
- if(smd->flag & MOD_SOLIDIFY_RIM) {
-
-
- /* bugger, need to re-calculate the normals for the new edge faces.
- * This could be done in many ways, but probably the quickest way is to calculate the average normals for side faces only.
- * Then blend them with the normals of the edge verts.
- *
- * at the moment its easiest to allocate an entire array for every vertex, even though we only need edge verts - campbell
- */
-
-#define SOLIDIFY_SIDE_NORMALS
-
-#ifdef SOLIDIFY_SIDE_NORMALS
- /* annoying to allocate these since we only need the edge verts, */
- float (*edge_vert_nos)[3]= MEM_callocN(sizeof(float) * numVerts * 3, "solidify_edge_nos");
- float nor[3];
-#endif
-
- const unsigned char crease_rim= smd->crease_rim * 255.0f;
- const unsigned char crease_outer= smd->crease_outer * 255.0f;
- const unsigned char crease_inner= smd->crease_inner * 255.0f;
-
- const int edge_indices[4][4] = {
- {1, 0, 0, 1},
- {2, 1, 1, 2},
- {3, 2, 2, 3},
- {0, 3, 3, 0}};
-
- /* add faces & edges */
- ed= medge + (numEdges * 2);
- for(i=0; i<newEdges; i++, ed++) {
- ed->v1= new_vert_arr[i];
- ed->v2= new_vert_arr[i] + numVerts;
- ed->flag |= ME_EDGEDRAW;
-
- if(crease_rim)
- ed->crease= crease_rim;
- }
-
- /* faces */
- mf= mface + (numFaces * 2);
- for(i=0; i<newFaces; i++, mf++) {
- int eidx= new_edge_arr[i];
- int fidx= edge_users[eidx];
- int flip;
-
- if(fidx >= numFaces) {
- fidx -= numFaces;
- flip= 1;
- }
- else {
- flip= 0;
- }
-
- ed= medge + eidx;
-
- /* copy most of the face settings */
- DM_copy_face_data(dm, result, fidx, (numFaces * 2) + i, 1);
-
- if(flip) {
- DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]);
-
- mf->v1= ed->v1;
- mf->v2= ed->v2;
- mf->v3= ed->v2 + numVerts;
- mf->v4= ed->v1 + numVerts;
- }
- else {
- DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]);
-
- mf->v1= ed->v2;
- mf->v2= ed->v1;
- mf->v3= ed->v1 + numVerts;
- mf->v4= ed->v2 + numVerts;
- }
-
- if(crease_outer)
- ed->crease= crease_outer;
-
- if(crease_inner) {
- medge[numEdges + eidx].crease= crease_inner;
- }
-
-#ifdef SOLIDIFY_SIDE_NORMALS
- normal_quad_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
-
- add_v3_v3(edge_vert_nos[ed->v1], nor);
- add_v3_v3(edge_vert_nos[ed->v2], nor);
-#endif
- }
-
-#ifdef SOLIDIFY_SIDE_NORMALS
- ed= medge + (numEdges * 2);
- for(i=0; i<newEdges; i++, ed++) {
- float nor_cpy[3];
- short *nor_short;
- int j;
-
- /* note, only the first vertex (lower half of the index) is calculated */
- normalize_v3_v3(nor_cpy, edge_vert_nos[ed->v1]);
-
- for(j=0; j<2; j++) { /* loop over both verts of the edge */
- nor_short= mvert[*(&ed->v1 + j)].no;
- normal_short_to_float_v3(nor, nor_short);
- add_v3_v3(nor, nor_cpy);
- normalize_v3(nor);
- normal_float_to_short_v3(nor_short, nor);
- }
- }
-
- MEM_freeN(edge_vert_nos);
-#endif
-
- MEM_freeN(new_vert_arr);
- MEM_freeN(new_edge_arr);
- MEM_freeN(edge_users);
- MEM_freeN(edge_order);
- }
-
- return result;
-}
-
-#undef SOLIDIFY_SIDE_NORMALS
-
-static DerivedMesh *solidifyModifier_applyModifierEM(ModifierData *md,
- Object *ob,
- EditMesh *editData,
- DerivedMesh *derivedData)
-{
- return solidifyModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Screw */
-
-/* Screw modifier: revolves the edges about an axis
-*/
-
-/* used for gathering edge connectivity */
-typedef struct ScrewVertConnect {
- float dist; /* distance from the center axis */
- float co[3]; /* loaction relative to the transformed axis */
- float no[3]; /* calc normal of the vertex */
- int v[2]; /* 2 verts on either side of this one */
- MEdge *e[2]; /* edges on either side, a bit of a waste since each edge ref's 2 edges */
- char flag;
-} ScrewVertConnect;
-
-typedef struct ScrewVertIter {
- ScrewVertConnect * v_array;
- ScrewVertConnect * v_poin;
- int v;
- int v_other;
- MEdge *e;
-} ScrewVertIter;
-
-#define ScrewVertIter_INIT(iter, array, v_init, dir)\
- iter.v_array = array;\
- iter.v = v_init;\
- if (v_init>=0) {\
- iter.v_poin = &array[v_init];\
- iter.v_other = iter.v_poin->v[dir];\
- if (dir)\
- iter.e = iter.v_poin->e[0];\
- else\
- iter.e = iter.v_poin->e[1];\
- } else {\
- iter.v_poin= NULL;\
- iter.e= NULL;\
- }
-
-
-#define ScrewVertIter_NEXT(iter)\
- if (iter.v_poin->v[0] == iter.v_other) {\
- iter.v_other= iter.v;\
- iter.v= iter.v_poin->v[1];\
- } else if (iter.v_poin->v[1] == iter.v_other) {\
- iter.v_other= iter.v;\
- iter.v= iter.v_poin->v[0];\
- }\
- if (iter.v >=0) {\
- iter.v_poin= &iter.v_array[iter.v];\
- if ( iter.v_poin->e[0] != iter.e ) iter.e= iter.v_poin->e[0];\
- else iter.e= iter.v_poin->e[1];\
- } else {\
- iter.e= NULL;\
- iter.v_poin= NULL;\
- }
-
-static void screwModifier_initData(ModifierData *md)
-{
- ScrewModifierData *ltmd= (ScrewModifierData*) md;
- ltmd->ob_axis= NULL;
- ltmd->angle= M_PI * 2.0;
- ltmd->axis= 2;
- ltmd->flag= 0;
- ltmd->steps= 16;
- ltmd->render_steps= 16;
- ltmd->iter= 1;
-}
-
-static void screwModifier_copyData(ModifierData *md, ModifierData *target)
-{
- ScrewModifierData *sltmd= (ScrewModifierData*) md;
- ScrewModifierData *tltmd= (ScrewModifierData*) target;
-
- tltmd->ob_axis= sltmd->ob_axis;
- tltmd->angle= sltmd->angle;
- tltmd->axis= sltmd->axis;
- tltmd->flag= sltmd->flag;
- tltmd->steps= sltmd->steps;
- tltmd->render_steps= sltmd->render_steps;
- tltmd->screw_ofs= sltmd->screw_ofs;
- tltmd->iter= sltmd->iter;
-}
-
-static DerivedMesh *screwModifier_applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm= derivedData;
- DerivedMesh *result;
- ScrewModifierData *ltmd= (ScrewModifierData*) md;
-
- int *origindex;
- int mface_index=0;
- int i, j;
- int i1,i2;
- int steps= ltmd->steps;
- int maxVerts=0, maxEdges=0, maxFaces=0;
- int totvert= dm->getNumVerts(dm);
- int totedge= dm->getNumEdges(dm);
-
- char axis_char, close;
- float angle= ltmd->angle;
- float screw_ofs= ltmd->screw_ofs;
- float axis_vec[3]= {0.0f, 0.0f, 0.0f};
- float tmp_vec1[3], tmp_vec2[3];
- float mat3[3][3];
- float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */
- float mtx_tx_inv[4][4]; /* inverted */
- float mtx_tmp_a[4][4];
-
- int vc_tot_linked= 0;
- short other_axis_1, other_axis_2;
- float *tmpf1, *tmpf2;
-
- MFace *mface_new, *mf_new;
- MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
- MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;
-
- ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL;
-
- float mat[4][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 0.0f, 0.0f, 1.0f}};
-
- /* dont do anything? */
- if (!totvert)
- return CDDM_from_template(dm, 0, 0, 0);
-
- steps= useRenderParams ? ltmd->render_steps : ltmd->steps;
-
- switch(ltmd->axis) {
- case 0:
- other_axis_1=1;
- other_axis_2=2;
- break;
- case 1:
- other_axis_1=0;
- other_axis_2=2;
- break;
- case 2:
- other_axis_1=0;
- other_axis_2=1;
- break;
- }
-
- axis_vec[ltmd->axis]= 1.0f;
-
- if (ltmd->ob_axis) {
- float mtx3_tx[3][3];
- /* calc the matrix relative to the axis object */
- invert_m4_m4(mtx_tmp_a, ob->obmat);
- copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat);
- mul_m4_m4m4(mtx_tx, mtx_tx_inv, mtx_tmp_a);
-
- copy_m3_m4(mtx3_tx, mtx_tx);
-
- /* calc the axis vec */
- mul_m3_v3(mtx3_tx, axis_vec);
- normalize_v3(axis_vec);
-
- /* screw */
- if(ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
- /* find the offset along this axis relative to this objects matrix */
- float totlen = len_v3(mtx_tx[3]);
-
- if(totlen != 0.0f) {
- float zero[3]={0.0f, 0.0f, 0.0f};
- float cp[3];
- screw_ofs= closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
- }
- else {
- screw_ofs= 0.0f;
- }
- }
-
- /* angle */
-
-#if 0 // cant incluide this, not pradictable enough, though quite fun,.
- if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
-
-
- float vec[3] = {0,1,0};
- float cross1[3];
- float cross2[3];
- cross_v3_v3v3(cross1, vec, axis_vec);
-
- mul_v3_m3v3(cross2, mtx3_tx, cross1);
- {
- float c1[3];
- float c2[3];
- float axis_tmp[3];
-
- cross_v3_v3v3(c1, cross2, axis_vec);
- cross_v3_v3v3(c2, axis_vec, c1);
-
-
- angle= angle_v3v3(cross1, c2);
-
- cross_v3_v3v3(axis_tmp, cross1, c2);
- normalize_v3(axis_tmp);
-
- if(len_v3v3(axis_tmp, axis_vec) > 1.0f)
- angle= -angle;
-
- }
- }
-#endif
- }
- else {
- /* exis char is used by i_rotate*/
- axis_char= 'X' + ltmd->axis;
-
- /* useful to be able to use the axis vec in some cases still */
- zero_v3(axis_vec);
- axis_vec[ltmd->axis]= 1.0f;
- }
-
- /* apply the multiplier */
- angle *= ltmd->iter;
- screw_ofs *= ltmd->iter;
-
- /* multiplying the steps is a bit tricky, this works best */
- steps = ((steps + 1) * ltmd->iter) - (ltmd->iter - 1);
-
- /* will the screw be closed?
- * Note! smaller then FLT_EPSILON*100 gives problems with float precission so its never closed. */
- if (fabs(screw_ofs) <= (FLT_EPSILON*100) && fabs(fabs(angle) - (M_PI * 2)) <= (FLT_EPSILON*100)) {
- close= 1;
- steps--;
- if(steps < 2) steps= 2;
-
- maxVerts = totvert * steps; /* -1 because we're joining back up */
- maxEdges = (totvert * steps) + /* these are the edges between new verts */
- (totedge * steps); /* -1 because vert edges join */
- maxFaces = totedge * steps;
-
- screw_ofs= 0.0f;
- }
- else {
- close= 0;
- if(steps < 2) steps= 2;
-
- maxVerts = totvert * steps; /* -1 because we're joining back up */
- maxEdges = (totvert * (steps-1)) + /* these are the edges between new verts */
- (totedge * steps); /* -1 because vert edges join */
- maxFaces = totedge * (steps-1);
- }
-
- result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces);
-
- /* copy verts from mesh */
- mvert_orig = dm->getVertArray(dm);
- medge_orig = dm->getEdgeArray(dm);
-
- mvert_new = result->getVertArray(result);
- mface_new = result->getFaceArray(result);
- medge_new = result->getEdgeArray(result);
-
- origindex= result->getFaceDataArray(result, CD_ORIGINDEX);
-
- /* Set the locations of the first set of verts */
-
- mv_new= mvert_new;
- mv_orig= mvert_orig;
-
- /* Copy the first set of edges */
- med_orig= medge_orig;
- med_new= medge_new;
- for (i=0; i < totedge; i++, med_orig++, med_new++) {
- med_new->v1= med_orig->v1;
- med_new->v2= med_orig->v2;
- med_new->crease= med_orig->crease;
- med_new->flag= med_orig->flag & ~ME_LOOSEEDGE;
- }
-
- if(ltmd->flag & MOD_SCREW_NORMAL_CALC) {
- /*
- * Normal Calculation (for face flipping)
- * Sort edge verts for correct face flipping
- * NOT REALLY NEEDED but face flipping is nice.
- *
- * */
-
-
- /* Notice!
- *
- * Since we are only ordering the edges here it can avoid mallocing the
- * extra space by abusing the vert array berfore its filled with new verts.
- * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert
- * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3
- * so its safe to use the second 2 thrids of MVert the array for vert_connect,
- * just make sure ScrewVertConnect struct is no more then twice as big as MVert,
- * at the moment there is no chance of that being a problem,
- * unless MVert becomes half its current size.
- *
- * once the edges are ordered, vert_connect is not needed and it can be used for verts
- *
- * This makes the modifier faster with one less alloc.
- */
-
- vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect");
- //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */
- vc= vert_connect;
-
- /* Copy Vert Locations */
- /* - We can do this in a later loop - only do here if no normal calc */
- if (!totedge) {
- for (i=0; i < totvert; i++, mv_orig++, mv_new++) {
- copy_v3_v3(mv_new->co, mv_orig->co);
- normalize_v3_v3(vc->no, mv_new->co); /* no edges- this is realy a dummy normal */
- }
- }
- else {
- /*printf("\n\n\n\n\nStarting Modifier\n");*/
- /* set edge users */
- med_new= medge_new;
- mv_new= mvert_new;
-
- if (ltmd->ob_axis) {
- /*mtx_tx is initialized early on */
- for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
- vc->co[0]= mv_new->co[0]= mv_orig->co[0];
- vc->co[1]= mv_new->co[1]= mv_orig->co[1];
- vc->co[2]= mv_new->co[2]= mv_orig->co[2];
-
- vc->flag= 0;
- vc->e[0]= vc->e[1]= NULL;
- vc->v[0]= vc->v[1]= -1;
-
- mul_m4_v3(mtx_tx, vc->co);
- /* length in 2d, dont sqrt because this is only for comparison */
- vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] +
- vc->co[other_axis_2]*vc->co[other_axis_2];
-
- /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
- }
- }
- else {
- for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
- vc->co[0]= mv_new->co[0]= mv_orig->co[0];
- vc->co[1]= mv_new->co[1]= mv_orig->co[1];
- vc->co[2]= mv_new->co[2]= mv_orig->co[2];
-
- vc->flag= 0;
- vc->e[0]= vc->e[1]= NULL;
- vc->v[0]= vc->v[1]= -1;
-
- /* length in 2d, dont sqrt because this is only for comparison */
- vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] +
- vc->co[other_axis_2]*vc->co[other_axis_2];
-
- /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
- }
- }
-
- /* this loop builds connectivity info for verts */
- for (i=0; i<totedge; i++, med_new++) {
- vc= &vert_connect[med_new->v1];
-
- if (vc->v[0]==-1) { /* unused */
- vc->v[0]= med_new->v2;
- vc->e[0]= med_new;
- }
- else if (vc->v[1]==-1) {
- vc->v[1]= med_new->v2;
- vc->e[1]= med_new;
- }
- else {
- vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */
- }
-
- vc= &vert_connect[med_new->v2];
-
- /* same as above but swap v1/2 */
- if (vc->v[0]==-1) { /* unused */
- vc->v[0]= med_new->v1;
- vc->e[0]= med_new;
- }
- else if (vc->v[1]==-1) {
- vc->v[1]= med_new->v1;
- vc->e[1]= med_new;
- }
- else {
- vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */
- }
- }
-
- /* find the first vert */
- vc= vert_connect;
- for (i=0; i < totvert; i++, vc++) {
- int VBEST=-1, ed_loop_closed=0; /* vert and vert new */
- int ed_loop_flip;
- float fl= -1.0f;
- ScrewVertIter lt_iter;
-
- /* Now do search for connected verts, order all edges and flip them
- * so resulting faces are flipped the right way */
- vc_tot_linked= 0; /* count the number of linked verts for this loop */
- if (vc->flag==0) {
- /*printf("Loop on connected vert: %i\n", i);*/
-
- for(j=0; j<2; j++) {
- /*printf("\tSide: %i\n", j);*/
- ScrewVertIter_INIT(lt_iter, vert_connect, i, j);
- if (j==1) {
- ScrewVertIter_NEXT(lt_iter);
- }
- while (lt_iter.v_poin) {
- /*printf("\t\tVERT: %i\n", lt_iter.v);*/
- if (lt_iter.v_poin->flag) {
- /*printf("\t\t\tBreaking Found end\n");*/
- //endpoints[0]= endpoints[1]= -1;
- ed_loop_closed= 1; /* circle */
- break;
- }
- lt_iter.v_poin->flag= 1;
- vc_tot_linked++;
- /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/
- if (fl <= lt_iter.v_poin->dist) {
- fl= lt_iter.v_poin->dist;
- VBEST= lt_iter.v;
- /*printf("\t\t\tVERT BEST: %i\n", VBEST);*/
- }
- ScrewVertIter_NEXT(lt_iter);
- if (!lt_iter.v_poin) {
- /*printf("\t\t\tFound End Also Num %i\n", j);*/
- /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */
- break;
- }
- }
- }
-
- /* now we have a collection of used edges. flip their edges the right way*/
- /*if (VBEST !=-1) - */
-
- /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/
-
- if (vc_tot_linked>1) {
- float vf_1, vf_2, vf_best;
-
- vc_tmp= &vert_connect[VBEST];
-
- tmpf1= vert_connect[vc_tmp->v[0]].co;
- tmpf2= vert_connect[vc_tmp->v[1]].co;
-
-
- /* edge connects on each side! */
- if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) {
- /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
- /* find out which is higher */
-
- vf_1= tmpf1[ltmd->axis];
- vf_2= tmpf2[ltmd->axis];
- vf_best= vc_tmp->co[ltmd->axis];
-
- if (vf_1 < vf_best && vf_best < vf_2) {
- ed_loop_flip= 0;
- }
- else if (vf_1 > vf_best && vf_best > vf_2) {
- ed_loop_flip= 1;
- }
- else {
- /* not so simple to work out which edge is higher */
- sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co);
- sub_v3_v3v3(tmp_vec1, tmpf2, vc_tmp->co);
- normalize_v3(tmp_vec1);
- normalize_v3(tmp_vec2);
-
- if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) {
- ed_loop_flip= 1;
- }
- else {
- ed_loop_flip= 0;
- }
- }
- }
- else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */
- /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
- if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
- ed_loop_flip= 1;
- }
- else { /* best is below or even... in even case we cant know whet to do. */
- ed_loop_flip= 0;
- }
-
- }/* else {
- printf("No Connected ___\n");
- }*/
-
- /*printf("flip direction %i\n", ed_loop_flip);*/
-
-
- /* switch the flip option if set */
- if (ltmd->flag & MOD_SCREW_NORMAL_FLIP)
- ed_loop_flip= !ed_loop_flip;
-
- if (angle < 0.0f)
- ed_loop_flip= !ed_loop_flip;
-
- /* if its closed, we only need 1 loop */
- for(j=ed_loop_closed; j<2; j++) {
- /*printf("Ordering Side J %i\n", j);*/
-
- ScrewVertIter_INIT(lt_iter, vert_connect, VBEST, j);
- /*printf("\n\nStarting - Loop\n");*/
- lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */
-
-
- /* If this is the vert off the best vert and
- * the best vert has 2 edges connected too it
- * then swap the flip direction */
- if (j==1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1))
- ed_loop_flip= !ed_loop_flip;
-
- while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
- /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/
-
- lt_iter.v_poin->flag= 2;
- if (lt_iter.e) {
- if (lt_iter.v == lt_iter.e->v1) {
- if (ed_loop_flip==0) {
- /*printf("\t\t\tFlipping 0\n");*/
- SWAP(int, lt_iter.e->v1, lt_iter.e->v2);
- }/* else {
- printf("\t\t\tFlipping Not 0\n");
- }*/
- }
- else if (lt_iter.v == lt_iter.e->v2) {
- if (ed_loop_flip==1) {
- /*printf("\t\t\tFlipping 1\n");*/
- SWAP(int, lt_iter.e->v1, lt_iter.e->v2);
- }/* else {
- printf("\t\t\tFlipping Not 1\n");
- }*/
- }/* else {
- printf("\t\tIncorrect edge topology");
- }*/
- }/* else {
- printf("\t\tNo Edge at this point\n");
- }*/
- ScrewVertIter_NEXT(lt_iter);
- }
- }
- }
- }
-
- /* *VERTEX NORMALS*
- * we know the surrounding edges are ordered correctly now
- * so its safe to create vertex normals.
- *
- * calculate vertex normals that can be propodated on lathing
- * use edge connectivity work this out */
- if (vc->v[0]>=0) {
- if (vc->v[1]>=0) {
- /* 2 edges connedted */
- /* make 2 connecting vert locations relative to the middle vert */
- sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
- sub_v3_v3v3(tmp_vec2, mvert_new[vc->v[1]].co, mvert_new[i].co);
- /* normalize so both edges have the same influence, no matter their length */
- normalize_v3(tmp_vec1);
- normalize_v3(tmp_vec2);
-
- /* vc_no_tmp1 - this line is the average direction of both connecting edges
- *
- * Use the edge order to make the subtraction, flip the normal the right way
- * edge should be there but check just in case... */
- if (vc->e && vc->e[0]->v1 == i) {
- sub_v3_v3v3(tmp_vec1, tmp_vec1, tmp_vec2);
- }
- else {
- sub_v3_v3v3(tmp_vec1, tmp_vec2, tmp_vec1);
- }
- }
- else {
- /* only 1 edge connected - same as above except
- * dont need to average edge direction */
- if (vc->e && vc->e[0]->v2 == i) {
- sub_v3_v3v3(tmp_vec1, mvert_new[i].co, mvert_new[vc->v[0]].co);
- }
- else {
- sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
- }
- }
-
- /* vc_no_tmp2 - is a line 90d from the pivot to the vec
- * This is used so the resulting normal points directly away from the middle */
- cross_v3_v3v3(tmp_vec2, axis_vec, vc->co);
-
- /* edge average vector and right angle to the pivot make the normal */
- cross_v3_v3v3(vc->no, tmp_vec1, tmp_vec2);
-
- }
- else {
- copy_v3_v3(vc->no, vc->co);
- }
-
- /* we wont be looping on this data again so copy normals here */
- if (angle < 0.0f)
- negate_v3(vc->no);
-
- normalize_v3(vc->no);
- normal_float_to_short_v3(mvert_new[i].no, vc->no);
-
- /* Done with normals */
- }
- }
- }
- else {
-
- if (ltmd->flag & MOD_SCREW_NORMAL_FLIP) {
- mv_orig= mvert_orig;
- mv_new= mvert_new + (totvert-1);
-
- for (i=0; i < totvert; i++, mv_new--, mv_orig++) {
- copy_v3_v3(mv_new->co, mv_orig->co);
- }
- }
- else {
- mv_orig= mvert_orig;
- mv_new= mvert_new;
-
- for (i=0; i < totvert; i++, mv_new++, mv_orig++) {
- copy_v3_v3(mv_new->co, mv_orig->co);
- }
- }
- }
- /* done with edge connectivity based normal flipping */
-
-
- /* Add Faces */
- for (i=1; i < steps; i++) {
- float step_angle;
- float no_tx[3];
- /* Rotation Matrix */
- if (close) step_angle= (angle / steps) * i;
- else step_angle= (angle / (steps-1)) * i;
-
- if (ltmd->ob_axis) {
- axis_angle_to_mat3(mat3, axis_vec, step_angle);
- copy_m4_m3(mat, mat3);
- }
- else {
- unit_m4(mat);
- rotate_m4(mat, axis_char, step_angle);
- copy_m3_m4(mat3, mat);
- }
-
- if(screw_ofs)
- madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)i / (float)(steps-1)));
-
- mv_new_base= mvert_new;
- mv_new= &mvert_new[totvert*i]; /* advance to the next slice */
-
- for (j=0; j<totvert; j++, mv_new_base++, mv_new++) {
- /* set normal */
- if(vert_connect) {
- mul_v3_m3v3(no_tx, mat3, vert_connect[j].no);
-
- /* set the normal now its transformed */
- normal_float_to_short_v3(mv_new->no, no_tx);
- }
-
- /* set location */
- copy_v3_v3(mv_new->co, mv_new_base->co);
-
- /* only need to set these if using non cleared memory */
- /*mv_new->mat_nr= mv_new->flag= 0;*/
-
- if (ltmd->ob_axis) {
- sub_v3_v3(mv_new->co, mtx_tx[3]);
-
- mul_m4_v3(mat, mv_new->co);
-
- add_v3_v3(mv_new->co, mtx_tx[3]);
- }
- else {
- mul_m4_v3(mat, mv_new->co);
- }
-
- /* add the new edge */
- med_new->v1= j+(i*totvert);
- med_new->v2= med_new->v1 - totvert;
- med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
- med_new++;
- }
- }
-
- /* we can avoid if using vert alloc trick */
- if(vert_connect) {
- MEM_freeN(vert_connect);
- vert_connect= NULL;
- }
-
- if (close) {
- /* last loop of edges, previous loop dosnt account for the last set of edges */
- for (i=0; i<totvert; i++) {
- med_new->v1= i;
- med_new->v2= i+((steps-1)*totvert);
- med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
- med_new++;
- }
- }
-
- mf_new= mface_new;
- med_new_firstloop= medge_new;
-
- for (i=0; i < totedge; i++, med_new_firstloop++) {
- /* for each edge, make a cylinder of quads */
- i1= med_new_firstloop->v1;
- i2= med_new_firstloop->v2;
-
- for (j=0; j < steps-1; j++) {
-
- /* new face */
- mf_new->v1= i1;
- mf_new->v2= i2;
- mf_new->v3= i2 + totvert;
- mf_new->v4= i1 + totvert;
-
- if( !mf_new->v3 || !mf_new->v4 ) {
- SWAP(int, mf_new->v1, mf_new->v3);
- SWAP(int, mf_new->v2, mf_new->v4);
- }
- mf_new->flag= ME_SMOOTH;
- origindex[mface_index]= ORIGINDEX_NONE;
- mf_new++;
- mface_index++;
-
- /* new vertical edge */
- if (j) { /* The first set is alredy dome */
- med_new->v1= i1;
- med_new->v2= i2;
- med_new->flag= med_new_firstloop->flag;
- med_new->crease= med_new_firstloop->crease;
- med_new++;
- }
- i1 += totvert;
- i2 += totvert;
- }
-
- /* close the loop*/
- if (close) {
- mf_new->v1= i1;
- mf_new->v2= i2;
- mf_new->v3= med_new_firstloop->v2;
- mf_new->v4= med_new_firstloop->v1;
-
- if( !mf_new->v3 || !mf_new->v4 ) {
- SWAP(int, mf_new->v1, mf_new->v3);
- SWAP(int, mf_new->v2, mf_new->v4);
- }
- mf_new->flag= ME_SMOOTH;
- origindex[mface_index]= ORIGINDEX_NONE;
- mf_new++;
- mface_index++;
- }
-
- /* new vertical edge */
- med_new->v1= i1;
- med_new->v2= i2;
- med_new->flag= med_new_firstloop->flag & ~ME_LOOSEEDGE;
- med_new->crease= med_new_firstloop->crease;
- med_new++;
- }
-
- if((ltmd->flag & MOD_SCREW_NORMAL_CALC)==0) {
- CDDM_calc_normals(result);
- }
-
- return result;
-}
-
-
-static void screwModifier_updateDepgraph(
- ModifierData *md, DagForest *forest,
- Scene *scene, Object *ob, DagNode *obNode)
-{
- ScrewModifierData *ltmd= (ScrewModifierData*) md;
-
- if(ltmd->ob_axis) {
- DagNode *curNode= dag_get_node(forest, ltmd->ob_axis);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "Screw Modifier");
- }
-}
-
-static void screwModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- ScrewModifierData *ltmd= (ScrewModifierData*) md;
-
- walk(userData, ob, &ltmd->ob_axis);
-}
-
-/* This dosnt work with material*/
-static DerivedMesh *screwModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData)
-{
- return screwModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-static int screwModifier_dependsOnTime(ModifierData *md)
-{
- return 0;
-}
-
-
-/* Smoke */
-
-static void smokeModifier_initData(ModifierData *md)
-{
- SmokeModifierData *smd = (SmokeModifierData*) md;
-
- smd->domain = NULL;
- smd->flow = NULL;
- smd->coll = NULL;
- smd->type = 0;
- smd->time = -1;
-}
-
-static void smokeModifier_freeData(ModifierData *md)
-{
- SmokeModifierData *smd = (SmokeModifierData*) md;
-
- smokeModifier_free (smd);
-}
-
-static void smokeModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- SmokeModifierData *smd = (SmokeModifierData*) md;
- DerivedMesh *dm = dm= get_cddm(md->scene, ob, NULL, derivedData, vertexCos);
-
- smokeModifier_do(smd, md->scene, ob, dm, useRenderParams, isFinalCalc);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static int smokeModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-
-static void smokeModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
- DagNode *obNode)
-{
- /*SmokeModifierData *smd = (SmokeModifierData *) md;
- if(smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
- {
- if(smd->domain->fluid_group)
- {
- GroupObject *go = NULL;
-
- for(go = smd->domain->fluid_group->gobject.first; go; go = go->next)
- {
- if(go->ob)
- {
- SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
-
- // check for initialized smoke object
- if(smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
- {
- DagNode *curNode = dag_get_node(forest, go->ob);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Smoke Flow");
- }
- }
- }
- }
- }
- */
-}
-
-/* Cloth */
-
-static void clothModifier_initData(ModifierData *md)
-{
- ClothModifierData *clmd = (ClothModifierData*) md;
-
- clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms");
- clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms");
- clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches);
-
- /* check for alloc failing */
- if(!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache)
- return;
-
- cloth_init (clmd);
-}
-
-static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData, int useRenderParams, int isFinalCalc)
-{
- ClothModifierData *clmd = (ClothModifierData*) md;
- DerivedMesh *result=NULL;
-
- /* check for alloc failing */
- if(!clmd->sim_parms || !clmd->coll_parms)
- {
- clothModifier_initData(md);
-
- if(!clmd->sim_parms || !clmd->coll_parms)
- return derivedData;
- }
-
- result = clothModifier_do(clmd, md->scene, ob, derivedData, useRenderParams, isFinalCalc);
-
- if(result)
- {
- CDDM_calc_normals(result);
- return result;
- }
- return derivedData;
-}
-
-static void clothModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
- DagNode *obNode)
-{
- ClothModifierData *clmd = (ClothModifierData*) md;
-
- Base *base;
-
- if(clmd)
- {
- for(base = scene->base.first; base; base= base->next)
- {
- Object *ob1= base->object;
- if(ob1 != ob)
- {
- CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision);
- if(coll_clmd)
- {
- DagNode *curNode = dag_get_node(forest, ob1);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Cloth Collision");
- }
- }
- }
- }
-}
-
-static CustomDataMask clothModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- CustomDataMask dataMask = 0;
- ClothModifierData *clmd = (ClothModifierData*)md;
-
- if(cloth_uses_vgroup(clmd))
- dataMask |= (1 << CD_MDEFORMVERT);
-
- if(clmd->sim_parms->shapekey_rest != 0)
- dataMask |= (1 << CD_CLOTH_ORCO);
-
- return dataMask;
-}
-
-static void clothModifier_copyData(ModifierData *md, ModifierData *target)
-{
- ClothModifierData *clmd = (ClothModifierData*) md;
- ClothModifierData *tclmd = (ClothModifierData*) target;
-
- if(tclmd->sim_parms)
- MEM_freeN(tclmd->sim_parms);
- if(tclmd->coll_parms)
- MEM_freeN(tclmd->coll_parms);
-
- BKE_ptcache_free_list(&tclmd->ptcaches);
- tclmd->point_cache = NULL;
-
- tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms);
- if(clmd->sim_parms->effector_weights)
- tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights);
- tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
- tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches);
- tclmd->clothObject = NULL;
-}
-
-static int clothModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-
-static void clothModifier_freeData(ModifierData *md)
-{
- ClothModifierData *clmd = (ClothModifierData*) md;
-
- if (clmd)
- {
- if(G.rt > 0)
- printf("clothModifier_freeData\n");
-
- cloth_free_modifier_extern (clmd);
-
- if(clmd->sim_parms) {
- if(clmd->sim_parms->effector_weights)
- MEM_freeN(clmd->sim_parms->effector_weights);
- MEM_freeN(clmd->sim_parms);
- }
- if(clmd->coll_parms)
- MEM_freeN(clmd->coll_parms);
-
- BKE_ptcache_free_list(&clmd->ptcaches);
- clmd->point_cache = NULL;
- }
-}
-
-/* Collision */
-
-static void collisionModifier_initData(ModifierData *md)
-{
- CollisionModifierData *collmd = (CollisionModifierData*) md;
-
- collmd->x = NULL;
- collmd->xnew = NULL;
- collmd->current_x = NULL;
- collmd->current_xnew = NULL;
- collmd->current_v = NULL;
- collmd->time = -1000;
- collmd->numverts = 0;
- collmd->bvhtree = NULL;
-}
-
-static void collisionModifier_freeData(ModifierData *md)
-{
- CollisionModifierData *collmd = (CollisionModifierData*) md;
-
- if (collmd)
- {
- if(collmd->bvhtree)
- BLI_bvhtree_free(collmd->bvhtree);
- if(collmd->x)
- MEM_freeN(collmd->x);
- if(collmd->xnew)
- MEM_freeN(collmd->xnew);
- if(collmd->current_x)
- MEM_freeN(collmd->current_x);
- if(collmd->current_xnew)
- MEM_freeN(collmd->current_xnew);
- if(collmd->current_v)
- MEM_freeN(collmd->current_v);
- if(collmd->mfaces)
- MEM_freeN(collmd->mfaces);
-
- collmd->x = NULL;
- collmd->xnew = NULL;
- collmd->current_x = NULL;
- collmd->current_xnew = NULL;
- collmd->current_v = NULL;
- collmd->time = -1000;
- collmd->numverts = 0;
- collmd->bvhtree = NULL;
- collmd->mfaces = NULL;
- }
-}
-
-static int collisionModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-
-static void collisionModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- CollisionModifierData *collmd = (CollisionModifierData*) md;
- DerivedMesh *dm = NULL;
- float current_time = 0;
- unsigned int numverts = 0, i = 0;
- MVert *tempVert = NULL;
-
- /* if possible use/create DerivedMesh */
- if(derivedData) dm = CDDM_copy(derivedData);
- else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
-
- if(!ob->pd)
- {
- printf("collisionModifier_deformVerts: Should not happen!\n");
- return;
- }
-
- if(dm)
- {
- CDDM_apply_vert_coords(dm, vertexCos);
- CDDM_calc_normals(dm);
-
- current_time = bsystem_time (md->scene, ob, ( float ) md->scene->r.cfra, 0.0 );
-
- if(G.rt > 0)
- printf("current_time %f, collmd->time %f\n", current_time, collmd->time);
-
- numverts = dm->getNumVerts ( dm );
-
- if((current_time > collmd->time)|| (BKE_ptcache_get_continue_physics()))
- {
- // check if mesh has changed
- if(collmd->x && (numverts != collmd->numverts))
- collisionModifier_freeData((ModifierData *)collmd);
-
- if(collmd->time == -1000) // first time
- {
- collmd->x = dm->dupVertArray(dm); // frame start position
-
- for ( i = 0; i < numverts; i++ )
- {
- // we save global positions
- mul_m4_v3( ob->obmat, collmd->x[i].co );
- }
-
- collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
- collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
- collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
- collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
-
- collmd->numverts = numverts;
-
- collmd->mfaces = dm->dupFaceArray(dm);
- collmd->numfaces = dm->getNumFaces(dm);
-
- // create bounding box hierarchy
- collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
-
- collmd->time = current_time;
- }
- else if(numverts == collmd->numverts)
- {
- // put positions to old positions
- tempVert = collmd->x;
- collmd->x = collmd->xnew;
- collmd->xnew = tempVert;
-
- memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
-
- for ( i = 0; i < numverts; i++ )
- {
- // we save global positions
- mul_m4_v3( ob->obmat, collmd->xnew[i].co );
- }
-
- memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert));
- memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
-
- /* check if GUI setting has changed for bvh */
- if(collmd->bvhtree)
- {
- if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree))
- {
- BLI_bvhtree_free(collmd->bvhtree);
- collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
- }
-
- }
-
- /* happens on file load (ONLY when i decomment changes in readfile.c) */
- if(!collmd->bvhtree)
- {
- collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
- }
- else
- {
- // recalc static bounding boxes
- bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
- }
-
- collmd->time = current_time;
- }
- else if(numverts != collmd->numverts)
- {
- collisionModifier_freeData((ModifierData *)collmd);
- }
-
- }
- else if(current_time < collmd->time)
- {
- collisionModifier_freeData((ModifierData *)collmd);
- }
- else
- {
- if(numverts != collmd->numverts)
- {
- collisionModifier_freeData((ModifierData *)collmd);
- }
- }
- }
-
- if(dm)
- dm->release(dm);
-}
-
-
-
-/* Surface */
-
-static void surfaceModifier_initData(ModifierData *md)
-{
- SurfaceModifierData *surmd = (SurfaceModifierData*) md;
-
- surmd->bvhtree = NULL;
-}
-
-static void surfaceModifier_freeData(ModifierData *md)
-{
- SurfaceModifierData *surmd = (SurfaceModifierData*) md;
-
- if (surmd)
- {
- if(surmd->bvhtree) {
- free_bvhtree_from_mesh(surmd->bvhtree);
- MEM_freeN(surmd->bvhtree);
- }
-
- if(surmd->dm)
- surmd->dm->release(surmd->dm);
-
- if(surmd->x)
- MEM_freeN(surmd->x);
-
- if(surmd->v)
- MEM_freeN(surmd->v);
-
- surmd->bvhtree = NULL;
- surmd->dm = NULL;
- }
-}
-
-static int surfaceModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-
-static void surfaceModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- SurfaceModifierData *surmd = (SurfaceModifierData*) md;
- unsigned int numverts = 0, i = 0;
-
- if(surmd->dm)
- surmd->dm->release(surmd->dm);
-
- /* if possible use/create DerivedMesh */
- if(derivedData) surmd->dm = CDDM_copy(derivedData);
- else surmd->dm = get_dm(md->scene, ob, NULL, NULL, NULL, 0);
-
- if(!ob->pd)
- {
- printf("surfaceModifier_deformVerts: Should not happen!\n");
- return;
- }
-
- if(surmd->dm)
- {
- int init = 0;
- float *vec;
- MVert *x, *v;
-
- CDDM_apply_vert_coords(surmd->dm, vertexCos);
- CDDM_calc_normals(surmd->dm);
-
- numverts = surmd->dm->getNumVerts ( surmd->dm );
-
- if(numverts != surmd->numverts || surmd->x == NULL || surmd->v == NULL || md->scene->r.cfra != surmd->cfra+1) {
- if(surmd->x) {
- MEM_freeN(surmd->x);
- surmd->x = NULL;
- }
- if(surmd->v) {
- MEM_freeN(surmd->v);
- surmd->v = NULL;
- }
-
- surmd->x = MEM_callocN(numverts * sizeof(MVert), "MVert");
- surmd->v = MEM_callocN(numverts * sizeof(MVert), "MVert");
-
- surmd->numverts = numverts;
-
- init = 1;
- }
-
- /* convert to global coordinates and calculate velocity */
- for(i = 0, x = surmd->x, v = surmd->v; i<numverts; i++, x++, v++) {
- vec = CDDM_get_vert(surmd->dm, i)->co;
- mul_m4_v3(ob->obmat, vec);
-
- if(init)
- v->co[0] = v->co[1] = v->co[2] = 0.0f;
- else
- sub_v3_v3v3(v->co, vec, x->co);
-
- copy_v3_v3(x->co, vec);
- }
-
- surmd->cfra = md->scene->r.cfra;
-
- if(surmd->bvhtree)
- free_bvhtree_from_mesh(surmd->bvhtree);
- else
- surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");
-
- if(surmd->dm->getNumFaces(surmd->dm))
- bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
- else
- bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
- }
-}
-
-
-/* Boolean */
-
-static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
-{
- BooleanModifierData *bmd = (BooleanModifierData*) md;
- BooleanModifierData *tbmd = (BooleanModifierData*) target;
-
- tbmd->object = bmd->object;
- tbmd->operation = bmd->operation;
-}
-
-static int booleanModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- BooleanModifierData *bmd = (BooleanModifierData*) md;
-
- return !bmd->object;
-}
-
-static void booleanModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- BooleanModifierData *bmd = (BooleanModifierData*) md;
-
- walk(userData, ob, &bmd->object);
-}
-
-static void booleanModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
- DagNode *obNode)
-{
- BooleanModifierData *bmd = (BooleanModifierData*) md;
-
- if(bmd->object) {
- DagNode *curNode = dag_get_node(forest, bmd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Boolean Modifier");
- }
-}
-
-static DerivedMesh *booleanModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- BooleanModifierData *bmd = (BooleanModifierData*) md;
- DerivedMesh *dm = bmd->object->derivedFinal;
-
- /* we do a quick sanity check */
- if(dm && (derivedData->getNumFaces(derivedData) > 3)
- && bmd->object && dm->getNumFaces(dm) > 3) {
- DerivedMesh *result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
- 1 + bmd->operation);
-
- /* if new mesh returned, return it; otherwise there was
- * an error, so delete the modifier object */
- if(result)
- return result;
- else
- modifier_setError(md, "Can't execute boolean operation.");
- }
-
- return derivedData;
-}
-
-static CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE);
-
- dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-/* Particles */
-static void particleSystemModifier_initData(ModifierData *md)
-{
- ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
- psmd->psys= 0;
- psmd->dm=0;
- psmd->totdmvert= psmd->totdmedge= psmd->totdmface= 0;
-}
-static void particleSystemModifier_freeData(ModifierData *md)
-{
- ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
-
- if(psmd->dm){
- psmd->dm->needsFree = 1;
- psmd->dm->release(psmd->dm);
- psmd->dm=0;
- }
-
- /* ED_object_modifier_remove may have freed this first before calling
- * modifier_free (which calls this function) */
- if(psmd->psys)
- psmd->psys->flag |= PSYS_DELETE;
-}
-static void particleSystemModifier_copyData(ModifierData *md, ModifierData *target)
-{
- ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
- ParticleSystemModifierData *tpsmd= (ParticleSystemModifierData*) target;
-
- tpsmd->dm = 0;
- tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
- //tpsmd->facepa = 0;
- tpsmd->flag = psmd->flag;
- /* need to keep this to recognise a bit later in copy_object */
- tpsmd->psys = psmd->psys;
-}
-
-static CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
- CustomDataMask dataMask = 0;
- Material *ma;
- MTex *mtex;
- int i;
-
- if(!psmd->psys->part)
- return 0;
-
- ma= give_current_material(ob, psmd->psys->part->omat);
- if(ma) {
- for(i=0; i<MAX_MTEX; i++) {
- mtex=ma->mtex[i];
- if(mtex && (ma->septex & (1<<i))==0)
- if(mtex->pmapto && (mtex->texco & TEXCO_UV))
- dataMask |= (1 << CD_MTFACE);
- }
- }
-
- if(psmd->psys->part->tanfac!=0.0)
- dataMask |= (1 << CD_MTFACE);
-
- /* ask for vertexgroups if we need them */
- for(i=0; i<PSYS_TOT_VG; i++){
- if(psmd->psys->vgroup[i]){
- dataMask |= (1 << CD_MDEFORMVERT);
- break;
- }
- }
-
- /* particles only need this if they are after a non deform modifier, and
- * the modifier stack will only create them in that case. */
- dataMask |= CD_MASK_ORIGSPACE;
-
- dataMask |= CD_MASK_ORCO;
-
- return dataMask;
-}
-
-/* saves the current emitter state for a particle system and calculates particles */
-static void particleSystemModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm = derivedData;
- ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
- ParticleSystem * psys=0;
- int needsFree=0;
-
- if(ob->particlesystem.first)
- psys=psmd->psys;
- else
- return;
-
- if(!psys_check_enabled(ob, psys))
- return;
-
- if(dm==0) {
- dm= get_dm(md->scene, ob, NULL, NULL, vertexCos, 1);
-
- if(!dm)
- return;
-
- needsFree= 1;
- }
-
- /* clear old dm */
- if(psmd->dm){
- psmd->dm->needsFree = 1;
- psmd->dm->release(psmd->dm);
- }
-
- /* make new dm */
- psmd->dm=CDDM_copy(dm);
- CDDM_apply_vert_coords(psmd->dm, vertexCos);
- CDDM_calc_normals(psmd->dm);
-
- if(needsFree){
- dm->needsFree = 1;
- dm->release(dm);
- }
-
- /* protect dm */
- psmd->dm->needsFree = 0;
-
- /* report change in mesh structure */
- if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert ||
- psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge ||
- psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){
- /* in file read dm hasn't really changed but just wasn't saved in file */
-
- psys->recalc |= PSYS_RECALC_RESET;
- psmd->flag |= eParticleSystemFlag_DM_changed;
-
- psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm);
- psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm);
- psmd->totdmface= psmd->dm->getNumFaces(psmd->dm);
- }
-
- if(psys) {
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(md->scene, ob, psys);
- psmd->flag |= eParticleSystemFlag_psys_updated;
- psmd->flag &= ~eParticleSystemFlag_DM_changed;
- }
-}
-
-/* disabled particles in editmode for now, until support for proper derivedmesh
- * updates is coded */
-#if 0
-static void particleSystemModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm = derivedData;
-
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
- particleSystemModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
-
- if(!derivedData) dm->release(dm);
-}
-#endif
-
-/* Particle Instance */
-static void particleInstanceModifier_initData(ModifierData *md)
-{
- ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
-
- pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn|
- eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead;
- pimd->psys = 1;
- pimd->position = 1.0f;
- pimd->axis = 2;
-
-}
-static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *target)
-{
- ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
- ParticleInstanceModifierData *tpimd= (ParticleInstanceModifierData*) target;
-
- tpimd->ob = pimd->ob;
- tpimd->psys = pimd->psys;
- tpimd->flag = pimd->flag;
- tpimd->axis = pimd->axis;
- tpimd->position = pimd->position;
- tpimd->random_position = pimd->random_position;
-}
-
-static int particleInstanceModifier_dependsOnTime(ModifierData *md)
-{
- return 0;
-}
-static void particleInstanceModifier_updateDepgraph(ModifierData *md, DagForest *forest,
- Scene *scene,Object *ob, DagNode *obNode)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
-
- if (pimd->ob) {
- DagNode *curNode = dag_get_node(forest, pimd->ob);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "Particle Instance Modifier");
- }
-}
-
-static void particleInstanceModifier_foreachObjectLink(ModifierData *md, Object *ob,
- ObjectWalkFunc walk, void *userData)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
-
- walk(userData, ob, &pimd->ob);
-}
-
-static DerivedMesh * particleInstanceModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm = derivedData, *result;
- ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
- ParticleSimulationData sim;
- ParticleSystem * psys=0;
- ParticleData *pa=0, *pars=0;
- MFace *mface, *orig_mface;
- MVert *mvert, *orig_mvert;
- int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
- short track=ob->trackflag%3, trackneg, axis = pimd->axis;
- float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
- float *size=NULL;
-
- trackneg=((ob->trackflag>2)?1:0);
-
- if(pimd->ob==ob){
- pimd->ob=0;
- return derivedData;
- }
-
- if(pimd->ob){
- psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
- if(psys==0 || psys->totpart==0)
- return derivedData;
- }
- else return derivedData;
-
- if(pimd->flag & eParticleInstanceFlag_Parents)
- totpart+=psys->totpart;
- if(pimd->flag & eParticleInstanceFlag_Children){
- if(totpart==0)
- first_particle=psys->totpart;
- totpart+=psys->totchild;
- }
-
- if(totpart==0)
- return derivedData;
-
- sim.scene = md->scene;
- sim.ob = pimd->ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(pimd->ob, psys);
-
- if(pimd->flag & eParticleInstanceFlag_UseSize) {
- int p;
- float *si;
- si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
-
- if(pimd->flag & eParticleInstanceFlag_Parents) {
- for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
- *si = pa->size;
- }
-
- if(pimd->flag & eParticleInstanceFlag_Children) {
- ChildParticle *cpa = psys->child;
-
- for(p=0; p<psys->totchild; p++, cpa++, si++) {
- *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
- }
- }
- }
-
- pars=psys->particles;
-
- totvert=dm->getNumVerts(dm);
- totface=dm->getNumFaces(dm);
-
- maxvert=totvert*totpart;
- maxface=totface*totpart;
-
- psys->lattice=psys_get_lattice(&sim);
-
- if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){
-
- float min_r[3], max_r[3];
- INIT_MINMAX(min_r, max_r);
- dm->getMinMax(dm, min_r, max_r);
- min_co=min_r[track];
- max_co=max_r[track];
- }
-
- result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);
-
- mvert=result->getVertArray(result);
- orig_mvert=dm->getVertArray(dm);
-
- for(i=0; i<maxvert; i++){
- MVert *inMV;
- MVert *mv = mvert + i;
- ParticleKey state;
-
- inMV = orig_mvert + i%totvert;
- DM_copy_vert_data(dm, result, i%totvert, i, 1);
- *mv = *inMV;
-
- /*change orientation based on object trackflag*/
- VECCOPY(temp_co,mv->co);
- mv->co[axis]=temp_co[track];
- mv->co[(axis+1)%3]=temp_co[(track+1)%3];
- mv->co[(axis+2)%3]=temp_co[(track+2)%3];
-
- if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
- float ran = 0.0f;
- if(pimd->random_position != 0.0f) {
- BLI_srandom(psys->seed + (i/totvert)%totpart);
- ran = pimd->random_position * BLI_frand();
- }
-
- if(pimd->flag & eParticleInstanceFlag_KeepShape) {
- state.time = pimd->position * (1.0f - ran);
- }
- else {
- state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);
-
- if(trackneg)
- state.time=1.0f-state.time;
-
- mv->co[axis] = 0.0;
- }
-
- psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);
-
- normalize_v3(state.vel);
-
- /* TODO: incremental rotations somehow */
- if(state.vel[axis] < -0.9999 || state.vel[axis] > 0.9999) {
- state.rot[0] = 1;
- state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
- }
- else {
- float temp[3] = {0.0f,0.0f,0.0f};
- temp[axis] = 1.0f;
-
- cross_v3_v3v3(cross, temp, state.vel);
-
- /* state.vel[axis] is the only component surviving from a dot product with the axis */
- axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis]));
- }
-
- }
- else{
- state.time=-1.0;
- psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
- }
-
- mul_qt_v3(state.rot,mv->co);
- if(pimd->flag & eParticleInstanceFlag_UseSize)
- mul_v3_fl(mv->co, size[i/totvert]);
- VECADD(mv->co,mv->co,state.co);
- }
-
- mface=result->getFaceArray(result);
- orig_mface=dm->getFaceArray(dm);
-
- for(i=0; i<maxface; i++){
- MFace *inMF;
- MFace *mf = mface + i;
-
- if(pimd->flag & eParticleInstanceFlag_Parents){
- if(i/totface>=psys->totpart){
- if(psys->part->childtype==PART_CHILD_PARTICLES)
- pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
- else
- pa=0;
- }
- else
- pa=pars+i/totface;
- }
- else{
- if(psys->part->childtype==PART_CHILD_PARTICLES)
- pa=psys->particles+(psys->child+i/totface)->parent;
- else
- pa=0;
- }
-
- if(pa){
- if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
- if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
- if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
- }
-
- inMF = orig_mface + i%totface;
- DM_copy_face_data(dm, result, i%totface, i, 1);
- *mf = *inMF;
-
- mf->v1+=(i/totface)*totvert;
- mf->v2+=(i/totface)*totvert;
- mf->v3+=(i/totface)*totvert;
- if(mf->v4)
- mf->v4+=(i/totface)*totvert;
- }
-
- CDDM_calc_edges(result);
- CDDM_calc_normals(result);
-
- if(psys->lattice){
- end_latt_deform(psys->lattice);
- psys->lattice= NULL;
- }
-
- if(size)
- MEM_freeN(size);
-
- return result;
-}
-static DerivedMesh *particleInstanceModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData)
-{
- return particleInstanceModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Explode */
-static void explodeModifier_initData(ModifierData *md)
-{
- ExplodeModifierData *emd= (ExplodeModifierData*) md;
-
- emd->facepa=0;
- emd->flag |= eExplodeFlag_Unborn+eExplodeFlag_Alive+eExplodeFlag_Dead;
-}
-static void explodeModifier_freeData(ModifierData *md)
-{
- ExplodeModifierData *emd= (ExplodeModifierData*) md;
-
- if(emd->facepa) MEM_freeN(emd->facepa);
-}
-static void explodeModifier_copyData(ModifierData *md, ModifierData *target)
-{
- ExplodeModifierData *emd= (ExplodeModifierData*) md;
- ExplodeModifierData *temd= (ExplodeModifierData*) target;
-
- temd->facepa = 0;
- temd->flag = emd->flag;
- temd->protect = emd->protect;
- temd->vgroup = emd->vgroup;
-}
-static int explodeModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-static CustomDataMask explodeModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- ExplodeModifierData *emd= (ExplodeModifierData*) md;
- CustomDataMask dataMask = 0;
-
- if(emd->vgroup)
- dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static void explodeModifier_createFacepa(ExplodeModifierData *emd,
- ParticleSystemModifierData *psmd,
- Object *ob, DerivedMesh *dm)
-{
- ParticleSystem *psys=psmd->psys;
- MFace *fa=0, *mface=0;
- MVert *mvert = 0;
- ParticleData *pa;
- KDTree *tree;
- float center[3], co[3];
- int *facepa=0,*vertpa=0,totvert=0,totface=0,totpart=0;
- int i,p,v1,v2,v3,v4=0;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
- totface= dm->getNumFaces(dm);
- totvert= dm->getNumVerts(dm);
- totpart= psmd->psys->totpart;
-
- BLI_srandom(psys->seed);
-
- if(emd->facepa)
- MEM_freeN(emd->facepa);
-
- facepa = emd->facepa = MEM_callocN(sizeof(int)*totface, "explode_facepa");
-
- vertpa = MEM_callocN(sizeof(int)*totvert, "explode_vertpa");
-
- /* initialize all faces & verts to no particle */
- for(i=0; i<totface; i++)
- facepa[i]=totpart;
-
- for (i=0; i<totvert; i++)
- vertpa[i]=totpart;
-
- /* set protected verts */
- if(emd->vgroup){
- MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
- float val;
- if(dvert){
- int defgrp_index= emd->vgroup-1;
- for(i=0; i<totvert; i++, dvert++){
- val = BLI_frand();
- val = (1.0f-emd->protect)*val + emd->protect*0.5f;
- if(val < defvert_find_weight(dvert, defgrp_index))
- vertpa[i] = -1;
- }
- }
- }
-
- /* make tree of emitter locations */
- tree=BLI_kdtree_new(totpart);
- for(p=0,pa=psys->particles; p<totpart; p++,pa++){
- psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,0,0);
- BLI_kdtree_insert(tree, p, co, NULL);
- }
- BLI_kdtree_balance(tree);
-
- /* set face-particle-indexes to nearest particle to face center */
- for(i=0,fa=mface; i<totface; i++,fa++){
- add_v3_v3v3(center,mvert[fa->v1].co,mvert[fa->v2].co);
- add_v3_v3v3(center,center,mvert[fa->v3].co);
- if(fa->v4){
- add_v3_v3v3(center,center,mvert[fa->v4].co);
- mul_v3_fl(center,0.25);
- }
- else
- mul_v3_fl(center,0.3333f);
-
- p= BLI_kdtree_find_nearest(tree,center,NULL,NULL);
-
- v1=vertpa[fa->v1];
- v2=vertpa[fa->v2];
- v3=vertpa[fa->v3];
- if(fa->v4)
- v4=vertpa[fa->v4];
-
- if(v1>=0 && v2>=0 && v3>=0 && (fa->v4==0 || v4>=0))
- facepa[i]=p;
-
- if(v1>=0) vertpa[fa->v1]=p;
- if(v2>=0) vertpa[fa->v2]=p;
- if(v3>=0) vertpa[fa->v3]=p;
- if(fa->v4 && v4>=0) vertpa[fa->v4]=p;
- }
-
- if(vertpa) MEM_freeN(vertpa);
- BLI_kdtree_free(tree);
-}
-
-static int edgesplit_get(EdgeHash *edgehash, int v1, int v2)
-{
- return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2));
-}
-
-static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
- DerivedMesh *splitdm;
- MFace *mf=0,*df1=0,*df2=0,*df3=0;
- MFace *mface=CDDM_get_faces(dm);
- MVert *dupve, *mv;
- EdgeHash *edgehash;
- EdgeHashIterator *ehi;
- int totvert=dm->getNumVerts(dm);
- int totface=dm->getNumFaces(dm);
-
- int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_facesplit");
- int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2");
- int *facepa = emd->facepa;
- int *fs, totesplit=0,totfsplit=0,totin=0,curdupvert=0,curdupface=0,curdupin=0;
- int i,j,v1,v2,v3,v4,esplit;
-
- edgehash= BLI_edgehash_new();
-
- /* recreate vertpa from facepa calculation */
- for (i=0,mf=mface; i<totface; i++,mf++) {
- vertpa[mf->v1]=facepa[i];
- vertpa[mf->v2]=facepa[i];
- vertpa[mf->v3]=facepa[i];
- if(mf->v4)
- vertpa[mf->v4]=facepa[i];
- }
-
- /* mark edges for splitting and how to split faces */
- for (i=0,mf=mface,fs=facesplit; i<totface; i++,mf++,fs++) {
- if(mf->v4){
- v1=vertpa[mf->v1];
- v2=vertpa[mf->v2];
- v3=vertpa[mf->v3];
- v4=vertpa[mf->v4];
-
- if(v1!=v2){
- BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL);
- (*fs)++;
- }
-
- if(v2!=v3){
- BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL);
- (*fs)++;
- }
-
- if(v3!=v4){
- BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL);
- (*fs)++;
- }
-
- if(v1!=v4){
- BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL);
- (*fs)++;
- }
-
- if(*fs==2){
- if((v1==v2 && v3==v4) || (v1==v4 && v2==v3))
- *fs=1;
- else if(v1!=v2){
- if(v1!=v4)
- BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL);
- else
- BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL);
- }
- else{
- if(v1!=v4)
- BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL);
- else
- BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL);
- }
- }
- }
- }
-
- /* count splits & reindex */
- ehi= BLI_edgehashIterator_new(edgehash);
- totesplit=totvert;
- for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totesplit));
- totesplit++;
- }
- BLI_edgehashIterator_free(ehi);
-
- /* count new faces due to splitting */
- for(i=0,fs=facesplit; i<totface; i++,fs++){
- if(*fs==1)
- totfsplit+=1;
- else if(*fs==2)
- totfsplit+=2;
- else if(*fs==3)
- totfsplit+=3;
- else if(*fs==4){
- totfsplit+=3;
-
- mf=dm->getFaceData(dm,i,CD_MFACE);//CDDM_get_face(dm,i);
-
- if(vertpa[mf->v1]!=vertpa[mf->v2] && vertpa[mf->v2]!=vertpa[mf->v3])
- totin++;
- }
- }
-
- splitdm= CDDM_from_template(dm, totesplit+totin, dm->getNumEdges(dm),totface+totfsplit);
-
- /* copy new faces & verts (is it really this painful with custom data??) */
- for(i=0; i<totvert; i++){
- MVert source;
- MVert *dest;
- dm->getVert(dm, i, &source);
- dest = CDDM_get_vert(splitdm, i);
-
- DM_copy_vert_data(dm, splitdm, i, i, 1);
- *dest = source;
- }
- for(i=0; i<totface; i++){
- MFace source;
- MFace *dest;
- dm->getFace(dm, i, &source);
- dest = CDDM_get_face(splitdm, i);
-
- DM_copy_face_data(dm, splitdm, i, i, 1);
- *dest = source;
- }
-
- /* override original facepa (original pointer is saved in caller function) */
- facepa= MEM_callocN(sizeof(int)*(totface+totfsplit),"explode_facepa");
- memcpy(facepa,emd->facepa,totface*sizeof(int));
- emd->facepa=facepa;
-
- /* create new verts */
- curdupvert=totvert;
- ehi= BLI_edgehashIterator_new(edgehash);
- for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_getKey(ehi, &i, &j);
- esplit= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
- mv=CDDM_get_vert(splitdm,j);
- dupve=CDDM_get_vert(splitdm,esplit);
-
- DM_copy_vert_data(splitdm,splitdm,j,esplit,1);
-
- *dupve=*mv;
-
- mv=CDDM_get_vert(splitdm,i);
-
- VECADD(dupve->co,dupve->co,mv->co);
- mul_v3_fl(dupve->co,0.5);
- }
- BLI_edgehashIterator_free(ehi);
-
- /* create new faces */
- curdupface=totface;
- curdupin=totesplit;
- for(i=0,fs=facesplit; i<totface; i++,fs++){
- if(*fs){
- mf=CDDM_get_face(splitdm,i);
-
- v1=vertpa[mf->v1];
- v2=vertpa[mf->v2];
- v3=vertpa[mf->v3];
- v4=vertpa[mf->v4];
- /* ouch! creating new faces & remapping them to new verts is no fun */
- if(*fs==1){
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df1=*mf;
- curdupface++;
-
- if(v1==v2){
- df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
- df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
- mf->v3=df1->v2;
- mf->v4=df1->v1;
- }
- else{
- df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
- df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4);
- mf->v2=df1->v1;
- mf->v3=df1->v4;
- }
-
- facepa[i]=v1;
- facepa[curdupface-1]=v3;
-
- test_index_face(df1, &splitdm->faceData, curdupface, (df1->v4 ? 4 : 3));
- }
- if(*fs==2){
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df1=*mf;
- curdupface++;
-
- df2=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df2=*mf;
- curdupface++;
-
- if(v1!=v2){
- if(v1!=v4){
- df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
- df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
- df2->v1=df1->v3=mf->v2;
- df2->v3=df1->v4=mf->v4;
- df2->v2=mf->v3;
-
- mf->v2=df1->v2;
- mf->v3=df1->v1;
-
- df2->v4=mf->v4=0;
-
- facepa[i]=v1;
- }
- else{
- df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
- df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
- df1->v4=mf->v3;
- df2->v2=mf->v3;
- df2->v3=mf->v4;
-
- mf->v1=df1->v2;
- mf->v3=df1->v3;
-
- df2->v4=mf->v4=0;
-
- facepa[i]=v2;
- }
- facepa[curdupface-1]=facepa[curdupface-2]=v3;
- }
- else{
- if(v1!=v4){
- df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
- df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
- df1->v2=mf->v3;
-
- mf->v1=df1->v4;
- mf->v2=df1->v3;
- mf->v3=mf->v4;
-
- df2->v4=mf->v4=0;
-
- facepa[i]=v4;
- }
- else{
- df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
- df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4);
- df1->v1=mf->v4;
- df1->v2=mf->v2;
- df2->v3=mf->v4;
-
- mf->v1=df1->v4;
- mf->v2=df1->v3;
-
- df2->v4=mf->v4=0;
-
- facepa[i]=v3;
- }
-
- facepa[curdupface-1]=facepa[curdupface-2]=v1;
- }
-
- test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
- test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
- }
- else if(*fs==3){
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df1=*mf;
- curdupface++;
-
- df2=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df2=*mf;
- curdupface++;
-
- df3=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df3=*mf;
- curdupface++;
-
- if(v1==v2){
- df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
- df3->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
- df3->v3=df2->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
- df3->v2=mf->v3;
- df2->v3=mf->v4;
- df1->v4=df2->v4=df3->v4=0;
-
- mf->v3=df1->v2;
- mf->v4=df1->v1;
-
- facepa[i]=facepa[curdupface-3]=v1;
- facepa[curdupface-1]=v3;
- facepa[curdupface-2]=v4;
- }
- else if(v2==v3){
- df3->v1=df2->v3=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
- df2->v2=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
- df3->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-
- df3->v3=mf->v4;
- df2->v1=mf->v1;
- df1->v4=df2->v4=df3->v4=0;
-
- mf->v1=df1->v2;
- mf->v4=df1->v3;
-
- facepa[i]=facepa[curdupface-3]=v2;
- facepa[curdupface-1]=v4;
- facepa[curdupface-2]=v1;
- }
- else if(v3==v4){
- df3->v2=df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
- df2->v3=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
- df3->v3=df1->v3=edgesplit_get(edgehash, mf->v1, mf->v4);
-
- df3->v1=mf->v1;
- df2->v2=mf->v2;
- df1->v4=df2->v4=df3->v4=0;
-
- mf->v1=df1->v3;
- mf->v2=df1->v2;
-
- facepa[i]=facepa[curdupface-3]=v3;
- facepa[curdupface-1]=v1;
- facepa[curdupface-2]=v2;
- }
- else{
- df3->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
- df3->v3=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
- df2->v3=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-
- df3->v2=mf->v2;
- df2->v2=mf->v3;
- df1->v4=df2->v4=df3->v4=0;
-
- mf->v2=df1->v1;
- mf->v3=df1->v3;
-
- facepa[i]=facepa[curdupface-3]=v1;
- facepa[curdupface-1]=v2;
- facepa[curdupface-2]=v3;
- }
-
- test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
- test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
- test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
- }
- else if(*fs==4){
- if(v1!=v2 && v2!=v3){
-
- /* set new vert to face center */
- mv=CDDM_get_vert(splitdm,mf->v1);
- dupve=CDDM_get_vert(splitdm,curdupin);
- DM_copy_vert_data(splitdm,splitdm,mf->v1,curdupin,1);
- *dupve=*mv;
-
- mv=CDDM_get_vert(splitdm,mf->v2);
- VECADD(dupve->co,dupve->co,mv->co);
- mv=CDDM_get_vert(splitdm,mf->v3);
- VECADD(dupve->co,dupve->co,mv->co);
- mv=CDDM_get_vert(splitdm,mf->v4);
- VECADD(dupve->co,dupve->co,mv->co);
- mul_v3_fl(dupve->co,0.25);
-
-
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df1=*mf;
- curdupface++;
-
- df2=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df2=*mf;
- curdupface++;
-
- df3=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df3=*mf;
- curdupface++;
-
- df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
- df3->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
-
- df2->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
- df3->v4=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-
- df3->v1=df2->v2=df1->v4=curdupin;
-
- mf->v2=df1->v1;
- mf->v3=curdupin;
- mf->v4=df2->v1;
-
- curdupin++;
-
- facepa[i]=v1;
- facepa[curdupface-3]=v2;
- facepa[curdupface-2]=v3;
- facepa[curdupface-1]=v4;
-
- test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
-
- test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
- test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
- }
- else{
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df1=*mf;
- curdupface++;
-
- df2=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df2=*mf;
- curdupface++;
-
- df3=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
- *df3=*mf;
- curdupface++;
-
- if(v2==v3){
- df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
- df3->v1=df1->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
- df2->v1=df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
-
- df3->v3=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-
- df3->v2=mf->v3;
- df3->v4=0;
-
- mf->v2=df1->v1;
- mf->v3=df1->v4;
- mf->v4=0;
-
- facepa[i]=v1;
- facepa[curdupface-3]=facepa[curdupface-2]=v2;
- facepa[curdupface-1]=v3;
- }
- else{
- df3->v1=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
- df2->v4=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
- df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
-
- df3->v3=df2->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
-
- df3->v4=0;
-
- mf->v1=df1->v4;
- mf->v2=df1->v3;
- mf->v3=mf->v4;
- mf->v4=0;
-
- facepa[i]=v4;
- facepa[curdupface-3]=facepa[curdupface-2]=v1;
- facepa[curdupface-1]=v2;
- }
-
- test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
- test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
- test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
- }
- }
-
- test_index_face(df1, &splitdm->faceData, i, (df1->v4 ? 4 : 3));
- }
- }
-
- BLI_edgehash_free(edgehash, NULL);
- MEM_freeN(facesplit);
- MEM_freeN(vertpa);
-
- return splitdm;
-
-}
-static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
- ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
- DerivedMesh *to_explode)
-{
- DerivedMesh *explode, *dm=to_explode;
- MFace *mf=0, *mface;
- ParticleSettings *part=psmd->psys->part;
- ParticleSimulationData sim = {scene, ob, psmd->psys, psmd};
- ParticleData *pa=NULL, *pars=psmd->psys->particles;
- ParticleKey state;
- EdgeHash *vertpahash;
- EdgeHashIterator *ehi;
- float *vertco=0, imat[4][4];
- float loc0[3], nor[3];
- float timestep, cfra;
- int *facepa=emd->facepa;
- int totdup=0,totvert=0,totface=0,totpart=0;
- int i, j, v, mindex=0;
-
- totface= dm->getNumFaces(dm);
- totvert= dm->getNumVerts(dm);
- mface= dm->getFaceArray(dm);
- totpart= psmd->psys->totpart;
-
- timestep= psys_get_timestep(&sim);
-
- //if(part->flag & PART_GLOB_TIME)
- cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0);
- //else
- // cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0);
-
- /* hash table for vertice <-> particle relations */
- vertpahash= BLI_edgehash_new();
-
- for (i=0; i<totface; i++) {
- /* do mindex + totvert to ensure the vertex index to be the first
- * with BLI_edgehashIterator_getKey */
- if(facepa[i]==totpart || cfra <= (pars+facepa[i])->time)
- mindex = totvert+totpart;
- else
- mindex = totvert+facepa[i];
-
- mf= &mface[i];
-
- /* set face vertices to exist in particle group */
- BLI_edgehash_insert(vertpahash, mf->v1, mindex, NULL);
- BLI_edgehash_insert(vertpahash, mf->v2, mindex, NULL);
- BLI_edgehash_insert(vertpahash, mf->v3, mindex, NULL);
- if(mf->v4)
- BLI_edgehash_insert(vertpahash, mf->v4, mindex, NULL);
- }
-
- /* make new vertice indexes & count total vertices after duplication */
- ehi= BLI_edgehashIterator_new(vertpahash);
- for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup));
- totdup++;
- }
- BLI_edgehashIterator_free(ehi);
-
- /* the final duplicated vertices */
- explode= CDDM_from_template(dm, totdup, 0,totface);
- /*dupvert= CDDM_get_verts(explode);*/
-
- /* getting back to object space */
- invert_m4_m4(imat,ob->obmat);
-
- psmd->psys->lattice = psys_get_lattice(&sim);
-
- /* duplicate & displace vertices */
- ehi= BLI_edgehashIterator_new(vertpahash);
- for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- MVert source;
- MVert *dest;
-
- /* get particle + vertex from hash */
- BLI_edgehashIterator_getKey(ehi, &j, &i);
- i -= totvert;
- v= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
-
- dm->getVert(dm, j, &source);
- dest = CDDM_get_vert(explode,v);
-
- DM_copy_vert_data(dm,explode,j,v,1);
- *dest = source;
-
- if(i!=totpart) {
- /* get particle */
- pa= pars+i;
-
- /* get particle state */
- psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc0,nor,0,0,0,0);
- mul_m4_v3(ob->obmat,loc0);
-
- state.time=cfra;
- psys_get_particle_state(&sim, i, &state, 1);
-
- vertco=CDDM_get_vert(explode,v)->co;
-
- mul_m4_v3(ob->obmat,vertco);
-
- VECSUB(vertco,vertco,loc0);
-
- /* apply rotation, size & location */
- mul_qt_v3(state.rot,vertco);
- if(emd->flag & eExplodeFlag_PaSize)
- mul_v3_fl(vertco,pa->size);
- VECADD(vertco,vertco,state.co);
-
- mul_m4_v3(imat,vertco);
- }
- }
- BLI_edgehashIterator_free(ehi);
-
- /*map new vertices to faces*/
- for (i=0; i<totface; i++) {
- MFace source;
- int orig_v4;
-
- if(facepa[i]!=totpart)
- {
- pa=pars+facepa[i];
-
- if(pa->alive==PARS_UNBORN && (emd->flag&eExplodeFlag_Unborn)==0) continue;
- if(pa->alive==PARS_ALIVE && (emd->flag&eExplodeFlag_Alive)==0) continue;
- if(pa->alive==PARS_DEAD && (emd->flag&eExplodeFlag_Dead)==0) continue;
- }
-
- dm->getFace(dm,i,&source);
- mf=CDDM_get_face(explode,i);
-
- orig_v4 = source.v4;
-
- if(facepa[i]!=totpart && cfra <= pa->time)
- mindex = totvert+totpart;
- else
- mindex = totvert+facepa[i];
-
- source.v1 = edgesplit_get(vertpahash, source.v1, mindex);
- source.v2 = edgesplit_get(vertpahash, source.v2, mindex);
- source.v3 = edgesplit_get(vertpahash, source.v3, mindex);
- if(source.v4)
- source.v4 = edgesplit_get(vertpahash, source.v4, mindex);
-
- DM_copy_face_data(dm,explode,i,i,1);
-
- *mf = source;
-
- test_index_face(mf, &explode->faceData, i, (orig_v4 ? 4 : 3));
- }
-
- /* cleanup */
- BLI_edgehash_free(vertpahash, NULL);
-
- /* finalization */
- CDDM_calc_edges(explode);
- CDDM_calc_normals(explode);
-
- if(psmd->psys->lattice){
- end_latt_deform(psmd->psys->lattice);
- psmd->psys->lattice= NULL;
- }
-
- return explode;
-}
-
-static ParticleSystemModifierData * explodeModifier_findPrecedingParticlesystem(Object *ob, ModifierData *emd)
-{
- ModifierData *md;
- ParticleSystemModifierData *psmd=0;
-
- for (md=ob->modifiers.first; emd!=md; md=md->next){
- if(md->type==eModifierType_ParticleSystem)
- psmd= (ParticleSystemModifierData*) md;
- }
- return psmd;
-}
-static DerivedMesh * explodeModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm = derivedData;
- ExplodeModifierData *emd= (ExplodeModifierData*) md;
- ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md);
-
- if(psmd){
- ParticleSystem * psys=psmd->psys;
-
- if(psys==0 || psys->totpart==0) return derivedData;
- if(psys->part==0 || psys->particles==0) return derivedData;
- if(psmd->dm==0) return derivedData;
-
- /* 1. find faces to be exploded if needed */
- if(emd->facepa==0
- || psmd->flag&eParticleSystemFlag_Pars
- || emd->flag&eExplodeFlag_CalcFaces
- || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumFaces(dm)){
- if(psmd->flag & eParticleSystemFlag_Pars)
- psmd->flag &= ~eParticleSystemFlag_Pars;
-
- if(emd->flag & eExplodeFlag_CalcFaces)
- emd->flag &= ~eExplodeFlag_CalcFaces;
-
- explodeModifier_createFacepa(emd,psmd,ob,derivedData);
- }
-
- /* 2. create new mesh */
- if(emd->flag & eExplodeFlag_EdgeSplit){
- int *facepa = emd->facepa;
- DerivedMesh *splitdm=explodeModifier_splitEdges(emd,dm);
- DerivedMesh *explode=explodeModifier_explodeMesh(emd, psmd, md->scene, ob, splitdm);
-
- MEM_freeN(emd->facepa);
- emd->facepa=facepa;
- splitdm->release(splitdm);
- return explode;
- }
- else
- return explodeModifier_explodeMesh(emd, psmd, md->scene, ob, derivedData);
- }
- return derivedData;
-}
-
-/* Fluidsim */
-static void fluidsimModifier_initData(ModifierData *md)
-{
- FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
-
- fluidsim_init(fluidmd);
-}
-static void fluidsimModifier_freeData(ModifierData *md)
-{
- FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
-
- fluidsim_free(fluidmd);
-}
-
-static void fluidsimModifier_copyData(ModifierData *md, ModifierData *target)
-{
- FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
- FluidsimModifierData *tfluidmd= (FluidsimModifierData*) target;
-
- if(tfluidmd->fss)
- MEM_freeN(tfluidmd->fss);
-
- tfluidmd->fss = MEM_dupallocN(fluidmd->fss);
-}
-
-static DerivedMesh * fluidsimModifier_applyModifier(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- int useRenderParams, int isFinalCalc)
-{
- FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
- DerivedMesh *result = NULL;
-
- /* check for alloc failing */
- if(!fluidmd->fss)
- {
- fluidsimModifier_initData(md);
-
- if(!fluidmd->fss)
- return derivedData;
- }
-
- result = fluidsimModifier_do(fluidmd, md->scene, ob, derivedData, useRenderParams, isFinalCalc);
-
- if(result)
- {
- return result;
- }
-
- return derivedData;
-}
-
-static void fluidsimModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene,
- Object *ob, DagNode *obNode)
-{
- FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
- Base *base;
-
- if(fluidmd && fluidmd->fss)
- {
- if(fluidmd->fss->type == OB_FLUIDSIM_DOMAIN)
- {
- for(base = scene->base.first; base; base= base->next)
- {
- Object *ob1= base->object;
- if(ob1 != ob)
- {
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim);
-
- // only put dependancies from NON-DOMAIN fluids in here
- if(fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type!=OB_FLUIDSIM_DOMAIN))
- {
- DagNode *curNode = dag_get_node(forest, ob1);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Fluidsim Object");
- }
- }
- }
- }
- }
-}
-
-static int fluidsimModifier_dependsOnTime(ModifierData *md)
-{
- return 1;
-}
-
-/* MeshDeform */
-
-static void meshdeformModifier_initData(ModifierData *md)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
-
- mmd->gridsize= 5;
-}
-
-static void meshdeformModifier_freeData(ModifierData *md)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
-
- if(mmd->bindweights) MEM_freeN(mmd->bindweights);
- if(mmd->bindcos) MEM_freeN(mmd->bindcos);
- if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
- if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
- if(mmd->dynverts) MEM_freeN(mmd->dynverts);
-}
-
-static void meshdeformModifier_copyData(ModifierData *md, ModifierData *target)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
- MeshDeformModifierData *tmmd = (MeshDeformModifierData*) target;
-
- tmmd->gridsize = mmd->gridsize;
- tmmd->object = mmd->object;
-}
-
-static CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(mmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static int meshdeformModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
-
- return !mmd->object;
-}
-
-static void meshdeformModifier_foreachObjectLink(
- ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
-
- walk(userData, ob, &mmd->object);
-}
-
-static void meshdeformModifier_updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
- DagNode *obNode)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
-
- if (mmd->object) {
- DagNode *curNode = dag_get_node(forest, mmd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA|DAG_RL_OB_DATA|DAG_RL_DATA_OB|DAG_RL_OB_OB,
- "Mesh Deform Modifier");
- }
-}
-
-static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3], float *vec)
-{
- MDefCell *cell;
- MDefInfluence *inf;
- float gridvec[3], dvec[3], ivec[3], co[3], wx, wy, wz;
- float weight, cageweight, totweight, *cageco;
- int i, j, a, x, y, z, size;
-
- co[0]= co[1]= co[2]= 0.0f;
- totweight= 0.0f;
- size= mmd->dyngridsize;
-
- for(i=0; i<3; i++) {
- gridvec[i]= (vec[i] - mmd->dyncellmin[i] - mmd->dyncellwidth*0.5f)/mmd->dyncellwidth;
- ivec[i]= (int)gridvec[i];
- dvec[i]= gridvec[i] - ivec[i];
- }
-
- for(i=0; i<8; i++) {
- if(i & 1) { x= ivec[0]+1; wx= dvec[0]; }
- else { x= ivec[0]; wx= 1.0f-dvec[0]; }
-
- if(i & 2) { y= ivec[1]+1; wy= dvec[1]; }
- else { y= ivec[1]; wy= 1.0f-dvec[1]; }
-
- if(i & 4) { z= ivec[2]+1; wz= dvec[2]; }
- else { z= ivec[2]; wz= 1.0f-dvec[2]; }
-
- CLAMP(x, 0, size-1);
- CLAMP(y, 0, size-1);
- CLAMP(z, 0, size-1);
-
- a= x + y*size + z*size*size;
- weight= wx*wy*wz;
-
- cell= &mmd->dyngrid[a];
- inf= mmd->dyninfluences + cell->offset;
- for(j=0; j<cell->totinfluence; j++, inf++) {
- cageco= dco[inf->vertex];
- cageweight= weight*inf->weight;
- co[0] += cageweight*cageco[0];
- co[1] += cageweight*cageco[1];
- co[2] += cageweight*cageco[2];
- totweight += cageweight;
- }
- }
-
- VECCOPY(vec, co);
-
- return totweight;
-}
-
-static void meshdeformModifier_do(
- ModifierData *md, Object *ob, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
- Mesh *me= (mmd->object)? mmd->object->data: NULL;
- EditMesh *em = (me)? BKE_mesh_get_editmesh(me): NULL;
- DerivedMesh *tmpdm, *cagedm;
- MDeformVert *dvert = NULL;
- MDeformWeight *dw;
- MVert *cagemvert;
- float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
- float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3];
- int a, b, totvert, totcagevert, defgrp_index;
-
- if(!mmd->object || (!mmd->bindcos && !mmd->bindfunc))
- return;
-
- /* get cage derivedmesh */
- if(em) {
- tmpdm= editmesh_get_derived_cage_and_final(md->scene, ob, em, &cagedm, 0);
- if(tmpdm)
- tmpdm->release(tmpdm);
- BKE_mesh_end_editmesh(me, em);
- }
- else
- cagedm= mmd->object->derivedFinal;
-
- /* if we don't have one computed, use derivedmesh from data
- * without any modifiers */
- if(!cagedm) {
- cagedm= get_dm(md->scene, mmd->object, NULL, NULL, NULL, 0);
- if(cagedm)
- cagedm->needsFree= 1;
- }
-
- if(!cagedm)
- return;
-
- /* compute matrices to go in and out of cage object space */
- invert_m4_m4(imat, mmd->object->obmat);
- mul_m4_m4m4(cagemat, ob->obmat, imat);
- mul_m4_m4m4(cmat, cagemat, mmd->bindmat);
- invert_m4_m4(iobmat, cmat);
- copy_m3_m4(icagemat, iobmat);
-
- /* bind weights if needed */
- if(!mmd->bindcos) {
- static int recursive = 0;
-
- /* progress bar redraw can make this recursive .. */
- if(!recursive) {
- recursive = 1;
- mmd->bindfunc(md->scene, dm, mmd, (float*)vertexCos, numVerts, cagemat);
- recursive = 0;
- }
- }
-
- /* verify we have compatible weights */
- totvert= numVerts;
- totcagevert= cagedm->getNumVerts(cagedm);
-
- if(mmd->totvert!=totvert || mmd->totcagevert!=totcagevert || !mmd->bindcos) {
- cagedm->release(cagedm);
- return;
- }
-
- /* setup deformation data */
- cagemvert= cagedm->getVertArray(cagedm);
- weights= mmd->bindweights;
- bindcos= (float(*)[3])mmd->bindcos;
-
- dco= MEM_callocN(sizeof(*dco)*totcagevert, "MDefDco");
- for(a=0; a<totcagevert; a++) {
- /* get cage vertex in world space with binding transform */
- VECCOPY(co, cagemvert[a].co);
-
- if(G.rt != 527) {
- mul_m4_v3(mmd->bindmat, co);
- /* compute difference with world space bind coord */
- VECSUB(dco[a], co, bindcos[a]);
- }
- else
- VECCOPY(dco[a], co)
- }
-
- defgrp_index = defgroup_name_index(ob, mmd->defgrp_name);
-
- if (defgrp_index >= 0)
- dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- /* do deformation */
- fac= 1.0f;
-
- for(b=0; b<totvert; b++) {
- if(mmd->flag & MOD_MDEF_DYNAMIC_BIND)
- if(!mmd->dynverts[b])
- continue;
-
- if(dvert) {
- for(dw=NULL, a=0; a<dvert[b].totweight; a++) {
- if(dvert[b].dw[a].def_nr == defgrp_index) {
- dw = &dvert[b].dw[a];
- break;
- }
- }
-
- if(mmd->flag & MOD_MDEF_INVERT_VGROUP) {
- if(!dw) fac= 1.0f;
- else if(dw->weight == 1.0f) continue;
- else fac=1.0f-dw->weight;
- }
- else {
- if(!dw) continue;
- else fac= dw->weight;
- }
- }
-
- if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
- /* transform coordinate into cage's local space */
- VECCOPY(co, vertexCos[b]);
- mul_m4_v3(cagemat, co);
- totweight= meshdeform_dynamic_bind(mmd, dco, co);
- }
- else {
- totweight= 0.0f;
- co[0]= co[1]= co[2]= 0.0f;
-
- for(a=0; a<totcagevert; a++) {
- weight= weights[a + b*totcagevert];
- co[0]+= weight*dco[a][0];
- co[1]+= weight*dco[a][1];
- co[2]+= weight*dco[a][2];
- totweight += weight;
- }
- }
-
- if(totweight > 0.0f) {
- mul_v3_fl(co, fac/totweight);
- mul_m3_v3(icagemat, co);
- if(G.rt != 527)
- VECADD(vertexCos[b], vertexCos[b], co)
- else
- VECCOPY(vertexCos[b], co)
- }
- }
-
- /* release cage derivedmesh */
- MEM_freeN(dco);
- cagedm->release(cagedm);
-}
-
-static void meshdeformModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm= get_dm(md->scene, ob, NULL, derivedData, NULL, 0);;
-
- if(!dm)
- return;
-
- modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
-
- meshdeformModifier_do(md, ob, dm, vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static void meshdeformModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm;
-
- if(!derivedData && ob->type == OB_MESH)
- dm = CDDM_from_editmesh(editData, ob->data);
- else
- dm = derivedData;
-
- meshdeformModifier_do(md, ob, dm, vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-/* Multires */
-static void multiresModifier_initData(ModifierData *md)
-{
- MultiresModifierData *mmd = (MultiresModifierData*)md;
-
- mmd->lvl = 0;
- mmd->sculptlvl = 0;
- mmd->renderlvl = 0;
- mmd->totlvl = 0;
-}
-
-static void multiresModifier_copyData(ModifierData *md, ModifierData *target)
-{
- MultiresModifierData *mmd = (MultiresModifierData*) md;
- MultiresModifierData *tmmd = (MultiresModifierData*) target;
-
- tmmd->lvl = mmd->lvl;
- tmmd->sculptlvl = mmd->sculptlvl;
- tmmd->renderlvl = mmd->renderlvl;
- tmmd->totlvl = mmd->totlvl;
-}
-
-static DerivedMesh *multiresModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
- int useRenderParams, int isFinalCalc)
-{
- MultiresModifierData *mmd = (MultiresModifierData*)md;
- DerivedMesh *result;
-
- result = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams, isFinalCalc);
-
- if(result == dm)
- return dm;
-
- if(useRenderParams || !isFinalCalc) {
- DerivedMesh *cddm= CDDM_copy(result);
- result->release(result);
- result= cddm;
- }
- else if((ob->mode & OB_MODE_SCULPT) && ob->sculpt) {
- /* would be created on the fly too, just nicer this
- way on first stroke after e.g. switching levels */
- ob->sculpt->pbvh= result->getPBVH(ob, result);
- }
-
- return result;
-}
-
-/* Shrinkwrap */
-
-static void shrinkwrapModifier_initData(ModifierData *md)
-{
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
- smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
- smd->shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR;
- smd->keepDist = 0.0f;
-
- smd->target = NULL;
- smd->auxTarget = NULL;
-}
-
-static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target)
-{
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*)md;
- ShrinkwrapModifierData *tsmd = (ShrinkwrapModifierData*)target;
-
- tsmd->target = smd->target;
- tsmd->auxTarget = smd->auxTarget;
-
- strcpy(tsmd->vgroup_name, smd->vgroup_name);
-
- tsmd->keepDist = smd->keepDist;
- tsmd->shrinkType= smd->shrinkType;
- tsmd->shrinkOpts= smd->shrinkOpts;
- tsmd->projAxis = smd->projAxis;
- tsmd->subsurfLevels = smd->subsurfLevels;
-}
-
-static CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(smd->vgroup_name[0])
- dataMask |= (1 << CD_MDEFORMVERT);
-
- if(smd->shrinkType == MOD_SHRINKWRAP_PROJECT
- && smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL)
- dataMask |= (1 << CD_MVERT);
-
- return dataMask;
-}
-
-static int shrinkwrapModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
- return !smd->target;
-}
-
-
-static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
-{
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
-
- walk(userData, ob, &smd->target);
- walk(userData, ob, &smd->auxTarget);
-}
-
-static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm = derivedData;
- CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md);
-
- /* ensure we get a CDDM with applied vertex coords */
- if(dataMask)
- dm= get_cddm(md->scene, ob, NULL, dm, vertexCos);
-
- shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm = derivedData;
- CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md);
-
- /* ensure we get a CDDM with applied vertex coords */
- if(dataMask)
- dm= get_cddm(md->scene, ob, editData, dm, vertexCos);
-
- shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static void shrinkwrapModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode)
-{
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
-
- if (smd->target)
- dag_add_relation(forest, dag_get_node(forest, smd->target), obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
-
- if (smd->auxTarget)
- dag_add_relation(forest, dag_get_node(forest, smd->auxTarget), obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
-}
-
-/* SimpleDeform */
-static void simpledeformModifier_initData(ModifierData *md)
-{
- SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
-
- smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST;
- smd->axis = 0;
-
- smd->origin = NULL;
- smd->factor = 0.35f;
- smd->limit[0] = 0.0f;
- smd->limit[1] = 1.0f;
-}
-
-static void simpledeformModifier_copyData(ModifierData *md, ModifierData *target)
-{
- SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md;
- SimpleDeformModifierData *tsmd = (SimpleDeformModifierData*)target;
-
- tsmd->mode = smd->mode;
- tsmd->axis = smd->axis;
- tsmd->origin= smd->origin;
- tsmd->factor= smd->factor;
- memcpy(tsmd->limit, smd->limit, sizeof(tsmd->limit));
-}
-
-static CustomDataMask simpledeformModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
- SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if(smd->vgroup_name[0])
- dataMask |= (1 << CD_MDEFORMVERT);
-
- return dataMask;
-}
-
-static void simpledeformModifier_foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
-{
- SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md;
- walk(userData, ob, &smd->origin);
-}
-
-static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode)
-{
- SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md;
-
- if (smd->origin)
- dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier");
-}
-
-static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- DerivedMesh *dm = derivedData;
- CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md);
-
- /* we implement requiredDataMask but thats not really usefull since
- mesh_calc_modifiers pass a NULL derivedData */
- if(dataMask)
- dm= get_dm(md->scene, ob, NULL, dm, NULL, 0);
-
- SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm = derivedData;
- CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md);
-
- /* we implement requiredDataMask but thats not really usefull since
- mesh_calc_modifiers pass a NULL derivedData */
- if(dataMask)
- dm= get_dm(md->scene, ob, editData, dm, NULL, 0);
-
- SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts);
-
- if(dm != derivedData)
- dm->release(dm);
-}
-
-/* Shape Key */
-
-static void shapekeyModifier_deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
- KeyBlock *kb= ob_get_keyblock(ob);
- float (*deformedVerts)[3];
-
- if(kb && kb->totelem == numVerts) {
- deformedVerts= (float(*)[3])do_ob_key(md->scene, ob);
- if(deformedVerts) {
- memcpy(vertexCos, deformedVerts, sizeof(float)*3*numVerts);
- MEM_freeN(deformedVerts);
- }
- }
-}
-
-static void shapekeyModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- Key *key= ob_get_key(ob);
-
- if(key && key->type == KEY_RELATIVE)
- shapekeyModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
-}
-
-static void shapekeyModifier_deformMatricesEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3],
- float (*defMats)[3][3], int numVerts)
-{
- Key *key= ob_get_key(ob);
- KeyBlock *kb= ob_get_keyblock(ob);
- float scale[3][3];
- int a;
-
- if(kb && kb->totelem==numVerts && kb!=key->refkey) {
- scale_m3_fl(scale, kb->curval);
-
- for(a=0; a<numVerts; a++)
- copy_m3_m3(defMats[a], scale);
- }
-}
-
-/***/
-
-static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
-static int typeArrInit = 1;
+#include "MOD_modifiertypes.h"
ModifierTypeInfo *modifierType_getInfo(ModifierType type)
{
- if (typeArrInit) {
- ModifierTypeInfo *mti;
+ static ModifierTypeInfo *types[NUM_MODIFIER_TYPES];
+ static int types_init = 1;
- memset(typeArr, 0, sizeof(typeArr));
+ if (types_init) {
+ memset(types, 0, sizeof(types));
- /* Initialize and return the appropriate type info structure,
- * assumes that modifier has:
- * name == typeName,
- * structName == typeName + 'ModifierData'
- */
#define INIT_TYPE(typeName) \
- (strcpy(typeArr[eModifierType_##typeName].name, #typeName), \
- strcpy(typeArr[eModifierType_##typeName].structName, \
-#typeName "ModifierData"), \
- typeArr[eModifierType_##typeName].structSize = \
- sizeof(typeName##ModifierData), \
- &typeArr[eModifierType_##typeName])
-
- mti = &typeArr[eModifierType_None];
- strcpy(mti->name, "None");
- strcpy(mti->structName, "ModifierData");
- mti->structSize = sizeof(ModifierData);
- mti->type = eModifierType_None;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_AcceptsCVs;
- mti->isDisabled = noneModifier_isDisabled;
-
- mti = INIT_TYPE(Curve);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode;
- mti->initData = curveModifier_initData;
- mti->copyData = curveModifier_copyData;
- mti->requiredDataMask = curveModifier_requiredDataMask;
- mti->isDisabled = curveModifier_isDisabled;
- mti->foreachObjectLink = curveModifier_foreachObjectLink;
- mti->updateDepgraph = curveModifier_updateDepgraph;
- mti->deformVerts = curveModifier_deformVerts;
- mti->deformVertsEM = curveModifier_deformVertsEM;
-
- mti = INIT_TYPE(Lattice);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode;
- mti->copyData = latticeModifier_copyData;
- mti->requiredDataMask = latticeModifier_requiredDataMask;
- mti->isDisabled = latticeModifier_isDisabled;
- mti->foreachObjectLink = latticeModifier_foreachObjectLink;
- mti->updateDepgraph = latticeModifier_updateDepgraph;
- mti->deformVerts = latticeModifier_deformVerts;
- mti->deformVertsEM = latticeModifier_deformVertsEM;
-
- mti = INIT_TYPE(Subsurf);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsMapping
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode
- | eModifierTypeFlag_AcceptsCVs;
- mti->initData = subsurfModifier_initData;
- mti->copyData = subsurfModifier_copyData;
- mti->freeData = subsurfModifier_freeData;
- mti->isDisabled = subsurfModifier_isDisabled;
- mti->applyModifier = subsurfModifier_applyModifier;
- mti->applyModifierEM = subsurfModifier_applyModifierEM;
-
- mti = INIT_TYPE(Build);
- mti->type = eModifierTypeType_Nonconstructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh |
- eModifierTypeFlag_AcceptsCVs;
- mti->initData = buildModifier_initData;
- mti->copyData = buildModifier_copyData;
- mti->dependsOnTime = buildModifier_dependsOnTime;
- mti->applyModifier = buildModifier_applyModifier;
-
- mti = INIT_TYPE(Mask);
- mti->type = eModifierTypeType_Nonconstructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh;
- mti->copyData = maskModifier_copyData;
- mti->requiredDataMask= maskModifier_requiredDataMask;
- mti->foreachObjectLink = maskModifier_foreachObjectLink;
- mti->updateDepgraph = maskModifier_updateDepgraph;
- mti->applyModifier = maskModifier_applyModifier;
-
- mti = INIT_TYPE(Array);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsMapping
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode
- | eModifierTypeFlag_AcceptsCVs;
- mti->initData = arrayModifier_initData;
- mti->copyData = arrayModifier_copyData;
- mti->foreachObjectLink = arrayModifier_foreachObjectLink;
- mti->updateDepgraph = arrayModifier_updateDepgraph;
- mti->applyModifier = arrayModifier_applyModifier;
- mti->applyModifierEM = arrayModifier_applyModifierEM;
-
- mti = INIT_TYPE(Mirror);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsMapping
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode
- | eModifierTypeFlag_AcceptsCVs;
- mti->initData = mirrorModifier_initData;
- mti->copyData = mirrorModifier_copyData;
- mti->foreachObjectLink = mirrorModifier_foreachObjectLink;
- mti->updateDepgraph = mirrorModifier_updateDepgraph;
- mti->applyModifier = mirrorModifier_applyModifier;
- mti->applyModifierEM = mirrorModifier_applyModifierEM;
-
- mti = INIT_TYPE(EdgeSplit);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsMapping
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode;
- mti->initData = edgesplitModifier_initData;
- mti->copyData = edgesplitModifier_copyData;
- mti->applyModifier = edgesplitModifier_applyModifier;
- mti->applyModifierEM = edgesplitModifier_applyModifierEM;
-
- mti = INIT_TYPE(Bevel);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode;
- mti->initData = bevelModifier_initData;
- mti->copyData = bevelModifier_copyData;
- mti->requiredDataMask = bevelModifier_requiredDataMask;
- mti->applyModifier = bevelModifier_applyModifier;
- mti->applyModifierEM = bevelModifier_applyModifierEM;
-
- mti = INIT_TYPE(Displace);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsEditmode;
- mti->initData = displaceModifier_initData;
- mti->copyData = displaceModifier_copyData;
- mti->requiredDataMask = displaceModifier_requiredDataMask;
- mti->dependsOnTime = displaceModifier_dependsOnTime;
- mti->foreachObjectLink = displaceModifier_foreachObjectLink;
- mti->foreachIDLink = displaceModifier_foreachIDLink;
- mti->updateDepgraph = displaceModifier_updateDepgraph;
- mti->isDisabled = displaceModifier_isDisabled;
- mti->deformVerts = displaceModifier_deformVerts;
- mti->deformVertsEM = displaceModifier_deformVertsEM;
-
- mti = INIT_TYPE(UVProject);
- mti->type = eModifierTypeType_Nonconstructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsMapping
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode;
- mti->initData = uvprojectModifier_initData;
- mti->copyData = uvprojectModifier_copyData;
- mti->requiredDataMask = uvprojectModifier_requiredDataMask;
- mti->foreachObjectLink = uvprojectModifier_foreachObjectLink;
- mti->foreachIDLink = uvprojectModifier_foreachIDLink;
- mti->updateDepgraph = uvprojectModifier_updateDepgraph;
- mti->applyModifier = uvprojectModifier_applyModifier;
- mti->applyModifierEM = uvprojectModifier_applyModifierEM;
-
- mti = INIT_TYPE(Decimate);
- mti->type = eModifierTypeType_Nonconstructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh;
- mti->initData = decimateModifier_initData;
- mti->copyData = decimateModifier_copyData;
- mti->applyModifier = decimateModifier_applyModifier;
-
- mti = INIT_TYPE(Smooth);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsEditmode;
- mti->initData = smoothModifier_initData;
- mti->copyData = smoothModifier_copyData;
- mti->requiredDataMask = smoothModifier_requiredDataMask;
- mti->isDisabled = smoothModifier_isDisabled;
- mti->deformVerts = smoothModifier_deformVerts;
- mti->deformVertsEM = smoothModifier_deformVertsEM;
-
- mti = INIT_TYPE(Cast);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode;
- mti->initData = castModifier_initData;
- mti->copyData = castModifier_copyData;
- mti->requiredDataMask = castModifier_requiredDataMask;
- mti->isDisabled = castModifier_isDisabled;
- mti->foreachObjectLink = castModifier_foreachObjectLink;
- mti->updateDepgraph = castModifier_updateDepgraph;
- mti->deformVerts = castModifier_deformVerts;
- mti->deformVertsEM = castModifier_deformVertsEM;
-
- mti = INIT_TYPE(Wave);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode;
- mti->initData = waveModifier_initData;
- mti->copyData = waveModifier_copyData;
- mti->dependsOnTime = waveModifier_dependsOnTime;
- mti->requiredDataMask = waveModifier_requiredDataMask;
- mti->foreachObjectLink = waveModifier_foreachObjectLink;
- mti->foreachIDLink = waveModifier_foreachIDLink;
- mti->updateDepgraph = waveModifier_updateDepgraph;
- mti->deformVerts = waveModifier_deformVerts;
- mti->deformVertsEM = waveModifier_deformVertsEM;
-
- mti = INIT_TYPE(Armature);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode;
- mti->initData = armatureModifier_initData;
- mti->copyData = armatureModifier_copyData;
- mti->requiredDataMask = armatureModifier_requiredDataMask;
- mti->isDisabled = armatureModifier_isDisabled;
- mti->foreachObjectLink = armatureModifier_foreachObjectLink;
- mti->updateDepgraph = armatureModifier_updateDepgraph;
- mti->deformVerts = armatureModifier_deformVerts;
- mti->deformVertsEM = armatureModifier_deformVertsEM;
- mti->deformMatricesEM = armatureModifier_deformMatricesEM;
-
- mti = INIT_TYPE(Hook);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode;
- mti->initData = hookModifier_initData;
- mti->copyData = hookModifier_copyData;
- mti->requiredDataMask = hookModifier_requiredDataMask;
- mti->freeData = hookModifier_freeData;
- mti->isDisabled = hookModifier_isDisabled;
- mti->foreachObjectLink = hookModifier_foreachObjectLink;
- mti->updateDepgraph = hookModifier_updateDepgraph;
- mti->deformVerts = hookModifier_deformVerts;
- mti->deformVertsEM = hookModifier_deformVertsEM;
-
- mti = INIT_TYPE(Softbody);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_RequiresOriginalData
- | eModifierTypeFlag_Single;
- mti->deformVerts = softbodyModifier_deformVerts;
- mti->dependsOnTime = softbodyModifier_dependsOnTime;
-
- mti = INIT_TYPE(Smoke);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->initData = smokeModifier_initData;
- mti->freeData = smokeModifier_freeData;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_UsesPointCache
- | eModifierTypeFlag_Single;
- mti->deformVerts = smokeModifier_deformVerts;
- mti->dependsOnTime = smokeModifier_dependsOnTime;
- mti->updateDepgraph = smokeModifier_updateDepgraph;
-
- mti = INIT_TYPE(Cloth);
- mti->type = eModifierTypeType_Nonconstructive;
- mti->initData = clothModifier_initData;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_UsesPointCache
- | eModifierTypeFlag_Single;
- mti->dependsOnTime = clothModifier_dependsOnTime;
- mti->freeData = clothModifier_freeData;
- mti->requiredDataMask = clothModifier_requiredDataMask;
- mti->copyData = clothModifier_copyData;
- mti->applyModifier = clothModifier_applyModifier;
- mti->updateDepgraph = clothModifier_updateDepgraph;
-
- mti = INIT_TYPE(Collision);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->initData = collisionModifier_initData;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_Single;
- mti->dependsOnTime = collisionModifier_dependsOnTime;
- mti->freeData = collisionModifier_freeData;
- mti->deformVerts = collisionModifier_deformVerts;
- // mti->copyData = collisionModifier_copyData;
-
- mti = INIT_TYPE(Surface);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->initData = surfaceModifier_initData;
- mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_NoUserAdd;
- mti->dependsOnTime = surfaceModifier_dependsOnTime;
- mti->freeData = surfaceModifier_freeData;
- mti->deformVerts = surfaceModifier_deformVerts;
-
- mti = INIT_TYPE(Boolean);
- mti->type = eModifierTypeType_Nonconstructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_UsesPointCache;
- mti->copyData = booleanModifier_copyData;
- mti->isDisabled = booleanModifier_isDisabled;
- mti->applyModifier = booleanModifier_applyModifier;
- mti->foreachObjectLink = booleanModifier_foreachObjectLink;
- mti->updateDepgraph = booleanModifier_updateDepgraph;
- mti->requiredDataMask = booleanModifier_requiredDataMask;
-
- mti = INIT_TYPE(MeshDeform);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode;
- mti->initData = meshdeformModifier_initData;
- mti->freeData = meshdeformModifier_freeData;
- mti->copyData = meshdeformModifier_copyData;
- mti->requiredDataMask = meshdeformModifier_requiredDataMask;
- mti->isDisabled = meshdeformModifier_isDisabled;
- mti->foreachObjectLink = meshdeformModifier_foreachObjectLink;
- mti->updateDepgraph = meshdeformModifier_updateDepgraph;
- mti->deformVerts = meshdeformModifier_deformVerts;
- mti->deformVertsEM = meshdeformModifier_deformVertsEM;
-
- mti = INIT_TYPE(ParticleSystem);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsMapping
- | eModifierTypeFlag_UsesPointCache;
-#if 0
- | eModifierTypeFlag_SupportsEditmode;
- |eModifierTypeFlag_EnableInEditmode;
-#endif
- mti->initData = particleSystemModifier_initData;
- mti->freeData = particleSystemModifier_freeData;
- mti->copyData = particleSystemModifier_copyData;
- mti->deformVerts = particleSystemModifier_deformVerts;
-#if 0
- mti->deformVertsEM = particleSystemModifier_deformVertsEM;
-#endif
- mti->requiredDataMask = particleSystemModifier_requiredDataMask;
-
- mti = INIT_TYPE(ParticleInstance);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsMapping
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode;
- mti->initData = particleInstanceModifier_initData;
- mti->copyData = particleInstanceModifier_copyData;
- mti->dependsOnTime = particleInstanceModifier_dependsOnTime;
- mti->foreachObjectLink = particleInstanceModifier_foreachObjectLink;
- mti->applyModifier = particleInstanceModifier_applyModifier;
- mti->applyModifierEM = particleInstanceModifier_applyModifierEM;
- mti->updateDepgraph = particleInstanceModifier_updateDepgraph;
-
- mti = INIT_TYPE(Explode);
- mti->type = eModifierTypeType_Nonconstructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh;
- mti->initData = explodeModifier_initData;
- mti->freeData = explodeModifier_freeData;
- mti->copyData = explodeModifier_copyData;
- mti->dependsOnTime = explodeModifier_dependsOnTime;
- mti->requiredDataMask = explodeModifier_requiredDataMask;
- mti->applyModifier = explodeModifier_applyModifier;
-
- mti = INIT_TYPE(Fluidsim);
- mti->type = eModifierTypeType_Nonconstructive
- | eModifierTypeFlag_RequiresOriginalData
- | eModifierTypeFlag_Single;
- mti->flags = eModifierTypeFlag_AcceptsMesh;
- mti->initData = fluidsimModifier_initData;
- mti->freeData = fluidsimModifier_freeData;
- mti->copyData = fluidsimModifier_copyData;
- mti->dependsOnTime = fluidsimModifier_dependsOnTime;
- mti->applyModifier = fluidsimModifier_applyModifier;
- mti->updateDepgraph = fluidsimModifier_updateDepgraph;
-
- mti = INIT_TYPE(Shrinkwrap);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode;
- mti->initData = shrinkwrapModifier_initData;
- mti->copyData = shrinkwrapModifier_copyData;
- mti->requiredDataMask = shrinkwrapModifier_requiredDataMask;
- mti->isDisabled = shrinkwrapModifier_isDisabled;
- mti->foreachObjectLink = shrinkwrapModifier_foreachObjectLink;
- mti->deformVerts = shrinkwrapModifier_deformVerts;
- mti->deformVertsEM = shrinkwrapModifier_deformVertsEM;
- mti->updateDepgraph = shrinkwrapModifier_updateDepgraph;
-
- mti = INIT_TYPE(SimpleDeform);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode;
- mti->initData = simpledeformModifier_initData;
- mti->copyData = simpledeformModifier_copyData;
- mti->requiredDataMask = simpledeformModifier_requiredDataMask;
- mti->deformVerts = simpledeformModifier_deformVerts;
- mti->deformVertsEM = simpledeformModifier_deformVertsEM;
- mti->foreachObjectLink = simpledeformModifier_foreachObjectLink;
- mti->updateDepgraph = simpledeformModifier_updateDepgraph;
-
- mti = INIT_TYPE(Multires);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData;
- mti->initData = multiresModifier_initData;
- mti->copyData = multiresModifier_copyData;
- mti->applyModifier = multiresModifier_applyModifier;
-
- mti = INIT_TYPE(ShapeKey);
- mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsEditmode;
- mti->deformVerts = shapekeyModifier_deformVerts;
- mti->deformVertsEM = shapekeyModifier_deformVertsEM;
- mti->deformMatricesEM = shapekeyModifier_deformMatricesEM;
-
- mti = INIT_TYPE(Solidify);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_AcceptsCVs
- | eModifierTypeFlag_SupportsMapping
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode;
- mti->initData = solidifyModifier_initData;
- mti->copyData = solidifyModifier_copyData;
- mti->applyModifier = solidifyModifier_applyModifier;
- mti->applyModifierEM = solidifyModifier_applyModifierEM;
- typeArrInit = 0;
-
- mti = INIT_TYPE(Screw);
- mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh
- | eModifierTypeFlag_SupportsEditmode
- | eModifierTypeFlag_EnableInEditmode
- | eModifierTypeFlag_AcceptsCVs;
-
- mti->initData = screwModifier_initData;
- mti->copyData = screwModifier_copyData;
- mti->foreachObjectLink = screwModifier_foreachObjectLink;
- mti->dependsOnTime = screwModifier_dependsOnTime;
- mti->updateDepgraph = screwModifier_updateDepgraph;
- mti->applyModifier = screwModifier_applyModifier;
- mti->applyModifierEM = screwModifier_applyModifierEM;
+ (types[eModifierType_##typeName] = &modifierType_##typeName)
+
+ INIT_TYPE(None);
+ INIT_TYPE(Curve);
+ INIT_TYPE(Lattice);
+ INIT_TYPE(Subsurf);
+ INIT_TYPE(Build);
+ INIT_TYPE(Array);
+ INIT_TYPE(Mirror);
+ INIT_TYPE(EdgeSplit);
+ INIT_TYPE(Bevel);
+ INIT_TYPE(Displace);
+ INIT_TYPE(UVProject);
+ INIT_TYPE(Decimate);
+ INIT_TYPE(Smooth);
+ INIT_TYPE(Cast);
+ INIT_TYPE(Wave);
+ INIT_TYPE(Armature);
+ INIT_TYPE(Hook);
+ INIT_TYPE(Softbody);
+ INIT_TYPE(Cloth);
+ INIT_TYPE(Collision);
+ INIT_TYPE(Boolean);
+ INIT_TYPE(MeshDeform);
+ INIT_TYPE(ParticleSystem);
+ INIT_TYPE(ParticleInstance);
+ INIT_TYPE(Explode);
+ INIT_TYPE(Cloth);
+ INIT_TYPE(Collision);
+ INIT_TYPE(Bevel);
+ INIT_TYPE(Shrinkwrap);
+ INIT_TYPE(Fluidsim);
+ INIT_TYPE(Mask);
+ INIT_TYPE(SimpleDeform);
+ INIT_TYPE(Multires);
+ INIT_TYPE(Surface);
+ INIT_TYPE(Smoke);
+ INIT_TYPE(ShapeKey);
+ INIT_TYPE(Solidify);
+ INIT_TYPE(Screw);
+
+ types_init = 0;
#undef INIT_TYPE
}
- if (type>=0 && type<NUM_MODIFIER_TYPES && typeArr[type].name[0]!='\0') {
- return &typeArr[type];
- } else {
+ if(type >= 0 && type < NUM_MODIFIER_TYPES &&
+ types[type]->name[0] != '\0') {
+ return types[type];
+ }
+ else {
return NULL;
}
}
diff --git a/source/blender/blenkernel/intern/simple_deform.c b/source/blender/blenkernel/intern/simple_deform.c
deleted file mode 100644
index 8ceb327b63c..00000000000
--- a/source/blender/blenkernel/intern/simple_deform.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/**
- * deform_simple.c
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): André Pinto
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#include "DNA_object_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_meshdata_types.h"
-
-#include "BKE_DerivedMesh.h"
-#include "BKE_lattice.h"
-#include "BKE_deform.h"
-#include "BKE_utildefines.h"
-#include "BLI_math.h"
-#include "BKE_shrinkwrap.h"
-
-#include <string.h>
-#include <math.h>
-
-
-//Clamps/Limits the given coordinate to: limits[0] <= co[axis] <= limits[1]
-//The ammount of clamp is saved on dcut
-static void axis_limit(int axis, const float limits[2], float co[3], float dcut[3])
-{
- float val = co[axis];
- if(limits[0] > val) val = limits[0];
- if(limits[1] < val) val = limits[1];
-
- dcut[axis] = co[axis] - val;
- co[axis] = val;
-}
-
-static void simpleDeform_taper(const float factor, const float dcut[3], float *co)
-{
- float x = co[0], y = co[1], z = co[2];
- float scale = z*factor;
-
- co[0] = x + x*scale;
- co[1] = y + y*scale;
- co[2] = z;
-
- if(dcut)
- {
- co[0] += dcut[0];
- co[1] += dcut[1];
- co[2] += dcut[2];
- }
-}
-
-static void simpleDeform_stretch(const float factor, const float dcut[3], float *co)
-{
- float x = co[0], y = co[1], z = co[2];
- float scale;
-
- scale = (z*z*factor-factor + 1.0);
-
- co[0] = x*scale;
- co[1] = y*scale;
- co[2] = z*(1.0+factor);
-
-
- if(dcut)
- {
- co[0] += dcut[0];
- co[1] += dcut[1];
- co[2] += dcut[2];
- }
-}
-
-static void simpleDeform_twist(const float factor, const float *dcut, float *co)
-{
- float x = co[0], y = co[1], z = co[2];
- float theta, sint, cost;
-
- theta = z*factor;
- sint = sin(theta);
- cost = cos(theta);
-
- co[0] = x*cost - y*sint;
- co[1] = x*sint + y*cost;
- co[2] = z;
-
- if(dcut)
- {
- co[0] += dcut[0];
- co[1] += dcut[1];
- co[2] += dcut[2];
- }
-}
-
-static void simpleDeform_bend(const float factor, const float dcut[3], float *co)
-{
- float x = co[0], y = co[1], z = co[2];
- float theta, sint, cost;
-
- theta = x*factor;
- sint = sin(theta);
- cost = cos(theta);
-
- if(fabs(factor) > 1e-7f)
- {
- co[0] = -(y-1.0f/factor)*sint;
- co[1] = (y-1.0f/factor)*cost + 1.0f/factor;
- co[2] = z;
- }
-
-
- if(dcut)
- {
- co[0] += cost*dcut[0];
- co[1] += sint*dcut[0];
- co[2] += dcut[2];
- }
-
-}
-
-
-/* simple deform modifier */
-void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
-{
- static const float lock_axis[2] = {0.0f, 0.0f};
-
- int i;
- int limit_axis = 0;
- float smd_limit[2], smd_factor;
- SpaceTransform *transf = NULL, tmp_transf;
- void (*simpleDeform_callback)(const float factor, const float dcut[3], float *co) = NULL; //Mode callback
- int vgroup = defgroup_name_index(ob, smd->vgroup_name);
- MDeformVert *dvert = NULL;
-
- //Safe-check
- if(smd->origin == ob) smd->origin = NULL; //No self references
-
- if(smd->limit[0] < 0.0) smd->limit[0] = 0.0f;
- if(smd->limit[0] > 1.0) smd->limit[0] = 1.0f;
-
- smd->limit[0] = MIN2(smd->limit[0], smd->limit[1]); //Upper limit >= than lower limit
-
- //Calculate matrixs do convert between coordinate spaces
- if(smd->origin)
- {
- transf = &tmp_transf;
-
- if(smd->originOpts & MOD_SIMPLEDEFORM_ORIGIN_LOCAL)
- {
- space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat);
- }
- else
- {
- copy_m4_m4(transf->local2target, smd->origin->obmat);
- invert_m4_m4(transf->target2local, transf->local2target);
- }
- }
-
- //Setup vars
- limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; //Bend limits on X.. all other modes limit on Z
-
- //Update limits if needed
- {
- float lower = FLT_MAX;
- float upper = -FLT_MAX;
-
- for(i=0; i<numVerts; i++)
- {
- float tmp[3];
- VECCOPY(tmp, vertexCos[i]);
-
- if(transf) space_transform_apply(transf, tmp);
-
- lower = MIN2(lower, tmp[limit_axis]);
- upper = MAX2(upper, tmp[limit_axis]);
- }
-
-
- //SMD values are normalized to the BV, calculate the absolut values
- smd_limit[1] = lower + (upper-lower)*smd->limit[1];
- smd_limit[0] = lower + (upper-lower)*smd->limit[0];
-
- smd_factor = smd->factor / MAX2(FLT_EPSILON, smd_limit[1]-smd_limit[0]);
- }
-
-
- if(dm)
- {
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
- }
- else if(ob->type == OB_LATTICE)
- {
- dvert = lattice_get_deform_verts(ob);
- }
-
-
-
- switch(smd->mode)
- {
- case MOD_SIMPLEDEFORM_MODE_TWIST: simpleDeform_callback = simpleDeform_twist; break;
- case MOD_SIMPLEDEFORM_MODE_BEND: simpleDeform_callback = simpleDeform_bend; break;
- case MOD_SIMPLEDEFORM_MODE_TAPER: simpleDeform_callback = simpleDeform_taper; break;
- case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch; break;
- default:
- return; //No simpledeform mode?
- }
-
- for(i=0; i<numVerts; i++)
- {
- float weight = defvert_array_find_weight_safe(dvert, i, vgroup);
-
- if(weight != 0.0f)
- {
- float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};
-
- if(transf) space_transform_apply(transf, vertexCos[i]);
-
- VECCOPY(co, vertexCos[i]);
-
- //Apply axis limits
- if(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) //Bend mode shoulnt have any lock axis
- {
- if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut);
- if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut);
- }
- axis_limit(limit_axis, smd_limit, co, dcut);
-
- simpleDeform_callback(smd_factor, dcut, co); //Apply deform
- interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight); //Use vertex weight has coef of linear interpolation
-
- if(transf) space_transform_invert(transf, vertexCos[i]);
- }
- }
-}
-
-
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
new file mode 100644
index 00000000000..95914917efd
--- /dev/null
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -0,0 +1,63 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain
+# Ben Batt
+#
+# ***** END GPL LICENSE BLOCK *****
+
+FILE(GLOB SRC intern/*.c)
+
+SET(INC
+ . ./intern
+ ../../../intern/guardedalloc
+ ../include
+ ../blenlib
+ ../makesdna
+ ../blenkernel
+ ../blenkernel/intern
+ ../render/extern/include
+ ../../../intern/decimation/extern
+ ../../../intern/elbeem/extern
+ ../../../intern/bsp/extern
+ ${ZLIB_INC}
+)
+
+IF(WITH_LZO)
+ SET(INC ${INC} ../../../extern/lzo/minilzo)
+ ADD_DEFINITIONS(-DWITH_LZO)
+ENDIF(WITH_LZO)
+
+IF(WITH_LZMA)
+ SET(INC ${INC} ../../../extern/lzma)
+ ADD_DEFINITIONS(-DWITH_LZMA)
+ENDIF(WITH_LZMA)
+
+IF(WITH_OPENMP)
+ ADD_DEFINITIONS(-DPARALLEL=1)
+ENDIF(WITH_OPENMP)
+
+IF(NOT WITH_ELBEEM)
+ ADD_DEFINITIONS(-DDISABLE_ELBEEM)
+ENDIF(NOT WITH_ELBEEM)
+
+BLENDERLIB(bf_modifiers "${SRC}" "${INC}")
+
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
new file mode 100644
index 00000000000..ee893fb3329
--- /dev/null
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -0,0 +1,71 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful;
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation;
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Ben Batt
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef MOD_MODIFIERTYPES_H
+#define MOD_MODIFIERTYPES_H
+
+#include "BKE_modifier.h"
+
+/* ****************** Type structures for all modifiers ****************** */
+
+extern ModifierTypeInfo modifierType_None;
+extern ModifierTypeInfo modifierType_Subsurf;
+extern ModifierTypeInfo modifierType_Lattice;
+extern ModifierTypeInfo modifierType_Curve;
+extern ModifierTypeInfo modifierType_Build;
+extern ModifierTypeInfo modifierType_Mirror;
+extern ModifierTypeInfo modifierType_Decimate;
+extern ModifierTypeInfo modifierType_Wave;
+extern ModifierTypeInfo modifierType_Armature;
+extern ModifierTypeInfo modifierType_Hook;
+extern ModifierTypeInfo modifierType_Softbody;
+extern ModifierTypeInfo modifierType_Boolean;
+extern ModifierTypeInfo modifierType_Array;
+extern ModifierTypeInfo modifierType_EdgeSplit;
+extern ModifierTypeInfo modifierType_Displace;
+extern ModifierTypeInfo modifierType_UVProject;
+extern ModifierTypeInfo modifierType_Smooth;
+extern ModifierTypeInfo modifierType_Cast;
+extern ModifierTypeInfo modifierType_MeshDeform;
+extern ModifierTypeInfo modifierType_ParticleSystem;
+extern ModifierTypeInfo modifierType_ParticleInstance;
+extern ModifierTypeInfo modifierType_Explode;
+extern ModifierTypeInfo modifierType_Cloth;
+extern ModifierTypeInfo modifierType_Collision;
+extern ModifierTypeInfo modifierType_Bevel;
+extern ModifierTypeInfo modifierType_Shrinkwrap;
+extern ModifierTypeInfo modifierType_Fluidsim;
+extern ModifierTypeInfo modifierType_Mask;
+extern ModifierTypeInfo modifierType_SimpleDeform;
+extern ModifierTypeInfo modifierType_Multires;
+extern ModifierTypeInfo modifierType_Surface;
+extern ModifierTypeInfo modifierType_Smoke;
+extern ModifierTypeInfo modifierType_ShapeKey;
+extern ModifierTypeInfo modifierType_Solidify;
+extern ModifierTypeInfo modifierType_Screw;
+
+#endif //MOD_MODIFIERTYPES_H
diff --git a/source/blender/modifiers/Makefile b/source/blender/modifiers/Makefile
new file mode 100644
index 00000000000..efe6ae4cb1d
--- /dev/null
+++ b/source/blender/modifiers/Makefile
@@ -0,0 +1,34 @@
+#
+# $Id:
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Ben Batt
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/modifiers
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript
new file mode 100644
index 00000000000..ad7f80f0907
--- /dev/null
+++ b/source/blender/modifiers/SConscript
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('intern/*.c')
+
+incs = '. ./intern'
+incs += ' #/intern/guardedalloc #/intern/decimation/extern #/intern/bsp/extern #/intern/elbeem/extern'
+incs += ' ../render/extern/include'
+incs += ' ../include ../blenlib ../makesdna ../blenkernel ../blenkernel/intern'
+
+incs += ' ' + env['BF_ZLIB_INC']
+
+defs = ''
+
+env.BlenderLib ( libname = 'modifiers', sources = sources,
+ includes = Split(incs), defines = Split(defs),
+ libtype=['core','player'], priority = [180, 20] ) \ No newline at end of file
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
new file mode 100644
index 00000000000..f8db316c4ac
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -0,0 +1,219 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "CCGSubSurf.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+/* Armature */
+
+static void initData(ModifierData *md)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+
+ amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+ ArmatureModifierData *tamd = (ArmatureModifierData*) target;
+
+ tamd->object = amd->object;
+ tamd->deformflag = amd->deformflag;
+ strncpy(tamd->defgrp_name, amd->defgrp_name, 32);
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups */
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+
+ return !amd->object;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+
+ walk(userData, ob, &amd->object);
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
+ DagNode *obNode)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+
+ if (amd->object) {
+ DagNode *curNode = dag_get_node(forest, amd->object);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Armature Modifier");
+ }
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+
+ modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
+
+ armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL,
+ numVerts, amd->deformflag,
+ (float(*)[3])amd->prevCos, amd->defgrp_name);
+ /* free cache */
+ if(amd->prevCos) {
+ MEM_freeN(amd->prevCos);
+ amd->prevCos= NULL;
+ }
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts,
+ amd->deformflag, NULL, amd->defgrp_name);
+
+ if(!derivedData) dm->release(dm);
+}
+
+static void deformMatricesEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3],
+ float (*defMats)[3][3], int numVerts)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts,
+ amd->deformflag, NULL, amd->defgrp_name);
+
+ if(!derivedData) dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Armature = {
+ /* name */ "Armature",
+ /* structName */ "ArmatureModifierData",
+ /* structSize */ sizeof(ArmatureModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ deformMatricesEM,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
new file mode 100644
index 00000000000..1d28b424895
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -0,0 +1,813 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+
+#include "MOD_modifiertypes.h"
+
+/* Array */
+/* Array modifier: duplicates the object multiple times along an axis
+*/
+
+static void initData(ModifierData *md)
+{
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ /* default to 2 duplicates distributed along the x-axis by an
+ offset of 1 object-width
+ */
+ amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
+ amd->count = 2;
+ amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
+ amd->scale[0] = 1;
+ amd->scale[1] = amd->scale[2] = 0;
+ amd->length = 0;
+ amd->merge_dist = 0.01;
+ amd->fit_type = MOD_ARR_FIXEDCOUNT;
+ amd->offset_type = MOD_ARR_OFF_RELATIVE;
+ amd->flags = 0;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+ ArrayModifierData *tamd = (ArrayModifierData*) target;
+
+ tamd->start_cap = amd->start_cap;
+ tamd->end_cap = amd->end_cap;
+ tamd->curve_ob = amd->curve_ob;
+ tamd->offset_ob = amd->offset_ob;
+ tamd->count = amd->count;
+ VECCOPY(tamd->offset, amd->offset);
+ VECCOPY(tamd->scale, amd->scale);
+ tamd->length = amd->length;
+ tamd->merge_dist = amd->merge_dist;
+ tamd->fit_type = amd->fit_type;
+ tamd->offset_type = amd->offset_type;
+ tamd->flags = amd->flags;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ walk(userData, ob, &amd->start_cap);
+ walk(userData, ob, &amd->end_cap);
+ walk(userData, ob, &amd->curve_ob);
+ walk(userData, ob, &amd->offset_ob);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ if (amd->start_cap) {
+ DagNode *curNode = dag_get_node(forest, amd->start_cap);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
+ }
+ if (amd->end_cap) {
+ DagNode *curNode = dag_get_node(forest, amd->end_cap);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
+ }
+ if (amd->curve_ob) {
+ DagNode *curNode = dag_get_node(forest, amd->curve_ob);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
+ }
+ if (amd->offset_ob) {
+ DagNode *curNode = dag_get_node(forest, amd->offset_ob);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
+ }
+}
+
+static float vertarray_size(MVert *mvert, int numVerts, int axis)
+{
+ int i;
+ float min_co, max_co;
+
+ /* if there are no vertices, width is 0 */
+ if(numVerts == 0) return 0;
+
+ /* find the minimum and maximum coordinates on the desired axis */
+ min_co = max_co = mvert->co[axis];
+ ++mvert;
+ for(i = 1; i < numVerts; ++i, ++mvert) {
+ if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
+ if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
+ }
+
+ return max_co - min_co;
+}
+
+typedef struct IndexMapEntry {
+ /* the new vert index that this old vert index maps to */
+ int new;
+ /* -1 if this vert isn't merged, otherwise the old vert index it
+ * should be replaced with
+ */
+ int merge;
+ /* 1 if this vert's first copy is merged with the last copy of its
+ * merge target, otherwise 0
+ */
+ short merge_final;
+} IndexMapEntry;
+
+/* indexMap - an array of IndexMap entries
+ * oldIndex - the old index to map
+ * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
+ */
+static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
+{
+ if(indexMap[oldIndex].merge < 0) {
+ /* vert wasn't merged, so use copy of this vert */
+ return indexMap[oldIndex].new + copyNum;
+ } else if(indexMap[oldIndex].merge == oldIndex) {
+ /* vert was merged with itself */
+ return indexMap[oldIndex].new;
+ } else {
+ /* vert was merged with another vert */
+ /* follow the chain of merges to the end, or until we've passed
+ * a number of vertices equal to the copy number
+ */
+ if(copyNum <= 0)
+ return indexMap[oldIndex].new;
+ else
+ return calc_mapping(indexMap, indexMap[oldIndex].merge,
+ copyNum - 1);
+ }
+}
+
+static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
+ Scene *scene, Object *ob, DerivedMesh *dm,
+ int initFlags)
+{
+ int i, j;
+ /* offset matrix */
+ float offset[4][4];
+ float final_offset[4][4];
+ float tmp_mat[4][4];
+ float length = amd->length;
+ int count = amd->count;
+ int numVerts, numEdges, numFaces;
+ int maxVerts, maxEdges, maxFaces;
+ int finalVerts, finalEdges, finalFaces;
+ DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
+ MVert *mvert, *src_mvert;
+ MEdge *medge;
+ MFace *mface;
+
+ IndexMapEntry *indexMap;
+
+ EdgeHash *edges;
+
+ /* need to avoid infinite recursion here */
+ if(amd->start_cap && amd->start_cap != ob)
+ start_cap = amd->start_cap->derivedFinal;
+ if(amd->end_cap && amd->end_cap != ob)
+ end_cap = amd->end_cap->derivedFinal;
+
+ unit_m4(offset);
+
+ indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
+ "indexmap");
+
+ src_mvert = dm->getVertArray(dm);
+
+ maxVerts = dm->getNumVerts(dm);
+
+ if(amd->offset_type & MOD_ARR_OFF_CONST)
+ add_v3_v3v3(offset[3], offset[3], amd->offset);
+ if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
+ for(j = 0; j < 3; j++)
+ offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
+ maxVerts, j);
+ }
+
+ if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
+ float obinv[4][4];
+ float result_mat[4][4];
+
+ if(ob)
+ invert_m4_m4(obinv, ob->obmat);
+ else
+ unit_m4(obinv);
+
+ mul_serie_m4(result_mat, offset,
+ obinv, amd->offset_ob->obmat,
+ NULL, NULL, NULL, NULL, NULL);
+ copy_m4_m4(offset, result_mat);
+ }
+
+ if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
+ Curve *cu = amd->curve_ob->data;
+ if(cu) {
+ float tmp_mat[3][3];
+ float scale;
+
+ object_to_mat3(amd->curve_ob, tmp_mat);
+ scale = mat3_to_scale(tmp_mat);
+
+ if(!cu->path) {
+ cu->flag |= CU_PATH; // needed for path & bevlist
+ makeDispListCurveTypes(scene, amd->curve_ob, 0);
+ }
+ if(cu->path)
+ length = scale*cu->path->totdist;
+ }
+ }
+
+ /* calculate the maximum number of copies which will fit within the
+ prescribed length */
+ if(amd->fit_type == MOD_ARR_FITLENGTH
+ || amd->fit_type == MOD_ARR_FITCURVE) {
+ float dist = sqrt(dot_v3v3(offset[3], offset[3]));
+
+ if(dist > 1e-6f)
+ /* this gives length = first copy start to last copy end
+ add a tiny offset for floating point rounding errors */
+ count = (length + 1e-6f) / dist;
+ else
+ /* if the offset has no translation, just make one copy */
+ count = 1;
+ }
+
+ if(count < 1)
+ count = 1;
+
+ /* allocate memory for count duplicates (including original) plus
+ * start and end caps
+ */
+ finalVerts = dm->getNumVerts(dm) * count;
+ finalEdges = dm->getNumEdges(dm) * count;
+ finalFaces = dm->getNumFaces(dm) * count;
+ if(start_cap) {
+ finalVerts += start_cap->getNumVerts(start_cap);
+ finalEdges += start_cap->getNumEdges(start_cap);
+ finalFaces += start_cap->getNumFaces(start_cap);
+ }
+ if(end_cap) {
+ finalVerts += end_cap->getNumVerts(end_cap);
+ finalEdges += end_cap->getNumEdges(end_cap);
+ finalFaces += end_cap->getNumFaces(end_cap);
+ }
+ result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
+
+ /* calculate the offset matrix of the final copy (for merging) */
+ unit_m4(final_offset);
+
+ for(j=0; j < count - 1; j++) {
+ mul_m4_m4m4(tmp_mat, final_offset, offset);
+ copy_m4_m4(final_offset, tmp_mat);
+ }
+
+ numVerts = numEdges = numFaces = 0;
+ mvert = CDDM_get_verts(result);
+
+ for (i = 0; i < maxVerts; i++) {
+ indexMap[i].merge = -1; /* default to no merge */
+ indexMap[i].merge_final = 0; /* default to no merge */
+ }
+
+ for (i = 0; i < maxVerts; i++) {
+ MVert *inMV;
+ MVert *mv = &mvert[numVerts];
+ MVert *mv2;
+ float co[3];
+
+ inMV = &src_mvert[i];
+
+ DM_copy_vert_data(dm, result, i, numVerts, 1);
+ *mv = *inMV;
+ numVerts++;
+
+ indexMap[i].new = numVerts - 1;
+
+ VECCOPY(co, mv->co);
+
+ /* Attempts to merge verts from one duplicate with verts from the
+ * next duplicate which are closer than amd->merge_dist.
+ * Only the first such vert pair is merged.
+ * If verts are merged in the first duplicate pair, they are merged
+ * in all pairs.
+ */
+ if((count > 1) && (amd->flags & MOD_ARR_MERGE)) {
+ float tmp_co[3];
+ VECCOPY(tmp_co, mv->co);
+ mul_m4_v3(offset, tmp_co);
+
+ for(j = 0; j < maxVerts; j++) {
+ /* if vertex already merged, don't use it */
+ if( indexMap[j].merge != -1 ) continue;
+
+ inMV = &src_mvert[j];
+ /* if this vert is within merge limit, merge */
+ if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist)) {
+ indexMap[i].merge = j;
+
+ /* test for merging with final copy of merge target */
+ if(amd->flags & MOD_ARR_MERGEFINAL) {
+ VECCOPY(tmp_co, inMV->co);
+ inMV = &src_mvert[i];
+ mul_m4_v3(final_offset, tmp_co);
+ if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist))
+ indexMap[i].merge_final = 1;
+ }
+ break;
+ }
+ }
+ }
+
+ /* if no merging, generate copies of this vert */
+ if(indexMap[i].merge < 0) {
+ for(j=0; j < count - 1; j++) {
+ mv2 = &mvert[numVerts];
+
+ DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
+ *mv2 = *mv;
+ numVerts++;
+
+ mul_m4_v3(offset, co);
+ VECCOPY(mv2->co, co);
+ }
+ } else if(indexMap[i].merge != i && indexMap[i].merge_final) {
+ /* if this vert is not merging with itself, and it is merging
+ * with the final copy of its merge target, remove the first copy
+ */
+ numVerts--;
+ DM_free_vert_data(result, numVerts, 1);
+ }
+ }
+
+ /* make a hashtable so we can avoid duplicate edges from merging */
+ edges = BLI_edgehash_new();
+
+ maxEdges = dm->getNumEdges(dm);
+ medge = CDDM_get_edges(result);
+ for(i = 0; i < maxEdges; i++) {
+ MEdge inMED;
+ MEdge med;
+ MEdge *med2;
+ int vert1, vert2;
+
+ dm->getEdge(dm, i, &inMED);
+
+ med = inMED;
+ med.v1 = indexMap[inMED.v1].new;
+ med.v2 = indexMap[inMED.v2].new;
+
+ /* if vertices are to be merged with the final copies of their
+ * merge targets, calculate that final copy
+ */
+ if(indexMap[inMED.v1].merge_final) {
+ med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
+ count - 1);
+ }
+ if(indexMap[inMED.v2].merge_final) {
+ med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
+ count - 1);
+ }
+
+ if(med.v1 == med.v2) continue;
+
+ if (initFlags) {
+ med.flag |= ME_EDGEDRAW | ME_EDGERENDER;
+ }
+
+ if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) {
+ DM_copy_edge_data(dm, result, i, numEdges, 1);
+ medge[numEdges] = med;
+ numEdges++;
+
+ BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
+ }
+
+ for(j = 1; j < count; j++)
+ {
+ vert1 = calc_mapping(indexMap, inMED.v1, j);
+ vert2 = calc_mapping(indexMap, inMED.v2, j);
+ /* avoid duplicate edges */
+ if(!BLI_edgehash_haskey(edges, vert1, vert2)) {
+ med2 = &medge[numEdges];
+
+ DM_copy_edge_data(dm, result, i, numEdges, 1);
+ *med2 = med;
+ numEdges++;
+
+ med2->v1 = vert1;
+ med2->v2 = vert2;
+
+ BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL);
+ }
+ }
+ }
+
+ maxFaces = dm->getNumFaces(dm);
+ mface = CDDM_get_faces(result);
+ for (i=0; i < maxFaces; i++) {
+ MFace inMF;
+ MFace *mf = &mface[numFaces];
+
+ dm->getFace(dm, i, &inMF);
+
+ DM_copy_face_data(dm, result, i, numFaces, 1);
+ *mf = inMF;
+
+ mf->v1 = indexMap[inMF.v1].new;
+ mf->v2 = indexMap[inMF.v2].new;
+ mf->v3 = indexMap[inMF.v3].new;
+ if(inMF.v4)
+ mf->v4 = indexMap[inMF.v4].new;
+
+ /* if vertices are to be merged with the final copies of their
+ * merge targets, calculate that final copy
+ */
+ if(indexMap[inMF.v1].merge_final)
+ mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
+ if(indexMap[inMF.v2].merge_final)
+ mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
+ if(indexMap[inMF.v3].merge_final)
+ mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
+ if(inMF.v4 && indexMap[inMF.v4].merge_final)
+ mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
+
+ if(test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3) < 3)
+ continue;
+
+ numFaces++;
+
+ /* if the face has fewer than 3 vertices, don't create it */
+ if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) {
+ numFaces--;
+ DM_free_face_data(result, numFaces, 1);
+ }
+
+ for(j = 1; j < count; j++)
+ {
+ MFace *mf2 = &mface[numFaces];
+
+ DM_copy_face_data(dm, result, i, numFaces, 1);
+ *mf2 = *mf;
+
+ mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
+ mf2->v2 = calc_mapping(indexMap, inMF.v2, j);
+ mf2->v3 = calc_mapping(indexMap, inMF.v3, j);
+ if (inMF.v4)
+ mf2->v4 = calc_mapping(indexMap, inMF.v4, j);
+
+ test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
+ numFaces++;
+
+ /* if the face has fewer than 3 vertices, don't create it */
+ if(mf2->v3 == 0 || (mf2->v1 && (mf2->v1 == mf2->v3 || mf2->v1 ==
+ mf2->v4))) {
+ numFaces--;
+ DM_free_face_data(result, numFaces, 1);
+ }
+ }
+ }
+
+ /* add start and end caps */
+ if(start_cap) {
+ float startoffset[4][4];
+ MVert *cap_mvert;
+ MEdge *cap_medge;
+ MFace *cap_mface;
+ int *origindex;
+ int *vert_map;
+ int capVerts, capEdges, capFaces;
+
+ capVerts = start_cap->getNumVerts(start_cap);
+ capEdges = start_cap->getNumEdges(start_cap);
+ capFaces = start_cap->getNumFaces(start_cap);
+ cap_mvert = start_cap->getVertArray(start_cap);
+ cap_medge = start_cap->getEdgeArray(start_cap);
+ cap_mface = start_cap->getFaceArray(start_cap);
+
+ invert_m4_m4(startoffset, offset);
+
+ vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
+ "arrayModifier_doArray vert_map");
+
+ origindex = result->getVertDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capVerts; i++) {
+ MVert *mv = &cap_mvert[i];
+ short merged = 0;
+
+ if(amd->flags & MOD_ARR_MERGE) {
+ float tmp_co[3];
+ MVert *in_mv;
+ int j;
+
+ VECCOPY(tmp_co, mv->co);
+ mul_m4_v3(startoffset, tmp_co);
+
+ for(j = 0; j < maxVerts; j++) {
+ in_mv = &src_mvert[j];
+ /* if this vert is within merge limit, merge */
+ if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
+ vert_map[i] = calc_mapping(indexMap, j, 0);
+ merged = 1;
+ break;
+ }
+ }
+ }
+
+ if(!merged) {
+ DM_copy_vert_data(start_cap, result, i, numVerts, 1);
+ mvert[numVerts] = *mv;
+ mul_m4_v3(startoffset, mvert[numVerts].co);
+ origindex[numVerts] = ORIGINDEX_NONE;
+
+ vert_map[i] = numVerts;
+
+ numVerts++;
+ }
+ }
+ origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capEdges; i++) {
+ int v1, v2;
+
+ v1 = vert_map[cap_medge[i].v1];
+ v2 = vert_map[cap_medge[i].v2];
+
+ if(!BLI_edgehash_haskey(edges, v1, v2)) {
+ DM_copy_edge_data(start_cap, result, i, numEdges, 1);
+ medge[numEdges] = cap_medge[i];
+ medge[numEdges].v1 = v1;
+ medge[numEdges].v2 = v2;
+ origindex[numEdges] = ORIGINDEX_NONE;
+
+ numEdges++;
+ }
+ }
+ origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capFaces; i++) {
+ DM_copy_face_data(start_cap, result, i, numFaces, 1);
+ mface[numFaces] = cap_mface[i];
+ mface[numFaces].v1 = vert_map[mface[numFaces].v1];
+ mface[numFaces].v2 = vert_map[mface[numFaces].v2];
+ mface[numFaces].v3 = vert_map[mface[numFaces].v3];
+ if(mface[numFaces].v4) {
+ mface[numFaces].v4 = vert_map[mface[numFaces].v4];
+
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 4);
+ }
+ else
+ {
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 3);
+ }
+
+ origindex[numFaces] = ORIGINDEX_NONE;
+
+ numFaces++;
+ }
+
+ MEM_freeN(vert_map);
+ start_cap->release(start_cap);
+ }
+
+ if(end_cap) {
+ float endoffset[4][4];
+ MVert *cap_mvert;
+ MEdge *cap_medge;
+ MFace *cap_mface;
+ int *origindex;
+ int *vert_map;
+ int capVerts, capEdges, capFaces;
+
+ capVerts = end_cap->getNumVerts(end_cap);
+ capEdges = end_cap->getNumEdges(end_cap);
+ capFaces = end_cap->getNumFaces(end_cap);
+ cap_mvert = end_cap->getVertArray(end_cap);
+ cap_medge = end_cap->getEdgeArray(end_cap);
+ cap_mface = end_cap->getFaceArray(end_cap);
+
+ mul_m4_m4m4(endoffset, final_offset, offset);
+
+ vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
+ "arrayModifier_doArray vert_map");
+
+ origindex = result->getVertDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capVerts; i++) {
+ MVert *mv = &cap_mvert[i];
+ short merged = 0;
+
+ if(amd->flags & MOD_ARR_MERGE) {
+ float tmp_co[3];
+ MVert *in_mv;
+ int j;
+
+ VECCOPY(tmp_co, mv->co);
+ mul_m4_v3(offset, tmp_co);
+
+ for(j = 0; j < maxVerts; j++) {
+ in_mv = &src_mvert[j];
+ /* if this vert is within merge limit, merge */
+ if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
+ vert_map[i] = calc_mapping(indexMap, j, count - 1);
+ merged = 1;
+ break;
+ }
+ }
+ }
+
+ if(!merged) {
+ DM_copy_vert_data(end_cap, result, i, numVerts, 1);
+ mvert[numVerts] = *mv;
+ mul_m4_v3(endoffset, mvert[numVerts].co);
+ origindex[numVerts] = ORIGINDEX_NONE;
+
+ vert_map[i] = numVerts;
+
+ numVerts++;
+ }
+ }
+ origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capEdges; i++) {
+ int v1, v2;
+
+ v1 = vert_map[cap_medge[i].v1];
+ v2 = vert_map[cap_medge[i].v2];
+
+ if(!BLI_edgehash_haskey(edges, v1, v2)) {
+ DM_copy_edge_data(end_cap, result, i, numEdges, 1);
+ medge[numEdges] = cap_medge[i];
+ medge[numEdges].v1 = v1;
+ medge[numEdges].v2 = v2;
+ origindex[numEdges] = ORIGINDEX_NONE;
+
+ numEdges++;
+ }
+ }
+ origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capFaces; i++) {
+ DM_copy_face_data(end_cap, result, i, numFaces, 1);
+ mface[numFaces] = cap_mface[i];
+ mface[numFaces].v1 = vert_map[mface[numFaces].v1];
+ mface[numFaces].v2 = vert_map[mface[numFaces].v2];
+ mface[numFaces].v3 = vert_map[mface[numFaces].v3];
+ if(mface[numFaces].v4) {
+ mface[numFaces].v4 = vert_map[mface[numFaces].v4];
+
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 4);
+ }
+ else
+ {
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 3);
+ }
+ origindex[numFaces] = ORIGINDEX_NONE;
+
+ numFaces++;
+ }
+
+ MEM_freeN(vert_map);
+ end_cap->release(end_cap);
+ }
+
+ BLI_edgehash_free(edges, NULL);
+ MEM_freeN(indexMap);
+
+ CDDM_lower_num_verts(result, numVerts);
+ CDDM_lower_num_edges(result, numEdges);
+ CDDM_lower_num_faces(result, numFaces);
+
+ return result;
+}
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ result = arrayModifier_doArray(amd, md->scene, ob, derivedData, 0);
+
+ if(result != derivedData)
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+
+ModifierTypeInfo modifierType_Array = {
+ /* name */ "Array",
+ /* structName */ "ArrayModifierData",
+ /* structSize */ sizeof(ArrayModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode
+ | eModifierTypeFlag_AcceptsCVs,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
new file mode 100644
index 00000000000..361708ceaca
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -0,0 +1,184 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "MOD_modifiertypes.h"
+
+static void initData(ModifierData *md)
+{
+ BevelModifierData *bmd = (BevelModifierData*) md;
+
+ bmd->value = 0.1f;
+ bmd->res = 1;
+ bmd->flags = 0;
+ bmd->val_flags = 0;
+ bmd->lim_flags = 0;
+ bmd->e_flags = 0;
+ bmd->bevel_angle = 30;
+ bmd->defgrp_name[0] = '\0';
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ BevelModifierData *bmd = (BevelModifierData*) md;
+ BevelModifierData *tbmd = (BevelModifierData*) target;
+
+ tbmd->value = bmd->value;
+ tbmd->res = bmd->res;
+ tbmd->flags = bmd->flags;
+ tbmd->val_flags = bmd->val_flags;
+ tbmd->lim_flags = bmd->lim_flags;
+ tbmd->e_flags = bmd->e_flags;
+ tbmd->bevel_angle = bmd->bevel_angle;
+ strncpy(tbmd->defgrp_name, bmd->defgrp_name, 32);
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ BevelModifierData *bmd = (BevelModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(bmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ BME_Mesh *bm;
+
+ /*bDeformGroup *def;*/
+ int /*i,*/ options, defgrp_index = -1;
+ BevelModifierData *bmd = (BevelModifierData*) md;
+
+ options = bmd->flags|bmd->val_flags|bmd->lim_flags|bmd->e_flags;
+
+ /*if ((options & BME_BEVEL_VWEIGHT) && bmd->defgrp_name[0]) {
+ defgrp_index = defgroup_name_index(ob, bmd->defgrp_name);
+ if (defgrp_index < 0) {
+ options &= ~BME_BEVEL_VWEIGHT;
+ }
+ }*/
+
+ bm = BME_derivedmesh_to_bmesh(derivedData);
+ BME_bevel(bm,bmd->value,bmd->res,options,defgrp_index,bmd->bevel_angle,NULL);
+ result = BME_bmesh_to_derivedmesh(bm,derivedData);
+ BME_free_mesh(bm);
+
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+
+ModifierTypeInfo modifierType_Bevel = {
+ /* name */ "Bevel",
+ /* structName */ "BevelModifierData",
+ /* structSize */ sizeof(BevelModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
new file mode 100644
index 00000000000..f96df0c5c38
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -0,0 +1,182 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_boolean_util.h"
+
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ BooleanModifierData *bmd = (BooleanModifierData*) md;
+ BooleanModifierData *tbmd = (BooleanModifierData*) target;
+
+ tbmd->object = bmd->object;
+ tbmd->operation = bmd->operation;
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ BooleanModifierData *bmd = (BooleanModifierData*) md;
+
+ return !bmd->object;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ BooleanModifierData *bmd = (BooleanModifierData*) md;
+
+ walk(userData, ob, &bmd->object);
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
+ DagNode *obNode)
+{
+ BooleanModifierData *bmd = (BooleanModifierData*) md;
+
+ if(bmd->object) {
+ DagNode *curNode = dag_get_node(forest, bmd->object);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Boolean Modifier");
+ }
+}
+
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ BooleanModifierData *bmd = (BooleanModifierData*) md;
+ DerivedMesh *dm = bmd->object->derivedFinal;
+
+ /* we do a quick sanity check */
+ if(dm && (derivedData->getNumFaces(derivedData) > 3)
+ && bmd->object && dm->getNumFaces(dm) > 3) {
+ DerivedMesh *result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
+ 1 + bmd->operation);
+
+ /* if new mesh returned, return it; otherwise there was
+ * an error, so delete the modifier object */
+ if(result)
+ return result;
+ else
+ modifier_setError(md, "Can't execute boolean operation.");
+ }
+
+ return derivedData;
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE);
+
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+
+ModifierTypeInfo modifierType_Boolean = {
+ /* name */ "Boolean",
+ /* structName */ "BooleanModifierData",
+ /* structSize */ sizeof(BooleanModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_UsesPointCache,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ 0,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
new file mode 100644
index 00000000000..3f46eb327d6
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_boolean_util.c
@@ -0,0 +1,594 @@
+/**
+ * $Id: booleanops.c 27655 2010-03-22 09:30:00Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * CSG operations.
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_ghash.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "CSG_BooleanOps.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_depsgraph.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+
+
+
+/**
+ * Here's the vertex iterator structure used to walk through
+ * the blender vertex structure.
+ */
+
+typedef struct {
+ DerivedMesh *dm;
+ Object *ob;
+ int pos;
+} VertexIt;
+
+/**
+ * Implementations of local vertex iterator functions.
+ * These describe a blender mesh to the CSG module.
+ */
+
+static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator)
+{
+ if (iterator->it) {
+ // deallocate memory for iterator
+ MEM_freeN(iterator->it);
+ iterator->it = 0;
+ }
+ iterator->Done = NULL;
+ iterator->Fill = NULL;
+ iterator->Reset = NULL;
+ iterator->Step = NULL;
+ iterator->num_elements = 0;
+
+}
+
+static int VertexIt_Done(CSG_IteratorPtr it)
+{
+ VertexIt * iterator = (VertexIt *)it;
+ return(iterator->pos >= iterator->dm->getNumVerts(iterator->dm));
+}
+
+static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert)
+{
+ VertexIt * iterator = (VertexIt *)it;
+ MVert *verts = iterator->dm->getVertArray(iterator->dm);
+
+ float global_pos[3];
+
+ /* boolean happens in global space, transform both with obmat */
+ mul_v3_m4v3(
+ global_pos,
+ iterator->ob->obmat,
+ verts[iterator->pos].co
+ );
+
+ vert->position[0] = global_pos[0];
+ vert->position[1] = global_pos[1];
+ vert->position[2] = global_pos[2];
+}
+
+static void VertexIt_Step(CSG_IteratorPtr it)
+{
+ VertexIt * iterator = (VertexIt *)it;
+ iterator->pos ++;
+}
+
+static void VertexIt_Reset(CSG_IteratorPtr it)
+{
+ VertexIt * iterator = (VertexIt *)it;
+ iterator->pos = 0;
+}
+
+static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh *dm, Object *ob)
+{
+
+ VertexIt *it;
+ if (output == 0) return;
+
+ // allocate some memory for blender iterator
+ it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt"));
+ if (it == 0) {
+ return;
+ }
+ // assign blender specific variables
+ it->dm = dm;
+ it->ob = ob; // needed for obmat transformations
+
+ it->pos = 0;
+
+ // assign iterator function pointers.
+ output->Step = VertexIt_Step;
+ output->Fill = VertexIt_Fill;
+ output->Done = VertexIt_Done;
+ output->Reset = VertexIt_Reset;
+ output->num_elements = it->dm->getNumVerts(it->dm);
+ output->it = it;
+}
+
+/**
+ * Blender Face iterator
+ */
+
+typedef struct {
+ DerivedMesh *dm;
+ int pos;
+ int offset;
+ int flip;
+} FaceIt;
+
+static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator)
+{
+ MEM_freeN(iterator->it);
+ iterator->Done = NULL;
+ iterator->Fill = NULL;
+ iterator->Reset = NULL;
+ iterator->Step = NULL;
+ iterator->num_elements = 0;
+}
+
+static int FaceIt_Done(CSG_IteratorPtr it)
+{
+ // assume CSG_IteratorPtr is of the correct type.
+ FaceIt * iterator = (FaceIt *)it;
+ return(iterator->pos >= iterator->dm->getNumFaces(iterator->dm));
+}
+
+static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face)
+{
+ // assume CSG_IteratorPtr is of the correct type.
+ FaceIt *face_it = (FaceIt *)it;
+ MFace *mfaces = face_it->dm->getFaceArray(face_it->dm);
+ MFace *mface = &mfaces[face_it->pos];
+
+ /* reverse face vertices if necessary */
+ face->vertex_index[1] = mface->v2;
+ if( face_it->flip == 0 ) {
+ face->vertex_index[0] = mface->v1;
+ face->vertex_index[2] = mface->v3;
+ } else {
+ face->vertex_index[2] = mface->v1;
+ face->vertex_index[0] = mface->v3;
+ }
+ if (mface->v4) {
+ face->vertex_index[3] = mface->v4;
+ face->vertex_number = 4;
+ } else {
+ face->vertex_number = 3;
+ }
+
+ face->orig_face = face_it->offset + face_it->pos;
+}
+
+static void FaceIt_Step(CSG_IteratorPtr it)
+{
+ FaceIt * face_it = (FaceIt *)it;
+ face_it->pos ++;
+}
+
+static void FaceIt_Reset(CSG_IteratorPtr it)
+{
+ FaceIt * face_it = (FaceIt *)it;
+ face_it->pos = 0;
+}
+
+static void FaceIt_Construct(
+ CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset, Object *ob)
+{
+ FaceIt *it;
+ if (output == 0) return;
+
+ // allocate some memory for blender iterator
+ it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt"));
+ if (it == 0) {
+ return ;
+ }
+ // assign blender specific variables
+ it->dm = dm;
+ it->offset = offset;
+ it->pos = 0;
+
+ /* determine if we will need to reverse order of face vertices */
+ if (ob->size[0] < 0.0f) {
+ if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) {
+ it->flip = 1;
+ } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) {
+ it->flip = 1;
+ } else {
+ it->flip = 0;
+ }
+ } else {
+ if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) {
+ it->flip = 0;
+ } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) {
+ it->flip = 0;
+ } else {
+ it->flip = 1;
+ }
+ }
+
+ // assign iterator function pointers.
+ output->Step = FaceIt_Step;
+ output->Fill = FaceIt_Fill;
+ output->Done = FaceIt_Done;
+ output->Reset = FaceIt_Reset;
+ output->num_elements = it->dm->getNumFaces(it->dm);
+ output->it = it;
+}
+
+static Object *AddNewBlenderMesh(Scene *scene, Base *base)
+{
+ // This little function adds a new mesh object to the blender object list
+ // It uses ob to duplicate data as this seems to be easier than creating
+ // a new one. This new oject contains no faces nor vertices.
+ Mesh *old_me;
+ Base *basen;
+ Object *ob_new;
+
+ // now create a new blender object.
+ // duplicating all the settings from the previous object
+ // to the new one.
+ ob_new= copy_object(base->object);
+
+ // Ok we don't want to use the actual data from the
+ // last object, the above function incremented the
+ // number of users, so decrement it here.
+ old_me= ob_new->data;
+ old_me->id.us--;
+
+ // Now create a new base to add into the linked list of
+ // vase objects.
+
+ basen= MEM_mallocN(sizeof(Base), "duplibase");
+ *basen= *base;
+ BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */
+ basen->object= ob_new;
+ basen->flag &= ~SELECT;
+
+ // Initialize the mesh data associated with this object.
+ ob_new->data= add_mesh("Mesh");
+
+ // Finally assign the object type.
+ ob_new->type= OB_MESH;
+
+ return ob_new;
+}
+
+static void InterpCSGFace(
+ DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr,
+ float mapmat[][4])
+{
+ float obco[3], *co[4], *orig_co[4], w[4][4];
+ MFace *mface, *orig_mface;
+ int j;
+
+ mface = CDDM_get_face(dm, index);
+ orig_mface = orig_dm->getFaceArray(orig_dm) + orig_index;
+
+ // get the vertex coordinates from the original mesh
+ orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co;
+ orig_co[1] = (orig_dm->getVertArray(orig_dm) + orig_mface->v2)->co;
+ orig_co[2] = (orig_dm->getVertArray(orig_dm) + orig_mface->v3)->co;
+ orig_co[3] = (orig_mface->v4)? (orig_dm->getVertArray(orig_dm) + orig_mface->v4)->co: NULL;
+
+ // get the vertex coordinates from the new derivedmesh
+ co[0] = CDDM_get_vert(dm, mface->v1)->co;
+ co[1] = CDDM_get_vert(dm, mface->v2)->co;
+ co[2] = CDDM_get_vert(dm, mface->v3)->co;
+ co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL;
+
+ for (j = 0; j < nr; j++) {
+ // get coordinate into the space of the original mesh
+ if (mapmat)
+ mul_v3_m4v3(obco, mapmat, co[j]);
+ else
+ copy_v3_v3(obco, co[j]);
+
+ interp_weights_face_v3( w[j],orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco);
+ }
+
+ CustomData_interp(&orig_dm->faceData, &dm->faceData, &orig_index, NULL, (float*)w, 1, index);
+}
+
+/* Iterate over the CSG Output Descriptors and create a new DerivedMesh
+ from them */
+static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
+ CSG_FaceIteratorDescriptor *face_it,
+ CSG_VertexIteratorDescriptor *vertex_it,
+ float parinv[][4],
+ float mapmat[][4],
+ Material **mat,
+ int *totmat,
+ DerivedMesh *dm1,
+ Object *ob1,
+ DerivedMesh *dm2,
+ Object *ob2)
+{
+ DerivedMesh *result, *orig_dm;
+ GHash *material_hash = NULL;
+ Mesh *me1= (Mesh*)ob1->data;
+ Mesh *me2= (Mesh*)ob2->data;
+ int i;
+
+ // create a new DerivedMesh
+ result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
+ CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
+ CD_DEFAULT, face_it->num_elements);
+ CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
+ CD_DEFAULT, face_it->num_elements);
+
+ // step through the vertex iterators:
+ for (i = 0; !vertex_it->Done(vertex_it->it); i++) {
+ CSG_IVertex csgvert;
+ MVert *mvert = CDDM_get_vert(result, i);
+
+ // retrieve a csg vertex from the boolean module
+ vertex_it->Fill(vertex_it->it, &csgvert);
+ vertex_it->Step(vertex_it->it);
+
+ // we have to map the vertex coordinates back in the coordinate frame
+ // of the resulting object, since it was computed in world space
+ mul_v3_m4v3(mvert->co, parinv, csgvert.position);
+ }
+
+ // a hash table to remap materials to indices
+ if (mat) {
+ material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ *totmat = 0;
+ }
+
+ // step through the face iterators
+ for(i = 0; !face_it->Done(face_it->it); i++) {
+ Mesh *orig_me;
+ Object *orig_ob;
+ Material *orig_mat;
+ CSG_IFace csgface;
+ MFace *mface;
+ int orig_index, mat_nr;
+
+ // retrieve a csg face from the boolean module
+ face_it->Fill(face_it->it, &csgface);
+ face_it->Step(face_it->it);
+
+ // find the original mesh and data
+ orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2;
+ orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2;
+ orig_me = (orig_ob == ob1)? me1: me2;
+ orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1);
+
+ // copy all face layers, including mface
+ CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1);
+
+ // set mface
+ mface = CDDM_get_face(result, i);
+ mface->v1 = csgface.vertex_index[0];
+ mface->v2 = csgface.vertex_index[1];
+ mface->v3 = csgface.vertex_index[2];
+ mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0;
+
+ // set material, based on lookup in hash table
+ orig_mat= give_current_material(orig_ob, mface->mat_nr+1);
+
+ if (mat && orig_mat) {
+ if (!BLI_ghash_haskey(material_hash, orig_mat)) {
+ mat[*totmat] = orig_mat;
+ mat_nr = mface->mat_nr = (*totmat)++;
+ BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
+ }
+ else
+ mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
+ }
+ else
+ mface->mat_nr = 0;
+
+ InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number,
+ (orig_me == me2)? mapmat: NULL);
+
+ test_index_face(mface, &result->faceData, i, csgface.vertex_number);
+ }
+
+ if (material_hash)
+ BLI_ghash_free(material_hash, NULL, NULL);
+
+ CDDM_calc_edges(result);
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+static void BuildMeshDescriptors(
+ struct DerivedMesh *dm,
+ struct Object *ob,
+ int face_offset,
+ struct CSG_FaceIteratorDescriptor * face_it,
+ struct CSG_VertexIteratorDescriptor * vertex_it)
+{
+ VertexIt_Construct(vertex_it,dm, ob);
+ FaceIt_Construct(face_it,dm,face_offset,ob);
+}
+
+static void FreeMeshDescriptors(
+ struct CSG_FaceIteratorDescriptor *face_it,
+ struct CSG_VertexIteratorDescriptor *vertex_it)
+{
+ VertexIt_Destruct(vertex_it);
+ FaceIt_Destruct(face_it);
+}
+
+DerivedMesh *NewBooleanDerivedMesh_intern(
+ DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
+ int int_op_type, Material **mat, int *totmat)
+{
+
+ float inv_mat[4][4];
+ float map_mat[4][4];
+
+ DerivedMesh *result = NULL;
+
+ if (dm == NULL || dm_select == NULL) return 0;
+ if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0;
+
+ // we map the final object back into ob's local coordinate space. For this
+ // we need to compute the inverse transform from global to ob (inv_mat),
+ // and the transform from ob to ob_select for use in interpolation (map_mat)
+ invert_m4_m4(inv_mat, ob->obmat);
+ mul_m4_m4m4(map_mat, ob_select->obmat, inv_mat);
+ invert_m4_m4(inv_mat, ob_select->obmat);
+
+ {
+ // interface with the boolean module:
+ //
+ // the idea is, we pass the boolean module verts and faces using the
+ // provided descriptors. once the boolean operation is performed, we
+ // get back output descriptors, from which we then build a DerivedMesh
+
+ CSG_VertexIteratorDescriptor vd_1, vd_2;
+ CSG_FaceIteratorDescriptor fd_1, fd_2;
+ CSG_OperationType op_type;
+ CSG_BooleanOperation *bool_op;
+
+ // work out the operation they chose and pick the appropriate
+ // enum from the csg module.
+ switch (int_op_type) {
+ case 1 : op_type = e_csg_intersection; break;
+ case 2 : op_type = e_csg_union; break;
+ case 3 : op_type = e_csg_difference; break;
+ case 4 : op_type = e_csg_classify; break;
+ default : op_type = e_csg_intersection;
+ }
+
+ BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1);
+ BuildMeshDescriptors(dm, ob, dm_select->getNumFaces(dm_select) , &fd_2, &vd_2);
+
+ bool_op = CSG_NewBooleanFunction();
+
+ // perform the operation
+ if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) {
+ CSG_VertexIteratorDescriptor vd_o;
+ CSG_FaceIteratorDescriptor fd_o;
+
+ CSG_OutputFaceDescriptor(bool_op, &fd_o);
+ CSG_OutputVertexDescriptor(bool_op, &vd_o);
+
+ // iterate through results of operation and insert
+ // into new object
+ result = ConvertCSGDescriptorsToDerivedMesh(
+ &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob);
+
+ // free up the memory
+ CSG_FreeVertexDescriptor(&vd_o);
+ CSG_FreeFaceDescriptor(&fd_o);
+ }
+ else
+ printf("Unknown internal error in boolean");
+
+ CSG_FreeBooleanOperation(bool_op);
+
+ FreeMeshDescriptors(&fd_1, &vd_1);
+ FreeMeshDescriptors(&fd_2, &vd_2);
+ }
+
+ return result;
+}
+
+int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
+{
+ Mesh *me_new;
+ int a, maxmat, totmat= 0;
+ Object *ob_new, *ob, *ob_select;
+ Material **mat;
+ DerivedMesh *result;
+ DerivedMesh *dm_select;
+ DerivedMesh *dm;
+
+ ob= base->object;
+ ob_select= base_select->object;
+
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ??
+
+ maxmat= ob->totcol + ob_select->totcol;
+ mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat");
+
+ /* put some checks in for nice user feedback */
+ if (dm == NULL || dm_select == NULL) return 0;
+ if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select))
+ {
+ MEM_freeN(mat);
+ return -1;
+ }
+
+ result= NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat);
+
+ if (result == NULL) {
+ MEM_freeN(mat);
+ return 0;
+ }
+
+ /* create a new blender mesh object - using 'base' as a template */
+ ob_new= AddNewBlenderMesh(scene, base_select);
+ me_new= ob_new->data;
+
+ DM_to_mesh(result, me_new);
+ result->release(result);
+
+ dm->release(dm);
+ dm_select->release(dm_select);
+
+ /* add materials to object */
+ for (a = 0; a < totmat; a++)
+ assign_material(ob_new, mat[a], a+1);
+
+ MEM_freeN(mat);
+
+ /* update dag */
+ DAG_id_flush_update(&ob_new->id, OB_RECALC_DATA);
+
+ return 1;
+}
+
+DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
+ int int_op_type)
+{
+ return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL);
+}
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.h b/source/blender/modifiers/intern/MOD_boolean_util.h
new file mode 100644
index 00000000000..37cee9b528c
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_boolean_util.h
@@ -0,0 +1,50 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef MOD_BOOLEAN_UTILS_H
+#define MOD_BOOLEAN_UTILS_H
+
+struct Scene;
+struct Object;
+struct Base;
+struct DerivedMesh;
+
+/* Performs a boolean between two mesh objects, it is assumed that both objects
+ are in fact a mesh object. On success returns 1 and creates a new mesh object
+ into blender data structures. On failure returns 0 and reports an error. */
+int NewBooleanMesh(struct Scene *scene, struct Base *base, struct Base *base_select, int op);
+
+
+/* Performs a boolean between two mesh objects, it is assumed that both objects
+ are in fact mesh object. On success returns a DerivedMesh. On failure
+ returns NULL and reports an error. */
+
+struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob, struct DerivedMesh *dm_select, struct Object *ob_select, int int_op_type);
+
+#endif // MOD_BOOLEAN_UTILS
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
new file mode 100644
index 00000000000..9b9896d66bd
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -0,0 +1,342 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+
+static void initData(ModifierData *md)
+{
+ BuildModifierData *bmd = (BuildModifierData*) md;
+
+ bmd->start = 1.0;
+ bmd->length = 100.0;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ BuildModifierData *bmd = (BuildModifierData*) md;
+ BuildModifierData *tbmd = (BuildModifierData*) target;
+
+ tbmd->start = bmd->start;
+ tbmd->length = bmd->length;
+ tbmd->randomize = bmd->randomize;
+ tbmd->seed = bmd->seed;
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = derivedData;
+ DerivedMesh *result;
+ BuildModifierData *bmd = (BuildModifierData*) md;
+ int i;
+ int numFaces, numEdges;
+ int maxVerts, maxEdges, maxFaces;
+ int *vertMap, *edgeMap, *faceMap;
+ float frac;
+ GHashIterator *hashIter;
+ /* maps vert indices in old mesh to indices in new mesh */
+ GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
+ BLI_ghashutil_intcmp);
+ /* maps edge indices in new mesh to indices in old mesh */
+ GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
+ BLI_ghashutil_intcmp);
+
+ maxVerts = dm->getNumVerts(dm);
+ vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts,
+ "build modifier vertMap");
+ for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
+
+ maxEdges = dm->getNumEdges(dm);
+ edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges,
+ "build modifier edgeMap");
+ for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
+
+ maxFaces = dm->getNumFaces(dm);
+ faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces,
+ "build modifier faceMap");
+ for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
+
+ if (ob) {
+ frac = bsystem_time(md->scene, ob, md->scene->r.cfra,
+ bmd->start - 1.0f) / bmd->length;
+ } else {
+ frac = md->scene->r.cfra - bmd->start / bmd->length;
+ }
+ CLAMP(frac, 0.0, 1.0);
+
+ numFaces = dm->getNumFaces(dm) * frac;
+ numEdges = dm->getNumEdges(dm) * frac;
+
+ /* if there's at least one face, build based on faces */
+ if(numFaces) {
+ int maxEdges;
+
+ if(bmd->randomize)
+ BLI_array_randomize(faceMap, sizeof(*faceMap),
+ maxFaces, bmd->seed);
+
+ /* get the set of all vert indices that will be in the final mesh,
+ * mapped to the new indices
+ */
+ for(i = 0; i < numFaces; ++i) {
+ MFace mf;
+ dm->getFace(dm, faceMap[i], &mf);
+
+ if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1),
+ SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2),
+ SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3),
+ SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4),
+ SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ }
+
+ /* get the set of edges that will be in the new mesh (i.e. all edges
+ * that have both verts in the new mesh)
+ */
+ maxEdges = dm->getNumEdges(dm);
+ for(i = 0; i < maxEdges; ++i) {
+ MEdge me;
+ dm->getEdge(dm, i, &me);
+
+ if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))
+ && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
+ BLI_ghash_insert(edgeHash,
+ SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i));
+ }
+ } else if(numEdges) {
+ if(bmd->randomize)
+ BLI_array_randomize(edgeMap, sizeof(*edgeMap),
+ maxEdges, bmd->seed);
+
+ /* get the set of all vert indices that will be in the final mesh,
+ * mapped to the new indices
+ */
+ for(i = 0; i < numEdges; ++i) {
+ MEdge me;
+ dm->getEdge(dm, edgeMap[i], &me);
+
+ if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1),
+ SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2),
+ SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ }
+
+ /* get the set of edges that will be in the new mesh
+ */
+ for(i = 0; i < numEdges; ++i) {
+ MEdge me;
+ dm->getEdge(dm, edgeMap[i], &me);
+
+ BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)),
+ SET_INT_IN_POINTER(edgeMap[i]));
+ }
+ } else {
+ int numVerts = dm->getNumVerts(dm) * frac;
+
+ if(bmd->randomize)
+ BLI_array_randomize(vertMap, sizeof(*vertMap),
+ maxVerts, bmd->seed);
+
+ /* get the set of all vert indices that will be in the final mesh,
+ * mapped to the new indices
+ */
+ for(i = 0; i < numVerts; ++i)
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i));
+ }
+
+ /* now we know the number of verts, edges and faces, we can create
+ * the mesh
+ */
+ result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
+ BLI_ghash_size(edgeHash), numFaces);
+
+ /* copy the vertices across */
+ for(hashIter = BLI_ghashIterator_new(vertHash);
+ !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_step(hashIter)) {
+ MVert source;
+ MVert *dest;
+ int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
+ int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
+
+ dm->getVert(dm, oldIndex, &source);
+ dest = CDDM_get_vert(result, newIndex);
+
+ DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
+ *dest = source;
+ }
+ BLI_ghashIterator_free(hashIter);
+
+ /* copy the edges across, remapping indices */
+ for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
+ MEdge source;
+ MEdge *dest;
+ int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i)));
+
+ dm->getEdge(dm, oldIndex, &source);
+ dest = CDDM_get_edge(result, i);
+
+ source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
+ source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
+
+ DM_copy_edge_data(dm, result, oldIndex, i, 1);
+ *dest = source;
+ }
+
+ /* copy the faces across, remapping indices */
+ for(i = 0; i < numFaces; ++i) {
+ MFace source;
+ MFace *dest;
+ int orig_v4;
+
+ dm->getFace(dm, faceMap[i], &source);
+ dest = CDDM_get_face(result, i);
+
+ orig_v4 = source.v4;
+
+ source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
+ source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
+ source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
+ if(source.v4)
+ source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
+
+ DM_copy_face_data(dm, result, faceMap[i], i, 1);
+ *dest = source;
+
+ test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
+ }
+
+ CDDM_calc_normals(result);
+
+ BLI_ghash_free(vertHash, NULL, NULL);
+ BLI_ghash_free(edgeHash, NULL, NULL);
+
+ MEM_freeN(vertMap);
+ MEM_freeN(edgeMap);
+ MEM_freeN(faceMap);
+
+ return result;
+}
+/*
+ mti = INIT_TYPE(Build);
+ mti->type = eModifierTypeType_Nonconstructive;
+ mti->flags = eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_AcceptsCVs;
+ mti->initData = buildModifier_initData;
+ mti->copyData = buildModifier_copyData;
+ mti->dependsOnTime = buildModifier_dependsOnTime;
+ mti->applyModifier = buildModifier_applyModifier;
+*/
+
+ModifierTypeInfo modifierType_Build = {
+ /* name */ "Build",
+ /* structName */ "BuildModifierData",
+ /* structSize */ sizeof(BuildModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_AcceptsCVs,
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
new file mode 100644
index 00000000000..4b2a85e56d7
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -0,0 +1,667 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+static void initData(ModifierData *md)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+
+ cmd->fac = 0.5f;
+ cmd->radius = 0.0f;
+ cmd->size = 0.0f;
+ cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z
+ | MOD_CAST_SIZE_FROM_RADIUS;
+ cmd->type = MOD_CAST_TYPE_SPHERE;
+ cmd->defgrp_name[0] = '\0';
+ cmd->object = NULL;
+}
+
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+ CastModifierData *tcmd = (CastModifierData*) target;
+
+ tcmd->fac = cmd->fac;
+ tcmd->radius = cmd->radius;
+ tcmd->size = cmd->size;
+ tcmd->flag = cmd->flag;
+ tcmd->type = cmd->type;
+ tcmd->object = cmd->object;
+ strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32);
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+ short flag;
+
+ flag = cmd->flag & (MOD_CAST_X|MOD_CAST_Y|MOD_CAST_Z);
+
+ if((cmd->fac == 0.0f) || flag == 0) return 1;
+
+ return 0;
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ CastModifierData *cmd = (CastModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(cmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+
+ walk (userData, ob, &cmd->object);
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
+ DagNode *obNode)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+
+ if (cmd->object) {
+ DagNode *curNode = dag_get_node(forest, cmd->object);
+
+ dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
+ "Cast Modifier");
+ }
+}
+
+static void sphere_do(
+ CastModifierData *cmd, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ MDeformVert *dvert = NULL;
+
+ Object *ctrl_ob = NULL;
+
+ int i, defgrp_index;
+ int has_radius = 0;
+ short flag, type;
+ float fac, facm, len = 0.0f;
+ float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
+ float mat[4][4], imat[4][4];
+
+ fac = cmd->fac;
+ facm = 1.0f - fac;
+
+ flag = cmd->flag;
+ type = cmd->type; /* projection type: sphere or cylinder */
+
+ if (type == MOD_CAST_TYPE_CYLINDER)
+ flag &= ~MOD_CAST_Z;
+
+ ctrl_ob = cmd->object;
+
+ /* spherify's center is {0, 0, 0} (the ob's own center in its local
+ * space), by default, but if the user defined a control object,
+ * we use its location, transformed to ob's local space */
+ if (ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
+ mul_m4_m4m4(mat, ob->obmat, ctrl_ob->imat);
+ invert_m4_m4(imat, mat);
+ }
+
+ invert_m4_m4(ob->imat, ob->obmat);
+ VECCOPY(center, ctrl_ob->obmat[3]);
+ mul_m4_v3(ob->imat, center);
+ }
+
+ /* now we check which options the user wants */
+
+ /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
+ /* 2) cmd->radius > 0.0f: only the vertices within this radius from
+ * the center of the effect should be deformed */
+ if (cmd->radius > FLT_EPSILON) has_radius = 1;
+
+ /* 3) if we were given a vertex group name,
+ * only those vertices should be affected */
+ defgrp_index = defgroup_name_index(ob, cmd->defgrp_name);
+
+ if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ if(flag & MOD_CAST_SIZE_FROM_RADIUS) {
+ len = cmd->radius;
+ }
+ else {
+ len = cmd->size;
+ }
+
+ if(len <= 0) {
+ for (i = 0; i < numVerts; i++) {
+ len += len_v3v3(center, vertexCos[i]);
+ }
+ len /= numVerts;
+
+ if (len == 0.0f) len = 10.0f;
+ }
+
+ /* ready to apply the effect, one vertex at a time;
+ * tiny optimization: the code is separated (with parts repeated)
+ * in two possible cases:
+ * with or w/o a vgroup. With lots of if's in the code below,
+ * further optimizations are possible, if needed */
+ if (dvert) { /* with a vgroup */
+ float fac_orig = fac;
+ for (i = 0; i < numVerts; i++) {
+ MDeformWeight *dw = NULL;
+ int j;
+ float tmp_co[3];
+
+ VECCOPY(tmp_co, vertexCos[i]);
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ mul_m4_v3(mat, tmp_co);
+ } else {
+ sub_v3_v3v3(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vec, tmp_co);
+
+ if (type == MOD_CAST_TYPE_CYLINDER)
+ vec[2] = 0.0f;
+
+ if (has_radius) {
+ if (len_v3(vec) > cmd->radius) continue;
+ }
+
+ for (j = 0; j < dvert[i].totweight; ++j) {
+ if(dvert[i].dw[j].def_nr == defgrp_index) {
+ dw = &dvert[i].dw[j];
+ break;
+ }
+ }
+ if (!dw) continue;
+
+ fac = fac_orig * dw->weight;
+ facm = 1.0f - fac;
+
+ normalize_v3(vec);
+
+ if (flag & MOD_CAST_X)
+ tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
+ if (flag & MOD_CAST_Y)
+ tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
+ if (flag & MOD_CAST_Z)
+ tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
+
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ mul_m4_v3(imat, tmp_co);
+ } else {
+ add_v3_v3v3(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vertexCos[i], tmp_co);
+ }
+ return;
+ }
+
+ /* no vgroup */
+ for (i = 0; i < numVerts; i++) {
+ float tmp_co[3];
+
+ VECCOPY(tmp_co, vertexCos[i]);
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ mul_m4_v3(mat, tmp_co);
+ } else {
+ sub_v3_v3v3(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vec, tmp_co);
+
+ if (type == MOD_CAST_TYPE_CYLINDER)
+ vec[2] = 0.0f;
+
+ if (has_radius) {
+ if (len_v3(vec) > cmd->radius) continue;
+ }
+
+ normalize_v3(vec);
+
+ if (flag & MOD_CAST_X)
+ tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
+ if (flag & MOD_CAST_Y)
+ tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
+ if (flag & MOD_CAST_Z)
+ tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
+
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ mul_m4_v3(imat, tmp_co);
+ } else {
+ add_v3_v3v3(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vertexCos[i], tmp_co);
+ }
+}
+
+static void cuboid_do(
+ CastModifierData *cmd, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ MDeformVert *dvert = NULL;
+ Object *ctrl_ob = NULL;
+
+ int i, defgrp_index;
+ int has_radius = 0;
+ short flag;
+ float fac, facm;
+ float min[3], max[3], bb[8][3];
+ float center[3] = {0.0f, 0.0f, 0.0f};
+ float mat[4][4], imat[4][4];
+
+ fac = cmd->fac;
+ facm = 1.0f - fac;
+
+ flag = cmd->flag;
+
+ ctrl_ob = cmd->object;
+
+ /* now we check which options the user wants */
+
+ /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
+ /* 2) cmd->radius > 0.0f: only the vertices within this radius from
+ * the center of the effect should be deformed */
+ if (cmd->radius > FLT_EPSILON) has_radius = 1;
+
+ /* 3) if we were given a vertex group name,
+ * only those vertices should be affected */
+ defgrp_index = defgroup_name_index(ob, cmd->defgrp_name);
+
+ if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ if (ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
+ mul_m4_m4m4(mat, ob->obmat, ctrl_ob->imat);
+ invert_m4_m4(imat, mat);
+ }
+
+ invert_m4_m4(ob->imat, ob->obmat);
+ VECCOPY(center, ctrl_ob->obmat[3]);
+ mul_m4_v3(ob->imat, center);
+ }
+
+ if((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
+ for(i = 0; i < 3; i++) {
+ min[i] = -cmd->radius;
+ max[i] = cmd->radius;
+ }
+ } else if(!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
+ for(i = 0; i < 3; i++) {
+ min[i] = -cmd->size;
+ max[i] = cmd->size;
+ }
+ } else {
+ /* get bound box */
+ /* We can't use the object's bound box because other modifiers
+ * may have changed the vertex data. */
+ INIT_MINMAX(min, max);
+
+ /* Cast's center is the ob's own center in its local space,
+ * by default, but if the user defined a control object, we use
+ * its location, transformed to ob's local space. */
+ if (ctrl_ob) {
+ float vec[3];
+
+ /* let the center of the ctrl_ob be part of the bound box: */
+ DO_MINMAX(center, min, max);
+
+ for (i = 0; i < numVerts; i++) {
+ sub_v3_v3v3(vec, vertexCos[i], center);
+ DO_MINMAX(vec, min, max);
+ }
+ }
+ else {
+ for (i = 0; i < numVerts; i++) {
+ DO_MINMAX(vertexCos[i], min, max);
+ }
+ }
+
+ /* we want a symmetric bound box around the origin */
+ if (fabs(min[0]) > fabs(max[0])) max[0] = fabs(min[0]);
+ if (fabs(min[1]) > fabs(max[1])) max[1] = fabs(min[1]);
+ if (fabs(min[2]) > fabs(max[2])) max[2] = fabs(min[2]);
+ min[0] = -max[0];
+ min[1] = -max[1];
+ min[2] = -max[2];
+ }
+
+ /* building our custom bounding box */
+ bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
+ bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
+ bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
+ bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
+ bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
+ bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
+
+ /* ready to apply the effect, one vertex at a time;
+ * tiny optimization: the code is separated (with parts repeated)
+ * in two possible cases:
+ * with or w/o a vgroup. With lots of if's in the code below,
+ * further optimizations are possible, if needed */
+ if (dvert) { /* with a vgroup */
+ float fac_orig = fac;
+ for (i = 0; i < numVerts; i++) {
+ MDeformWeight *dw = NULL;
+ int j, octant, coord;
+ float d[3], dmax, apex[3], fbb;
+ float tmp_co[3];
+
+ VECCOPY(tmp_co, vertexCos[i]);
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ mul_m4_v3(mat, tmp_co);
+ } else {
+ sub_v3_v3v3(tmp_co, tmp_co, center);
+ }
+ }
+
+ if (has_radius) {
+ if (fabs(tmp_co[0]) > cmd->radius ||
+ fabs(tmp_co[1]) > cmd->radius ||
+ fabs(tmp_co[2]) > cmd->radius) continue;
+ }
+
+ for (j = 0; j < dvert[i].totweight; ++j) {
+ if(dvert[i].dw[j].def_nr == defgrp_index) {
+ dw = &dvert[i].dw[j];
+ break;
+ }
+ }
+ if (!dw) continue;
+
+ fac = fac_orig * dw->weight;
+ facm = 1.0f - fac;
+
+ /* The algo used to project the vertices to their
+ * bounding box (bb) is pretty simple:
+ * for each vertex v:
+ * 1) find in which octant v is in;
+ * 2) find which outer "wall" of that octant is closer to v;
+ * 3) calculate factor (var fbb) to project v to that wall;
+ * 4) project. */
+
+ /* find in which octant this vertex is in */
+ octant = 0;
+ if (tmp_co[0] > 0.0f) octant += 1;
+ if (tmp_co[1] > 0.0f) octant += 2;
+ if (tmp_co[2] > 0.0f) octant += 4;
+
+ /* apex is the bb's vertex at the chosen octant */
+ copy_v3_v3(apex, bb[octant]);
+
+ /* find which bb plane is closest to this vertex ... */
+ d[0] = tmp_co[0] / apex[0];
+ d[1] = tmp_co[1] / apex[1];
+ d[2] = tmp_co[2] / apex[2];
+
+ /* ... (the closest has the higher (closer to 1) d value) */
+ dmax = d[0];
+ coord = 0;
+ if (d[1] > dmax) {
+ dmax = d[1];
+ coord = 1;
+ }
+ if (d[2] > dmax) {
+ /* dmax = d[2]; */ /* commented, we don't need it */
+ coord = 2;
+ }
+
+ /* ok, now we know which coordinate of the vertex to use */
+
+ if (fabs(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
+ continue;
+
+ /* finally, this is the factor we wanted, to project the vertex
+ * to its bounding box (bb) */
+ fbb = apex[coord] / tmp_co[coord];
+
+ /* calculate the new vertex position */
+ if (flag & MOD_CAST_X)
+ tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
+ if (flag & MOD_CAST_Y)
+ tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
+ if (flag & MOD_CAST_Z)
+ tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
+
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ mul_m4_v3(imat, tmp_co);
+ } else {
+ add_v3_v3v3(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vertexCos[i], tmp_co);
+ }
+ return;
+ }
+
+ /* no vgroup (check previous case for comments about the code) */
+ for (i = 0; i < numVerts; i++) {
+ int octant, coord;
+ float d[3], dmax, fbb, apex[3];
+ float tmp_co[3];
+
+ VECCOPY(tmp_co, vertexCos[i]);
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ mul_m4_v3(mat, tmp_co);
+ } else {
+ sub_v3_v3v3(tmp_co, tmp_co, center);
+ }
+ }
+
+ if (has_radius) {
+ if (fabs(tmp_co[0]) > cmd->radius ||
+ fabs(tmp_co[1]) > cmd->radius ||
+ fabs(tmp_co[2]) > cmd->radius) continue;
+ }
+
+ octant = 0;
+ if (tmp_co[0] > 0.0f) octant += 1;
+ if (tmp_co[1] > 0.0f) octant += 2;
+ if (tmp_co[2] > 0.0f) octant += 4;
+
+ copy_v3_v3(apex, bb[octant]);
+
+ d[0] = tmp_co[0] / apex[0];
+ d[1] = tmp_co[1] / apex[1];
+ d[2] = tmp_co[2] / apex[2];
+
+ dmax = d[0];
+ coord = 0;
+ if (d[1] > dmax) {
+ dmax = d[1];
+ coord = 1;
+ }
+ if (d[2] > dmax) {
+ /* dmax = d[2]; */ /* commented, we don't need it */
+ coord = 2;
+ }
+
+ if (fabs(tmp_co[coord]) < FLT_EPSILON)
+ continue;
+
+ fbb = apex[coord] / tmp_co[coord];
+
+ if (flag & MOD_CAST_X)
+ tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
+ if (flag & MOD_CAST_Y)
+ tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
+ if (flag & MOD_CAST_Z)
+ tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
+
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ mul_m4_v3(imat, tmp_co);
+ } else {
+ add_v3_v3v3(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vertexCos[i], tmp_co);
+ }
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = NULL;
+ CastModifierData *cmd = (CastModifierData *)md;
+
+ dm = get_dm(md->scene, ob, NULL, derivedData, NULL, 0);
+
+ if (cmd->type == MOD_CAST_TYPE_CUBOID) {
+ cuboid_do(cmd, ob, dm, vertexCos, numVerts);
+ } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
+ sphere_do(cmd, ob, dm, vertexCos, numVerts);
+ }
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = get_dm(md->scene, ob, editData, derivedData, NULL, 0);
+ CastModifierData *cmd = (CastModifierData *)md;
+
+ if (cmd->type == MOD_CAST_TYPE_CUBOID) {
+ cuboid_do(cmd, ob, dm, vertexCos, numVerts);
+ } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
+ sphere_do(cmd, ob, dm, vertexCos, numVerts);
+ }
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Cast = {
+ /* name */ "Cast",
+ /* structName */ "CastModifierData",
+ /* structSize */ sizeof(CastModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
new file mode 100644
index 00000000000..a2f5fdc614e
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -0,0 +1,244 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ ClothModifierData *clmd = (ClothModifierData*) md;
+
+ clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms");
+ clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms");
+ clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches);
+
+ /* check for alloc failing */
+ if(!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache)
+ return;
+
+ cloth_init (clmd);
+}
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData, int useRenderParams, int isFinalCalc)
+{
+ ClothModifierData *clmd = (ClothModifierData*) md;
+ DerivedMesh *result=NULL;
+
+ /* check for alloc failing */
+ if(!clmd->sim_parms || !clmd->coll_parms)
+ {
+ initData(md);
+
+ if(!clmd->sim_parms || !clmd->coll_parms)
+ return derivedData;
+ }
+
+ result = clothModifier_do(clmd, md->scene, ob, derivedData, useRenderParams, isFinalCalc);
+
+ if(result)
+ {
+ CDDM_calc_normals(result);
+ return result;
+ }
+ return derivedData;
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
+ DagNode *obNode)
+{
+ ClothModifierData *clmd = (ClothModifierData*) md;
+
+ Base *base;
+
+ if(clmd)
+ {
+ for(base = scene->base.first; base; base= base->next)
+ {
+ Object *ob1= base->object;
+ if(ob1 != ob)
+ {
+ CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision);
+ if(coll_clmd)
+ {
+ DagNode *curNode = dag_get_node(forest, ob1);
+ dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Cloth Collision");
+ }
+ }
+ }
+ }
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ CustomDataMask dataMask = 0;
+ ClothModifierData *clmd = (ClothModifierData*)md;
+
+ if(cloth_uses_vgroup(clmd))
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ if(clmd->sim_parms->shapekey_rest != 0)
+ dataMask |= (1 << CD_CLOTH_ORCO);
+
+ return dataMask;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ ClothModifierData *clmd = (ClothModifierData*) md;
+ ClothModifierData *tclmd = (ClothModifierData*) target;
+
+ if(tclmd->sim_parms)
+ MEM_freeN(tclmd->sim_parms);
+ if(tclmd->coll_parms)
+ MEM_freeN(tclmd->coll_parms);
+
+ BKE_ptcache_free_list(&tclmd->ptcaches);
+ tclmd->point_cache = NULL;
+
+ tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms);
+ if(clmd->sim_parms->effector_weights)
+ tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights);
+ tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
+ tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches);
+ tclmd->clothObject = NULL;
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+static void freeData(ModifierData *md)
+{
+ ClothModifierData *clmd = (ClothModifierData*) md;
+
+ if (clmd)
+ {
+ if(G.rt > 0)
+ printf("clothModifier_freeData\n");
+
+ cloth_free_modifier_extern (clmd);
+
+ if(clmd->sim_parms) {
+ if(clmd->sim_parms->effector_weights)
+ MEM_freeN(clmd->sim_parms->effector_weights);
+ MEM_freeN(clmd->sim_parms);
+ }
+ if(clmd->coll_parms)
+ MEM_freeN(clmd->coll_parms);
+
+ BKE_ptcache_free_list(&clmd->ptcaches);
+ clmd->point_cache = NULL;
+ }
+}
+
+
+ModifierTypeInfo modifierType_Cloth = {
+ /* name */ "Cloth",
+ /* structName */ "ClothModifierData",
+ /* structSize */ sizeof(ClothModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_UsesPointCache |
+ eModifierTypeFlag_Single,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ 0,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ freeData,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
new file mode 100644
index 00000000000..11f0dbfc5e1
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -0,0 +1,292 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+static void initData(ModifierData *md)
+{
+ CollisionModifierData *collmd = (CollisionModifierData*) md;
+
+ collmd->x = NULL;
+ collmd->xnew = NULL;
+ collmd->current_x = NULL;
+ collmd->current_xnew = NULL;
+ collmd->current_v = NULL;
+ collmd->time = -1000;
+ collmd->numverts = 0;
+ collmd->bvhtree = NULL;
+}
+
+static void freeData(ModifierData *md)
+{
+ CollisionModifierData *collmd = (CollisionModifierData*) md;
+
+ if (collmd)
+ {
+ if(collmd->bvhtree)
+ BLI_bvhtree_free(collmd->bvhtree);
+ if(collmd->x)
+ MEM_freeN(collmd->x);
+ if(collmd->xnew)
+ MEM_freeN(collmd->xnew);
+ if(collmd->current_x)
+ MEM_freeN(collmd->current_x);
+ if(collmd->current_xnew)
+ MEM_freeN(collmd->current_xnew);
+ if(collmd->current_v)
+ MEM_freeN(collmd->current_v);
+ if(collmd->mfaces)
+ MEM_freeN(collmd->mfaces);
+
+ collmd->x = NULL;
+ collmd->xnew = NULL;
+ collmd->current_x = NULL;
+ collmd->current_xnew = NULL;
+ collmd->current_v = NULL;
+ collmd->time = -1000;
+ collmd->numverts = 0;
+ collmd->bvhtree = NULL;
+ collmd->mfaces = NULL;
+ }
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ CollisionModifierData *collmd = (CollisionModifierData*) md;
+ DerivedMesh *dm = NULL;
+ float current_time = 0;
+ unsigned int numverts = 0, i = 0;
+ MVert *tempVert = NULL;
+
+ /* if possible use/create DerivedMesh */
+ if(derivedData) dm = CDDM_copy(derivedData);
+ else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
+
+ if(!ob->pd)
+ {
+ printf("CollisionModifier deformVerts: Should not happen!\n");
+ return;
+ }
+
+ if(dm)
+ {
+ CDDM_apply_vert_coords(dm, vertexCos);
+ CDDM_calc_normals(dm);
+
+ current_time = bsystem_time (md->scene, ob, ( float ) md->scene->r.cfra, 0.0 );
+
+ if(G.rt > 0)
+ printf("current_time %f, collmd->time %f\n", current_time, collmd->time);
+
+ numverts = dm->getNumVerts ( dm );
+
+ if((current_time > collmd->time)|| (BKE_ptcache_get_continue_physics()))
+ {
+ // check if mesh has changed
+ if(collmd->x && (numverts != collmd->numverts))
+ freeData((ModifierData *)collmd);
+
+ if(collmd->time == -1000) // first time
+ {
+ collmd->x = dm->dupVertArray(dm); // frame start position
+
+ for ( i = 0; i < numverts; i++ )
+ {
+ // we save global positions
+ mul_m4_v3( ob->obmat, collmd->x[i].co );
+ }
+
+ collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
+ collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
+ collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
+ collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
+
+ collmd->numverts = numverts;
+
+ collmd->mfaces = dm->dupFaceArray(dm);
+ collmd->numfaces = dm->getNumFaces(dm);
+
+ // create bounding box hierarchy
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
+
+ collmd->time = current_time;
+ }
+ else if(numverts == collmd->numverts)
+ {
+ // put positions to old positions
+ tempVert = collmd->x;
+ collmd->x = collmd->xnew;
+ collmd->xnew = tempVert;
+
+ memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
+
+ for ( i = 0; i < numverts; i++ )
+ {
+ // we save global positions
+ mul_m4_v3( ob->obmat, collmd->xnew[i].co );
+ }
+
+ memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert));
+ memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
+
+ /* check if GUI setting has changed for bvh */
+ if(collmd->bvhtree)
+ {
+ if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree))
+ {
+ BLI_bvhtree_free(collmd->bvhtree);
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
+ }
+
+ }
+
+ /* happens on file load (ONLY when i decomment changes in readfile.c) */
+ if(!collmd->bvhtree)
+ {
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
+ }
+ else
+ {
+ // recalc static bounding boxes
+ bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
+ }
+
+ collmd->time = current_time;
+ }
+ else if(numverts != collmd->numverts)
+ {
+ freeData((ModifierData *)collmd);
+ }
+
+ }
+ else if(current_time < collmd->time)
+ {
+ freeData((ModifierData *)collmd);
+ }
+ else
+ {
+ if(numverts != collmd->numverts)
+ {
+ freeData((ModifierData *)collmd);
+ }
+ }
+ }
+
+ if(dm)
+ dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Collision = {
+ /* name */ "Collision",
+ /* structName */ "CollisionModifierData",
+ /* structSize */ sizeof(CollisionModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_Single,
+
+ /* copyData */ 0,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ freeData,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
new file mode 100644
index 00000000000..b0ef2da4b30
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -0,0 +1,195 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ CurveModifierData *cmd = (CurveModifierData*) md;
+
+ cmd->defaxis = MOD_CURVE_POSX;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ CurveModifierData *cmd = (CurveModifierData*) md;
+ CurveModifierData *tcmd = (CurveModifierData*) target;
+
+ tcmd->defaxis = cmd->defaxis;
+ tcmd->object = cmd->object;
+ strncpy(tcmd->name, cmd->name, 32);
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ CurveModifierData *cmd = (CurveModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(cmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static int isDisabled(ModifierData *md, int userRenderParams)
+{
+ CurveModifierData *cmd = (CurveModifierData*) md;
+
+ return !cmd->object;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ CurveModifierData *cmd = (CurveModifierData*) md;
+
+ walk(userData, ob, &cmd->object);
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ CurveModifierData *cmd = (CurveModifierData*) md;
+
+ if (cmd->object) {
+ DagNode *curNode = dag_get_node(forest, cmd->object);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Modifier");
+ }
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ CurveModifierData *cmd = (CurveModifierData*) md;
+
+ curve_deform_verts(md->scene, cmd->object, ob, derivedData, vertexCos, numVerts,
+ cmd->name, cmd->defaxis);
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
+
+ if(!derivedData) dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Curve = {
+ /* name */ "Curve",
+ /* structName */ "CurveModifierData",
+ /* structSize */ sizeof(CurveModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
new file mode 100644
index 00000000000..dd912cfb58c
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -0,0 +1,243 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+
+#include "LOD_decimation.h"
+
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ DecimateModifierData *dmd = (DecimateModifierData*) md;
+
+ dmd->percent = 1.0;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ DecimateModifierData *dmd = (DecimateModifierData*) md;
+ DecimateModifierData *tdmd = (DecimateModifierData*) target;
+
+ tdmd->percent = dmd->percent;
+}
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DecimateModifierData *dmd = (DecimateModifierData*) md;
+ DerivedMesh *dm = derivedData, *result = NULL;
+ MVert *mvert;
+ MFace *mface;
+ LOD_Decimation_Info lod;
+ int totvert, totface;
+ int a, numTris;
+
+ mvert = dm->getVertArray(dm);
+ mface = dm->getFaceArray(dm);
+ totvert = dm->getNumVerts(dm);
+ totface = dm->getNumFaces(dm);
+
+ numTris = 0;
+ for (a=0; a<totface; a++) {
+ MFace *mf = &mface[a];
+ numTris++;
+ if (mf->v4) numTris++;
+ }
+
+ if(numTris<3) {
+ modifier_setError(md,
+ "Modifier requires more than 3 input faces (triangles).");
+ goto exit;
+ }
+
+ lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices");
+ lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*totvert, "normals");
+ lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*numTris, "trias");
+ lod.vertex_num= totvert;
+ lod.face_num= numTris;
+
+ for(a=0; a<totvert; a++) {
+ MVert *mv = &mvert[a];
+ float *vbCo = &lod.vertex_buffer[a*3];
+ float *vbNo = &lod.vertex_normal_buffer[a*3];
+
+ VECCOPY(vbCo, mv->co);
+
+ vbNo[0] = mv->no[0]/32767.0f;
+ vbNo[1] = mv->no[1]/32767.0f;
+ vbNo[2] = mv->no[2]/32767.0f;
+ }
+
+ numTris = 0;
+ for(a=0; a<totface; a++) {
+ MFace *mf = &mface[a];
+ int *tri = &lod.triangle_index_buffer[3*numTris++];
+ tri[0]= mf->v1;
+ tri[1]= mf->v2;
+ tri[2]= mf->v3;
+
+ if(mf->v4) {
+ tri = &lod.triangle_index_buffer[3*numTris++];
+ tri[0]= mf->v1;
+ tri[1]= mf->v3;
+ tri[2]= mf->v4;
+ }
+ }
+
+ dmd->faceCount = 0;
+ if(LOD_LoadMesh(&lod) ) {
+ if( LOD_PreprocessMesh(&lod) ) {
+ /* we assume the decim_faces tells how much to reduce */
+
+ while(lod.face_num > numTris*dmd->percent) {
+ if( LOD_CollapseEdge(&lod)==0) break;
+ }
+
+ if(lod.vertex_num>2) {
+ result = CDDM_new(lod.vertex_num, 0, lod.face_num);
+ dmd->faceCount = lod.face_num;
+ }
+ else
+ result = CDDM_new(lod.vertex_num, 0, 0);
+
+ mvert = CDDM_get_verts(result);
+ for(a=0; a<lod.vertex_num; a++) {
+ MVert *mv = &mvert[a];
+ float *vbCo = &lod.vertex_buffer[a*3];
+
+ VECCOPY(mv->co, vbCo);
+ }
+
+ if(lod.vertex_num>2) {
+ mface = CDDM_get_faces(result);
+ for(a=0; a<lod.face_num; a++) {
+ MFace *mf = &mface[a];
+ int *tri = &lod.triangle_index_buffer[a*3];
+ mf->v1 = tri[0];
+ mf->v2 = tri[1];
+ mf->v3 = tri[2];
+ test_index_face(mf, NULL, 0, 3);
+ }
+ }
+
+ CDDM_calc_edges(result);
+ CDDM_calc_normals(result);
+ }
+ else
+ modifier_setError(md, "Out of memory.");
+
+ LOD_FreeDecimationData(&lod);
+ }
+ else
+ modifier_setError(md, "Non-manifold mesh as input.");
+
+ MEM_freeN(lod.vertex_buffer);
+ MEM_freeN(lod.vertex_normal_buffer);
+ MEM_freeN(lod.triangle_index_buffer);
+
+exit:
+ return result;
+}
+
+
+ModifierTypeInfo modifierType_Decimate = {
+ /* name */ "Decimate",
+ /* structName */ "DecimateModifierData",
+ /* structSize */ sizeof(DecimateModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh,
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
new file mode 100644
index 00000000000..415ea7201af
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -0,0 +1,396 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+/* Displace */
+
+static void initData(ModifierData *md)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ dmd->texture = NULL;
+ dmd->strength = 1;
+ dmd->direction = MOD_DISP_DIR_NOR;
+ dmd->midlevel = 0.5;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+ DisplaceModifierData *tdmd = (DisplaceModifierData*) target;
+
+ tdmd->texture = dmd->texture;
+ tdmd->strength = dmd->strength;
+ tdmd->direction = dmd->direction;
+ strncpy(tdmd->defgrp_name, dmd->defgrp_name, 32);
+ tdmd->midlevel = dmd->midlevel;
+ tdmd->texmapping = dmd->texmapping;
+ tdmd->map_object = dmd->map_object;
+ strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32);
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(dmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ /* ask for UV coordinates if we need them */
+ if(dmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE);
+
+ return dataMask;
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData *)md;
+
+ if(dmd->texture)
+ {
+ return BKE_texture_dependsOnTime(dmd->texture);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ walk(userData, ob, &dmd->map_object);
+}
+
+static void foreachIDLink(ModifierData *md, Object *ob,
+ IDWalkFunc walk, void *userData)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ walk(userData, ob, (ID **)&dmd->texture);
+
+ foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ return !dmd->texture;
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ if(dmd->map_object) {
+ DagNode *curNode = dag_get_node(forest, dmd->map_object);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier");
+ }
+}
+
+static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
+ DerivedMesh *dm,
+ float (*co)[3], float (*texco)[3],
+ int numVerts)
+{
+ int i;
+ int texmapping = dmd->texmapping;
+ float mapob_imat[4][4];
+
+ if(texmapping == MOD_DISP_MAP_OBJECT) {
+ if(dmd->map_object)
+ invert_m4_m4(mapob_imat, dmd->map_object->obmat);
+ else /* if there is no map object, default to local */
+ texmapping = MOD_DISP_MAP_LOCAL;
+ }
+
+ /* UVs need special handling, since they come from faces */
+ if(texmapping == MOD_DISP_MAP_UV) {
+ if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
+ MFace *mface = dm->getFaceArray(dm);
+ MFace *mf;
+ char *done = MEM_callocN(sizeof(*done) * numVerts,
+ "get_texture_coords done");
+ int numFaces = dm->getNumFaces(dm);
+ char uvname[32];
+ MTFace *tf;
+
+ validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname);
+ tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
+
+ /* verts are given the UV from the first face that uses them */
+ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
+ if(!done[mf->v1]) {
+ texco[mf->v1][0] = tf->uv[0][0];
+ texco[mf->v1][1] = tf->uv[0][1];
+ texco[mf->v1][2] = 0;
+ done[mf->v1] = 1;
+ }
+ if(!done[mf->v2]) {
+ texco[mf->v2][0] = tf->uv[1][0];
+ texco[mf->v2][1] = tf->uv[1][1];
+ texco[mf->v2][2] = 0;
+ done[mf->v2] = 1;
+ }
+ if(!done[mf->v3]) {
+ texco[mf->v3][0] = tf->uv[2][0];
+ texco[mf->v3][1] = tf->uv[2][1];
+ texco[mf->v3][2] = 0;
+ done[mf->v3] = 1;
+ }
+ if(!done[mf->v4]) {
+ texco[mf->v4][0] = tf->uv[3][0];
+ texco[mf->v4][1] = tf->uv[3][1];
+ texco[mf->v4][2] = 0;
+ done[mf->v4] = 1;
+ }
+ }
+
+ /* remap UVs from [0, 1] to [-1, 1] */
+ for(i = 0; i < numVerts; ++i) {
+ texco[i][0] = texco[i][0] * 2 - 1;
+ texco[i][1] = texco[i][1] * 2 - 1;
+ }
+
+ MEM_freeN(done);
+ return;
+ } else /* if there are no UVs, default to local */
+ texmapping = MOD_DISP_MAP_LOCAL;
+ }
+
+ for(i = 0; i < numVerts; ++i, ++co, ++texco) {
+ switch(texmapping) {
+ case MOD_DISP_MAP_LOCAL:
+ VECCOPY(*texco, *co);
+ break;
+ case MOD_DISP_MAP_GLOBAL:
+ VECCOPY(*texco, *co);
+ mul_m4_v3(ob->obmat, *texco);
+ break;
+ case MOD_DISP_MAP_OBJECT:
+ VECCOPY(*texco, *co);
+ mul_m4_v3(ob->obmat, *texco);
+ mul_m4_v3(mapob_imat, *texco);
+ break;
+ }
+ }
+}
+
+/* dm must be a CDDerivedMesh */
+static void displaceModifier_do(
+ DisplaceModifierData *dmd, Object *ob,
+ DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
+{
+ int i;
+ MVert *mvert;
+ MDeformVert *dvert = NULL;
+ int defgrp_index;
+ float (*tex_co)[3];
+
+ if(!dmd->texture) return;
+
+ defgrp_index = defgroup_name_index(ob, dmd->defgrp_name);
+
+ mvert = CDDM_get_verts(dm);
+ if(defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ tex_co = MEM_callocN(sizeof(*tex_co) * numVerts,
+ "displaceModifier_do tex_co");
+ get_texture_coords(dmd, ob, dm, vertexCos, tex_co, numVerts);
+
+ for(i = 0; i < numVerts; ++i) {
+ TexResult texres;
+ float delta = 0, strength = dmd->strength;
+ MDeformWeight *def_weight = NULL;
+
+ if(dvert) {
+ int j;
+ for(j = 0; j < dvert[i].totweight; ++j) {
+ if(dvert[i].dw[j].def_nr == defgrp_index) {
+ def_weight = &dvert[i].dw[j];
+ break;
+ }
+ }
+ if(!def_weight) continue;
+ }
+
+ texres.nor = NULL;
+ get_texture_value(dmd->texture, tex_co[i], &texres);
+
+ delta = texres.tin - dmd->midlevel;
+
+ if(def_weight) strength *= def_weight->weight;
+
+ delta *= strength;
+
+ switch(dmd->direction) {
+ case MOD_DISP_DIR_X:
+ vertexCos[i][0] += delta;
+ break;
+ case MOD_DISP_DIR_Y:
+ vertexCos[i][1] += delta;
+ break;
+ case MOD_DISP_DIR_Z:
+ vertexCos[i][2] += delta;
+ break;
+ case MOD_DISP_DIR_RGB_XYZ:
+ vertexCos[i][0] += (texres.tr - dmd->midlevel) * strength;
+ vertexCos[i][1] += (texres.tg - dmd->midlevel) * strength;
+ vertexCos[i][2] += (texres.tb - dmd->midlevel) * strength;
+ break;
+ case MOD_DISP_DIR_NOR:
+ vertexCos[i][0] += delta * mvert[i].no[0] / 32767.0f;
+ vertexCos[i][1] += delta * mvert[i].no[1] / 32767.0f;
+ vertexCos[i][2] += delta * mvert[i].no[2] / 32767.0f;
+ break;
+ }
+ }
+
+ MEM_freeN(tex_co);
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm= get_cddm(md->scene, ob, NULL, derivedData, vertexCos);
+
+ displaceModifier_do((DisplaceModifierData *)md, ob, dm,
+ vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm= get_cddm(md->scene, ob, editData, derivedData, vertexCos);
+
+ displaceModifier_do((DisplaceModifierData *)md, ob, dm,
+ vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Displace = {
+ /* name */ "Displace",
+ /* structName */ "DisplaceModifierData",
+ /* structSize */ sizeof(DisplaceModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ foreachIDLink,
+};
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
new file mode 100644
index 00000000000..2b2d114b6f1
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -0,0 +1,1337 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
+ * or edge angle (can be used to achieve autosmoothing)
+*/
+#if 0
+#define EDGESPLIT_DEBUG_3
+#define EDGESPLIT_DEBUG_2
+#define EDGESPLIT_DEBUG_1
+#define EDGESPLIT_DEBUG_0
+#endif
+
+static void initData(ModifierData *md)
+{
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+
+ /* default to 30-degree split angle, sharpness from both angle & flag
+ */
+ emd->split_angle = 30;
+ emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+ EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
+
+ temd->split_angle = emd->split_angle;
+ temd->flags = emd->flags;
+}
+
+/* Mesh data for edgesplit operation */
+typedef struct SmoothVert {
+ LinkNode *faces; /* all faces which use this vert */
+ int oldIndex; /* the index of the original DerivedMesh vert */
+ int newIndex; /* the index of the new DerivedMesh vert */
+} SmoothVert;
+
+#define SMOOTHEDGE_NUM_VERTS 2
+
+typedef struct SmoothEdge {
+ SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
+ LinkNode *faces; /* all faces which use this edge */
+ int oldIndex; /* the index of the original DerivedMesh edge */
+ int newIndex; /* the index of the new DerivedMesh edge */
+ short flag; /* the flags from the original DerivedMesh edge */
+} SmoothEdge;
+
+#define SMOOTHFACE_MAX_EDGES 4
+
+typedef struct SmoothFace {
+ SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
+ int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
+ float normal[3]; /* the normal of this face */
+ int oldIndex; /* the index of the original DerivedMesh face */
+ int newIndex; /* the index of the new DerivedMesh face */
+} SmoothFace;
+
+typedef struct SmoothMesh {
+ SmoothVert *verts;
+ SmoothEdge *edges;
+ SmoothFace *faces;
+ int num_verts, num_edges, num_faces;
+ int max_verts, max_edges, max_faces;
+ DerivedMesh *dm;
+ float threshold; /* the cosine of the smoothing angle */
+ int flags;
+ MemArena *arena;
+ ListBase propagatestack, reusestack;
+} SmoothMesh;
+
+static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
+{
+ SmoothVert *copy = &mesh->verts[mesh->num_verts];
+
+ if(mesh->num_verts >= mesh->max_verts) {
+ printf("Attempted to add a SmoothMesh vert beyond end of array\n");
+ return NULL;
+ }
+
+ *copy = *vert;
+ copy->faces = NULL;
+ copy->newIndex = mesh->num_verts;
+ ++mesh->num_verts;
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
+#endif
+ return copy;
+}
+
+static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
+{
+ SmoothEdge *copy = &mesh->edges[mesh->num_edges];
+
+ if(mesh->num_edges >= mesh->max_edges) {
+ printf("Attempted to add a SmoothMesh edge beyond end of array\n");
+ return NULL;
+ }
+
+ *copy = *edge;
+ copy->faces = NULL;
+ copy->newIndex = mesh->num_edges;
+ ++mesh->num_edges;
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
+#endif
+ return copy;
+}
+
+static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
+{
+ int i;
+ for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
+ if(edge->verts[i] == vert) return 1;
+
+ return 0;
+}
+
+static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
+ int max_verts, int max_edges, int max_faces)
+{
+ SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
+ mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
+ "SmoothMesh.verts");
+ mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
+ "SmoothMesh.edges");
+ mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
+ "SmoothMesh.faces");
+
+ mesh->num_verts = num_verts;
+ mesh->num_edges = num_edges;
+ mesh->num_faces = num_faces;
+
+ mesh->max_verts = max_verts;
+ mesh->max_edges = max_edges;
+ mesh->max_faces = max_faces;
+
+ return mesh;
+}
+
+static void smoothmesh_free(SmoothMesh *mesh)
+{
+ int i;
+
+ for(i = 0; i < mesh->num_verts; ++i)
+ BLI_linklist_free(mesh->verts[i].faces, NULL);
+
+ for(i = 0; i < mesh->num_edges; ++i)
+ BLI_linklist_free(mesh->edges[i].faces, NULL);
+
+ if(mesh->arena)
+ BLI_memarena_free(mesh->arena);
+
+ MEM_freeN(mesh->verts);
+ MEM_freeN(mesh->edges);
+ MEM_freeN(mesh->faces);
+ MEM_freeN(mesh);
+}
+
+static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
+{
+ int i;
+ SmoothVert *tmp;
+
+ if(max_verts <= mesh->max_verts) return;
+
+ tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
+
+ memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
+
+ /* remap vert pointers in edges */
+ for(i = 0; i < mesh->num_edges; ++i) {
+ int j;
+ SmoothEdge *edge = &mesh->edges[i];
+
+ for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
+ /* pointer arithmetic to get vert array index */
+ edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
+ }
+
+ MEM_freeN(mesh->verts);
+ mesh->verts = tmp;
+ mesh->max_verts = max_verts;
+}
+
+static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
+{
+ int i;
+ SmoothEdge *tmp;
+
+ if(max_edges <= mesh->max_edges) return;
+
+ tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
+
+ memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
+
+ /* remap edge pointers in faces */
+ for(i = 0; i < mesh->num_faces; ++i) {
+ int j;
+ SmoothFace *face = &mesh->faces[i];
+
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
+ if(face->edges[j])
+ /* pointer arithmetic to get edge array index */
+ face->edges[j] = &tmp[face->edges[j] - mesh->edges];
+ }
+
+ MEM_freeN(mesh->edges);
+ mesh->edges = tmp;
+ mesh->max_edges = max_edges;
+}
+
+#ifdef EDGESPLIT_DEBUG_0
+static void smoothmesh_print(SmoothMesh *mesh)
+{
+ int i, j;
+ DerivedMesh *dm = mesh->dm;
+
+ printf("--- SmoothMesh ---\n");
+ printf("--- Vertices ---\n");
+ for(i = 0; i < mesh->num_verts; i++) {
+ SmoothVert *vert = &mesh->verts[i];
+ LinkNode *node;
+ MVert mv;
+
+ dm->getVert(dm, vert->oldIndex, &mv);
+
+ printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
+ i, vert->oldIndex, vert->newIndex,
+ mv.co[0], mv.co[1], mv.co[2]);
+ printf(", faces={");
+ for(node = vert->faces; node != NULL; node = node->next) {
+ printf(" %d", ((SmoothFace *)node->link)->newIndex);
+ }
+ printf("}\n");
+ }
+
+ printf("\n--- Edges ---\n");
+ for(i = 0; i < mesh->num_edges; i++) {
+ SmoothEdge *edge = &mesh->edges[i];
+ LinkNode *node;
+
+ printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
+ i,
+ edge->oldIndex, edge->newIndex,
+ edge->verts[0]->newIndex, edge->verts[1]->newIndex);
+ if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
+ printf(", faces={");
+ for(node = edge->faces; node != NULL; node = node->next) {
+ printf(" %d", ((SmoothFace *)node->link)->newIndex);
+ }
+ printf("}\n");
+ }
+
+ printf("\n--- Faces ---\n");
+ for(i = 0; i < mesh->num_faces; i++) {
+ SmoothFace *face = &mesh->faces[i];
+
+ printf("%4d: indices={%4d, %4d}, edges={", i,
+ face->oldIndex, face->newIndex);
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ if(face->flip[j])
+ printf(" -%-2d", face->edges[j]->newIndex);
+ else
+ printf(" %-2d", face->edges[j]->newIndex);
+ }
+ printf("}, verts={");
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
+ }
+ printf("}\n");
+ }
+}
+#endif
+
+static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
+{
+ SmoothMesh *mesh;
+ EdgeHash *edges = BLI_edgehash_new();
+ int i;
+ int totvert, totedge, totface;
+
+ totvert = dm->getNumVerts(dm);
+ totedge = dm->getNumEdges(dm);
+ totface = dm->getNumFaces(dm);
+
+ mesh = smoothmesh_new(totvert, totedge, totface,
+ totvert, totedge, totface);
+
+ mesh->dm = dm;
+
+ for(i = 0; i < totvert; i++) {
+ SmoothVert *vert = &mesh->verts[i];
+
+ vert->oldIndex = vert->newIndex = i;
+ }
+
+ for(i = 0; i < totedge; i++) {
+ SmoothEdge *edge = &mesh->edges[i];
+ MEdge med;
+
+ dm->getEdge(dm, i, &med);
+ edge->verts[0] = &mesh->verts[med.v1];
+ edge->verts[1] = &mesh->verts[med.v2];
+ edge->oldIndex = edge->newIndex = i;
+ edge->flag = med.flag;
+
+ BLI_edgehash_insert(edges, med.v1, med.v2, edge);
+ }
+
+ for(i = 0; i < totface; i++) {
+ SmoothFace *face = &mesh->faces[i];
+ MFace mf;
+ MVert v1, v2, v3;
+ int j;
+
+ dm->getFace(dm, i, &mf);
+
+ dm->getVert(dm, mf.v1, &v1);
+ dm->getVert(dm, mf.v2, &v2);
+ dm->getVert(dm, mf.v3, &v3);
+ face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
+ if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
+ face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
+ if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
+ if(mf.v4) {
+ MVert v4;
+ dm->getVert(dm, mf.v4, &v4);
+ face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
+ if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
+ face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
+ if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
+ normal_quad_v3( face->normal,v1.co, v2.co, v3.co, v4.co);
+ } else {
+ face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
+ if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
+ face->edges[3] = NULL;
+ normal_tri_v3( face->normal,v1.co, v2.co, v3.co);
+ }
+
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ SmoothEdge *edge = face->edges[j];
+ BLI_linklist_prepend(&edge->faces, face);
+ BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
+ }
+
+ face->oldIndex = face->newIndex = i;
+ }
+
+ BLI_edgehash_free(edges, NULL);
+
+ return mesh;
+}
+
+static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
+{
+ DerivedMesh *result = CDDM_from_template(mesh->dm,
+ mesh->num_verts,
+ mesh->num_edges,
+ mesh->num_faces);
+ MVert *new_verts = CDDM_get_verts(result);
+ MEdge *new_edges = CDDM_get_edges(result);
+ MFace *new_faces = CDDM_get_faces(result);
+ int i;
+
+ for(i = 0; i < mesh->num_verts; ++i) {
+ SmoothVert *vert = &mesh->verts[i];
+ MVert *newMV = &new_verts[vert->newIndex];
+
+ DM_copy_vert_data(mesh->dm, result,
+ vert->oldIndex, vert->newIndex, 1);
+ mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
+ }
+
+ for(i = 0; i < mesh->num_edges; ++i) {
+ SmoothEdge *edge = &mesh->edges[i];
+ MEdge *newME = &new_edges[edge->newIndex];
+
+ DM_copy_edge_data(mesh->dm, result,
+ edge->oldIndex, edge->newIndex, 1);
+ mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
+ newME->v1 = edge->verts[0]->newIndex;
+ newME->v2 = edge->verts[1]->newIndex;
+ }
+
+ for(i = 0; i < mesh->num_faces; ++i) {
+ SmoothFace *face = &mesh->faces[i];
+ MFace *newMF = &new_faces[face->newIndex];
+
+ DM_copy_face_data(mesh->dm, result,
+ face->oldIndex, face->newIndex, 1);
+ mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
+
+ newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
+ newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
+ newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
+
+ if(face->edges[3]) {
+ newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
+ } else {
+ newMF->v4 = 0;
+ }
+ }
+
+ return result;
+}
+
+/* returns the other vert in the given edge
+ */
+static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
+{
+ if(edge->verts[0] == vert) return edge->verts[1];
+ else return edge->verts[0];
+}
+
+/* returns the other edge in the given face that uses the given vert
+ * returns NULL if no other edge in the given face uses the given vert
+ * (this should never happen)
+ */
+static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
+ SmoothEdge *edge)
+{
+ int i,j;
+ for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
+ SmoothEdge *tmp_edge = face->edges[i];
+ if(tmp_edge == edge) continue;
+
+ for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
+ if(tmp_edge->verts[j] == vert) return tmp_edge;
+ }
+
+ /* if we get to here, something's wrong (there should always be 2 edges
+ * which use the same vert in a face)
+ */
+ return NULL;
+}
+
+/* returns a face attached to the given edge which is not the given face.
+ * returns NULL if no other faces use this edge.
+ */
+static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
+{
+ LinkNode *node;
+
+ for(node = edge->faces; node != NULL; node = node->next)
+ if(node->link != face) return node->link;
+
+ return NULL;
+}
+
+#if 0
+/* copies source list to target, overwriting target (target is not freed)
+ * nodes in the copy will be in the same order as in source
+ */
+static void linklist_copy(LinkNode **target, LinkNode *source)
+{
+ LinkNode *node = NULL;
+ *target = NULL;
+
+ for(; source; source = source->next) {
+ if(node) {
+ node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
+ node = node->next;
+} else {
+ node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
+}
+ node->link = source->link;
+ node->next = NULL;
+}
+}
+#endif
+
+ /* appends source to target if it's not already in target */
+ static void linklist_append_unique(LinkNode **target, void *source)
+{
+ LinkNode *node;
+ LinkNode *prev = NULL;
+
+ /* check if source value is already in the list */
+ for(node = *target; node; prev = node, node = node->next)
+ if(node->link == source) return;
+
+ node = MEM_mallocN(sizeof(*node), "nlink");
+ node->next = NULL;
+ node->link = source;
+
+ if(prev) prev->next = node;
+ else *target = node;
+}
+
+/* appends elements of source which aren't already in target to target */
+static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
+{
+ for(; source; source = source->next)
+ linklist_append_unique(target, source->link);
+}
+
+#if 0 /* this is no longer used, it should possibly be removed */
+/* prepends prepend to list - doesn't copy nodes, just joins the lists */
+static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
+{
+ if(prepend) {
+ LinkNode *node = prepend;
+ while(node->next) node = node->next;
+
+ node->next = *list;
+ *list = prepend;
+}
+}
+#endif
+
+/* returns 1 if the linked list contains the given pointer, 0 otherwise
+ */
+static int linklist_contains(LinkNode *list, void *ptr)
+{
+ LinkNode *node;
+
+ for(node = list; node; node = node->next)
+ if(node->link == ptr) return 1;
+
+ return 0;
+}
+
+/* returns 1 if the first linked list is a subset of the second (comparing
+ * pointer values), 0 if not
+ */
+static int linklist_subset(LinkNode *list1, LinkNode *list2)
+{
+ for(; list1; list1 = list1->next)
+ if(!linklist_contains(list2, list1->link))
+ return 0;
+
+ return 1;
+}
+
+#if 0
+/* empties the linked list
+ * frees pointers with freefunc if freefunc is not NULL
+ */
+static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
+{
+ BLI_linklist_free(*list, freefunc);
+ *list = NULL;
+}
+#endif
+
+/* removes the first instance of value from the linked list
+ * frees the pointer with freefunc if freefunc is not NULL
+ */
+static void linklist_remove_first(LinkNode **list, void *value,
+ LinkNodeFreeFP freefunc)
+{
+ LinkNode *node = *list;
+ LinkNode *prev = NULL;
+
+ while(node && node->link != value) {
+ prev = node;
+ node = node->next;
+ }
+
+ if(node) {
+ if(prev)
+ prev->next = node->next;
+ else
+ *list = node->next;
+
+ if(freefunc)
+ freefunc(node->link);
+
+ MEM_freeN(node);
+ }
+}
+
+/* removes all elements in source from target */
+static void linklist_remove_list(LinkNode **target, LinkNode *source,
+ LinkNodeFreeFP freefunc)
+{
+ for(; source; source = source->next)
+ linklist_remove_first(target, source->link, freefunc);
+}
+
+#ifdef EDGESPLIT_DEBUG_0
+static void print_ptr(void *ptr)
+{
+ printf("%p\n", ptr);
+}
+
+static void print_edge(void *ptr)
+{
+ SmoothEdge *edge = ptr;
+ printf(" %4d", edge->newIndex);
+}
+
+static void print_face(void *ptr)
+{
+ SmoothFace *face = ptr;
+ printf(" %4d", face->newIndex);
+}
+#endif
+
+typedef struct ReplaceData {
+ void *find;
+ void *replace;
+} ReplaceData;
+
+static void edge_replace_vert(void *ptr, void *userdata)
+{
+ SmoothEdge *edge = ptr;
+ SmoothVert *find = ((ReplaceData *)userdata)->find;
+ SmoothVert *replace = ((ReplaceData *)userdata)->replace;
+ int i;
+
+#ifdef EDGESPLIT_DEBUG_3
+ printf("replacing vert %4d with %4d in edge %4d",
+ find->newIndex, replace->newIndex, edge->newIndex);
+ printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
+#endif
+
+ for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
+ if(edge->verts[i] == find) {
+ linklist_append_list_unique(&replace->faces, edge->faces);
+ linklist_remove_list(&find->faces, edge->faces, NULL);
+
+ edge->verts[i] = replace;
+ }
+ }
+
+#ifdef EDGESPLIT_DEBUG_3
+ printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
+#endif
+}
+
+static void face_replace_vert(void *ptr, void *userdata)
+{
+ SmoothFace *face = ptr;
+ int i;
+
+ for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
+ edge_replace_vert(face->edges[i], userdata);
+}
+
+static void face_replace_edge(void *ptr, void *userdata)
+{
+ SmoothFace *face = ptr;
+ SmoothEdge *find = ((ReplaceData *)userdata)->find;
+ SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
+ int i;
+
+#ifdef EDGESPLIT_DEBUG_3
+ printf("replacing edge %4d with %4d in face %4d",
+ find->newIndex, replace->newIndex, face->newIndex);
+ if(face->edges[3])
+ printf(": {%2d %2d %2d %2d}",
+ face->edges[0]->newIndex, face->edges[1]->newIndex,
+ face->edges[2]->newIndex, face->edges[3]->newIndex);
+ else
+ printf(": {%2d %2d %2d}",
+ face->edges[0]->newIndex, face->edges[1]->newIndex,
+ face->edges[2]->newIndex);
+#endif
+
+ for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
+ if(face->edges[i] == find) {
+ linklist_remove_first(&face->edges[i]->faces, face, NULL);
+ BLI_linklist_prepend(&replace->faces, face);
+ face->edges[i] = replace;
+ }
+ }
+
+#ifdef EDGESPLIT_DEBUG_3
+ if(face->edges[3])
+ printf(" -> {%2d %2d %2d %2d}\n",
+ face->edges[0]->newIndex, face->edges[1]->newIndex,
+ face->edges[2]->newIndex, face->edges[3]->newIndex);
+ else
+ printf(" -> {%2d %2d %2d}\n",
+ face->edges[0]->newIndex, face->edges[1]->newIndex,
+ face->edges[2]->newIndex);
+#endif
+}
+
+static int edge_is_loose(SmoothEdge *edge)
+{
+ return !(edge->faces && edge->faces->next);
+}
+
+static int edge_is_sharp(SmoothEdge *edge, int flags,
+ float threshold)
+{
+#ifdef EDGESPLIT_DEBUG_1
+ printf("edge %d: ", edge->newIndex);
+#endif
+ if(edge->flag & ME_SHARP) {
+ /* edge can only be sharp if it has at least 2 faces */
+ if(!edge_is_loose(edge)) {
+#ifdef EDGESPLIT_DEBUG_1
+ printf("sharp\n");
+#endif
+ return 1;
+ } else {
+ /* edge is loose, so it can't be sharp */
+ edge->flag &= ~ME_SHARP;
+ }
+ }
+
+#ifdef EDGESPLIT_DEBUG_1
+ printf("not sharp\n");
+#endif
+ return 0;
+}
+
+/* finds another sharp edge which uses vert, by traversing faces around the
+ * vert until it does one of the following:
+ * - hits a loose edge (the edge is returned)
+ * - hits a sharp edge (the edge is returned)
+ * - returns to the start edge (NULL is returned)
+ */
+static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge,
+ LinkNode **visited_faces, float threshold, int flags)
+{
+ SmoothFace *face = NULL;
+ SmoothEdge *edge2 = NULL;
+ /* holds the edges we've seen so we can avoid looping indefinitely */
+ LinkNode *visited_edges = NULL;
+#ifdef EDGESPLIT_DEBUG_1
+ printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
+ edge->newIndex, vert->newIndex);
+#endif
+
+ /* get a face on which to start */
+ if(edge->faces) face = edge->faces->link;
+ else return NULL;
+
+ /* record this edge as visited */
+ BLI_linklist_prepend(&visited_edges, edge);
+
+ /* get the next edge */
+ edge2 = other_edge(face, vert, edge);
+
+ /* record this face as visited */
+ if(visited_faces)
+ BLI_linklist_prepend(visited_faces, face);
+
+ /* search until we hit a loose edge or a sharp edge or an edge we've
+ * seen before
+ */
+ while(face && !edge_is_sharp(edge2, flags, threshold)
+ && !linklist_contains(visited_edges, edge2)) {
+#ifdef EDGESPLIT_DEBUG_3
+ printf("current face %4d; current edge %4d\n", face->newIndex,
+ edge2->newIndex);
+#endif
+ /* get the next face */
+ face = other_face(edge2, face);
+
+ /* if face == NULL, edge2 is a loose edge */
+ if(face) {
+ /* record this face as visited */
+ if(visited_faces)
+ BLI_linklist_prepend(visited_faces, face);
+
+ /* record this edge as visited */
+ BLI_linklist_prepend(&visited_edges, edge2);
+
+ /* get the next edge */
+ edge2 = other_edge(face, vert, edge2);
+#ifdef EDGESPLIT_DEBUG_3
+ printf("next face %4d; next edge %4d\n",
+ face->newIndex, edge2->newIndex);
+ } else {
+ printf("loose edge: %4d\n", edge2->newIndex);
+#endif
+ }
+ }
+
+ /* either we came back to the start edge or we found a sharp/loose edge */
+ if(linklist_contains(visited_edges, edge2))
+ /* we came back to the start edge */
+ edge2 = NULL;
+
+ BLI_linklist_free(visited_edges, NULL);
+
+#ifdef EDGESPLIT_DEBUG_1
+ printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
+ "returning edge %d\n",
+ edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
+#endif
+ return edge2;
+}
+
+static void split_single_vert(SmoothVert *vert, SmoothFace *face,
+ SmoothMesh *mesh)
+{
+ SmoothVert *copy_vert;
+ ReplaceData repdata;
+
+ copy_vert = smoothvert_copy(vert, mesh);
+
+ repdata.find = vert;
+ repdata.replace = copy_vert;
+ face_replace_vert(face, &repdata);
+}
+
+typedef struct PropagateEdge {
+ struct PropagateEdge *next, *prev;
+ SmoothEdge *edge;
+ SmoothVert *vert;
+} PropagateEdge;
+
+static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
+{
+ PropagateEdge *pedge = mesh->reusestack.first;
+
+ if(pedge) {
+ BLI_remlink(&mesh->reusestack, pedge);
+ }
+ else {
+ if(!mesh->arena) {
+ mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+ BLI_memarena_use_calloc(mesh->arena);
+ }
+
+ pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
+ }
+
+ pedge->edge = edge;
+ pedge->vert = vert;
+ BLI_addhead(&mesh->propagatestack, pedge);
+}
+
+static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh)
+{
+ PropagateEdge *pedge = mesh->propagatestack.first;
+
+ if(pedge) {
+ *edge = pedge->edge;
+ *vert = pedge->vert;
+ BLI_remlink(&mesh->propagatestack, pedge);
+ BLI_addhead(&mesh->reusestack, pedge);
+ }
+ else {
+ *edge = NULL;
+ *vert = NULL;
+ }
+}
+
+static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
+
+static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
+ SmoothMesh *mesh)
+{
+ SmoothEdge *edge2;
+ LinkNode *visited_faces = NULL;
+#ifdef EDGESPLIT_DEBUG_1
+ printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
+ edge->newIndex, vert->newIndex);
+#endif
+
+ edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
+ mesh->threshold, mesh->flags);
+
+ if(!edge2) {
+ /* didn't find a sharp or loose edge, so we've hit a dead end */
+ } else if(!edge_is_loose(edge2)) {
+ /* edge2 is not loose, so it must be sharp */
+ if(edge_is_loose(edge)) {
+ /* edge is loose, so we can split edge2 at this vert */
+ split_edge(edge2, vert, mesh);
+ } else if(edge_is_sharp(edge, mesh->flags, mesh->threshold)) {
+ /* both edges are sharp, so we can split the pair at vert */
+ split_edge(edge, vert, mesh);
+ } else {
+ /* edge is not sharp, so try to split edge2 at its other vert */
+ split_edge(edge2, other_vert(edge2, vert), mesh);
+ }
+ } else { /* edge2 is loose */
+ if(edge_is_loose(edge)) {
+ SmoothVert *vert2;
+ ReplaceData repdata;
+
+ /* can't split edge, what should we do with vert? */
+ if(linklist_subset(vert->faces, visited_faces)) {
+ /* vert has only one fan of faces attached; don't split it */
+ } else {
+ /* vert has more than one fan of faces attached; split it */
+ vert2 = smoothvert_copy(vert, mesh);
+
+ /* replace vert with its copy in visited_faces */
+ repdata.find = vert;
+ repdata.replace = vert2;
+ BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
+ }
+ } else {
+ /* edge is not loose, so it must be sharp; split it */
+ split_edge(edge, vert, mesh);
+ }
+ }
+
+ BLI_linklist_free(visited_faces, NULL);
+#ifdef EDGESPLIT_DEBUG_1
+ printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
+ edge->newIndex, vert->newIndex);
+#endif
+}
+
+static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
+{
+ SmoothEdge *edge2;
+ SmoothVert *vert2;
+ ReplaceData repdata;
+ /* the list of faces traversed while looking for a sharp edge */
+ LinkNode *visited_faces = NULL;
+#ifdef EDGESPLIT_DEBUG_1
+ printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
+ edge->newIndex, vert->newIndex);
+#endif
+
+ edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
+ mesh->threshold, mesh->flags);
+
+ if(!edge2) {
+ /* didn't find a sharp or loose edge, so try the other vert */
+ vert2 = other_vert(edge, vert);
+ push_propagate_stack(edge, vert2, mesh);
+ } else if(!edge_is_loose(edge2)) {
+ /* edge2 is not loose, so it must be sharp */
+ SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
+ SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
+ SmoothVert *vert2;
+
+ /* replace edge with its copy in visited_faces */
+ repdata.find = edge;
+ repdata.replace = copy_edge;
+ BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
+
+ /* replace edge2 with its copy in visited_faces */
+ repdata.find = edge2;
+ repdata.replace = copy_edge2;
+ BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
+
+ vert2 = smoothvert_copy(vert, mesh);
+
+ /* replace vert with its copy in visited_faces (must be done after
+ * edge replacement so edges have correct vertices)
+ */
+ repdata.find = vert;
+ repdata.replace = vert2;
+ BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
+
+ /* all copying and replacing is done; the mesh should be consistent.
+ * now propagate the split to the vertices at either end
+ */
+ push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
+ push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh);
+
+ if(smoothedge_has_vert(edge, vert))
+ push_propagate_stack(edge, vert, mesh);
+ } else {
+ /* edge2 is loose */
+ SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
+ SmoothVert *vert2;
+
+ /* replace edge with its copy in visited_faces */
+ repdata.find = edge;
+ repdata.replace = copy_edge;
+ BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
+
+ vert2 = smoothvert_copy(vert, mesh);
+
+ /* replace vert with its copy in visited_faces (must be done after
+ * edge replacement so edges have correct vertices)
+ */
+ repdata.find = vert;
+ repdata.replace = vert2;
+ BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
+
+ /* copying and replacing is done; the mesh should be consistent.
+ * now propagate the split to the vertex at the other end
+ */
+ push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
+
+ if(smoothedge_has_vert(edge, vert))
+ push_propagate_stack(edge, vert, mesh);
+ }
+
+ BLI_linklist_free(visited_faces, NULL);
+#ifdef EDGESPLIT_DEBUG_1
+ printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
+ edge->newIndex, vert->newIndex);
+#endif
+}
+
+static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
+ int flags, int *extra_edges)
+{
+ /* if normal1 dot normal2 < threshold, angle is greater, so split */
+ /* FIXME not sure if this always works */
+ /* 0.00001 added for floating-point rounding */
+ float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
+ int i;
+
+ *extra_edges = 0;
+
+ /* loop through edges, counting potential new ones */
+ for(i = 0; i < mesh->num_edges; i++) {
+ SmoothEdge *edge = &mesh->edges[i];
+ int sharp = 0;
+
+ /* treat all non-manifold edges (3 or more faces) as sharp */
+ if(edge->faces && edge->faces->next && edge->faces->next->next) {
+ LinkNode *node;
+
+ /* this edge is sharp */
+ sharp = 1;
+
+ /* add an extra edge for every face beyond the first */
+ *extra_edges += 2;
+ for(node = edge->faces->next->next->next; node; node = node->next)
+ (*extra_edges)++;
+ } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
+ && !edge_is_loose(edge)) {
+ /* (the edge can only be sharp if we're checking angle or flag,
+ * and it has at least 2 faces) */
+
+ /* if we're checking the sharp flag and it's set, good */
+ if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
+ /* this edge is sharp */
+ sharp = 1;
+
+ (*extra_edges)++;
+ } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
+ /* we know the edge has 2 faces, so check the angle */
+ SmoothFace *face1 = edge->faces->link;
+ SmoothFace *face2 = edge->faces->next->link;
+ float edge_angle_cos = dot_v3v3(face1->normal,
+ face2->normal);
+
+ if(edge_angle_cos < threshold) {
+ /* this edge is sharp */
+ sharp = 1;
+
+ (*extra_edges)++;
+ }
+ }
+ }
+
+ /* set/clear sharp flag appropriately */
+ if(sharp) edge->flag |= ME_SHARP;
+ else edge->flag &= ~ME_SHARP;
+ }
+}
+
+static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
+{
+ SmoothVert *vert;
+ int i;
+ /* if normal1 dot normal2 < threshold, angle is greater, so split */
+ /* FIXME not sure if this always works */
+ /* 0.00001 added for floating-point rounding */
+ mesh->threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
+ mesh->flags = flags;
+
+ /* loop through edges, splitting sharp ones */
+ /* can't use an iterator here, because we'll be adding edges */
+ for(i = 0; i < mesh->num_edges; i++) {
+ SmoothEdge *edge = &mesh->edges[i];
+
+ if(edge_is_sharp(edge, flags, mesh->threshold)) {
+ split_edge(edge, edge->verts[0], mesh);
+
+ do {
+ pop_propagate_stack(&edge, &vert, mesh);
+ if(edge && smoothedge_has_vert(edge, vert))
+ propagate_split(edge, vert, mesh);
+ } while(edge);
+ }
+ }
+}
+
+static int count_bridge_verts(SmoothMesh *mesh)
+{
+ int i, j, count = 0;
+
+ for(i = 0; i < mesh->num_faces; i++) {
+ SmoothFace *face = &mesh->faces[i];
+
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ SmoothEdge *edge = face->edges[j];
+ SmoothEdge *next_edge;
+ SmoothVert *vert = edge->verts[1 - face->flip[j]];
+ int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
+
+ /* wrap next around if at last edge */
+ if(!face->edges[next]) next = 0;
+
+ next_edge = face->edges[next];
+
+ /* if there are other faces sharing this vertex but not
+ * these edges, the vertex will be split, so count it
+ */
+ /* vert has to have at least one face (this one), so faces != 0 */
+ if(!edge->faces->next && !next_edge->faces->next
+ && vert->faces->next) {
+ count++;
+ }
+ }
+ }
+
+ /* each bridge vert will be counted once per face that uses it,
+ * so count is too high, but it's ok for now
+ */
+ return count;
+}
+
+static void split_bridge_verts(SmoothMesh *mesh)
+{
+ int i,j;
+
+ for(i = 0; i < mesh->num_faces; i++) {
+ SmoothFace *face = &mesh->faces[i];
+
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ SmoothEdge *edge = face->edges[j];
+ SmoothEdge *next_edge;
+ SmoothVert *vert = edge->verts[1 - face->flip[j]];
+ int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
+
+ /* wrap next around if at last edge */
+ if(!face->edges[next]) next = 0;
+
+ next_edge = face->edges[next];
+
+ /* if there are other faces sharing this vertex but not
+ * these edges, split the vertex
+ */
+ /* vert has to have at least one face (this one), so faces != 0 */
+ if(!edge->faces->next && !next_edge->faces->next
+ && vert->faces->next)
+ /* FIXME this needs to find all faces that share edges with
+ * this one and split off together
+ */
+ split_single_vert(vert, face, mesh);
+ }
+ }
+}
+
+static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
+ Object *ob, DerivedMesh *dm)
+{
+ SmoothMesh *mesh;
+ DerivedMesh *result;
+ int max_verts, max_edges;
+
+ if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
+ return dm;
+
+ /* 1. make smoothmesh with initial number of elements */
+ mesh = smoothmesh_from_derivedmesh(dm);
+
+ /* 2. count max number of elements to add */
+ tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
+ max_verts = max_edges * 2 + mesh->max_verts;
+ max_verts += count_bridge_verts(mesh);
+ max_edges += mesh->max_edges;
+
+ /* 3. reallocate smoothmesh arrays & copy elements across */
+ /* 4. remap copied elements' pointers to point into the new arrays */
+ smoothmesh_resize_verts(mesh, max_verts);
+ smoothmesh_resize_edges(mesh, max_edges);
+
+#ifdef EDGESPLIT_DEBUG_1
+ printf("********** Pre-split **********\n");
+ smoothmesh_print(mesh);
+#endif
+
+ split_sharp_edges(mesh, emd->split_angle, emd->flags);
+#ifdef EDGESPLIT_DEBUG_1
+ printf("********** Post-edge-split **********\n");
+ smoothmesh_print(mesh);
+#endif
+
+ split_bridge_verts(mesh);
+
+#ifdef EDGESPLIT_DEBUG_1
+ printf("********** Post-vert-split **********\n");
+ smoothmesh_print(mesh);
+#endif
+
+#ifdef EDGESPLIT_DEBUG_0
+ printf("Edgesplit: Estimated %d verts & %d edges, "
+ "found %d verts & %d edges\n", max_verts, max_edges,
+ mesh->num_verts, mesh->num_edges);
+#endif
+
+ result = CDDM_from_smoothmesh(mesh);
+ smoothmesh_free(mesh);
+
+ return result;
+}
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+
+ result = edgesplitModifier_do(emd, ob, derivedData);
+
+ if(result != derivedData)
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+
+ModifierTypeInfo modifierType_EdgeSplit = {
+ /* name */ "EdgeSplit",
+ /* structName */ "EdgeSplitModifierData",
+ /* structSize */ sizeof(EdgeSplitModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
new file mode 100644
index 00000000000..432d1b08ea3
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -0,0 +1,939 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+
+ emd->facepa=0;
+ emd->flag |= eExplodeFlag_Unborn+eExplodeFlag_Alive+eExplodeFlag_Dead;
+}
+static void freeData(ModifierData *md)
+{
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+
+ if(emd->facepa) MEM_freeN(emd->facepa);
+}
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+ ExplodeModifierData *temd= (ExplodeModifierData*) target;
+
+ temd->facepa = 0;
+ temd->flag = emd->flag;
+ temd->protect = emd->protect;
+ temd->vgroup = emd->vgroup;
+}
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+ CustomDataMask dataMask = 0;
+
+ if(emd->vgroup)
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void createFacepa(ExplodeModifierData *emd,
+ ParticleSystemModifierData *psmd,
+ Object *ob, DerivedMesh *dm)
+{
+ ParticleSystem *psys=psmd->psys;
+ MFace *fa=0, *mface=0;
+ MVert *mvert = 0;
+ ParticleData *pa;
+ KDTree *tree;
+ float center[3], co[3];
+ int *facepa=0,*vertpa=0,totvert=0,totface=0,totpart=0;
+ int i,p,v1,v2,v3,v4=0;
+
+ mvert = dm->getVertArray(dm);
+ mface = dm->getFaceArray(dm);
+ totface= dm->getNumFaces(dm);
+ totvert= dm->getNumVerts(dm);
+ totpart= psmd->psys->totpart;
+
+ BLI_srandom(psys->seed);
+
+ if(emd->facepa)
+ MEM_freeN(emd->facepa);
+
+ facepa = emd->facepa = MEM_callocN(sizeof(int)*totface, "explode_facepa");
+
+ vertpa = MEM_callocN(sizeof(int)*totvert, "explode_vertpa");
+
+ /* initialize all faces & verts to no particle */
+ for(i=0; i<totface; i++)
+ facepa[i]=totpart;
+
+ for (i=0; i<totvert; i++)
+ vertpa[i]=totpart;
+
+ /* set protected verts */
+ if(emd->vgroup){
+ MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+ float val;
+ if(dvert){
+ int defgrp_index= emd->vgroup-1;
+ for(i=0; i<totvert; i++, dvert++){
+ val = BLI_frand();
+ val = (1.0f-emd->protect)*val + emd->protect*0.5f;
+ if(val < defvert_find_weight(dvert, defgrp_index))
+ vertpa[i] = -1;
+ }
+ }
+ }
+
+ /* make tree of emitter locations */
+ tree=BLI_kdtree_new(totpart);
+ for(p=0,pa=psys->particles; p<totpart; p++,pa++){
+ psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,0,0);
+ BLI_kdtree_insert(tree, p, co, NULL);
+ }
+ BLI_kdtree_balance(tree);
+
+ /* set face-particle-indexes to nearest particle to face center */
+ for(i=0,fa=mface; i<totface; i++,fa++){
+ add_v3_v3v3(center,mvert[fa->v1].co,mvert[fa->v2].co);
+ add_v3_v3v3(center,center,mvert[fa->v3].co);
+ if(fa->v4){
+ add_v3_v3v3(center,center,mvert[fa->v4].co);
+ mul_v3_fl(center,0.25);
+ }
+ else
+ mul_v3_fl(center,0.3333f);
+
+ p= BLI_kdtree_find_nearest(tree,center,NULL,NULL);
+
+ v1=vertpa[fa->v1];
+ v2=vertpa[fa->v2];
+ v3=vertpa[fa->v3];
+ if(fa->v4)
+ v4=vertpa[fa->v4];
+
+ if(v1>=0 && v2>=0 && v3>=0 && (fa->v4==0 || v4>=0))
+ facepa[i]=p;
+
+ if(v1>=0) vertpa[fa->v1]=p;
+ if(v2>=0) vertpa[fa->v2]=p;
+ if(v3>=0) vertpa[fa->v3]=p;
+ if(fa->v4 && v4>=0) vertpa[fa->v4]=p;
+ }
+
+ if(vertpa) MEM_freeN(vertpa);
+ BLI_kdtree_free(tree);
+}
+
+static int edgesplit_get(EdgeHash *edgehash, int v1, int v2)
+{
+ return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2));
+}
+
+static DerivedMesh * splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
+ DerivedMesh *splitdm;
+ MFace *mf=0,*df1=0,*df2=0,*df3=0;
+ MFace *mface=CDDM_get_faces(dm);
+ MVert *dupve, *mv;
+ EdgeHash *edgehash;
+ EdgeHashIterator *ehi;
+ int totvert=dm->getNumVerts(dm);
+ int totface=dm->getNumFaces(dm);
+
+ int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_facesplit");
+ int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2");
+ int *facepa = emd->facepa;
+ int *fs, totesplit=0,totfsplit=0,totin=0,curdupvert=0,curdupface=0,curdupin=0;
+ int i,j,v1,v2,v3,v4,esplit;
+
+ edgehash= BLI_edgehash_new();
+
+ /* recreate vertpa from facepa calculation */
+ for (i=0,mf=mface; i<totface; i++,mf++) {
+ vertpa[mf->v1]=facepa[i];
+ vertpa[mf->v2]=facepa[i];
+ vertpa[mf->v3]=facepa[i];
+ if(mf->v4)
+ vertpa[mf->v4]=facepa[i];
+ }
+
+ /* mark edges for splitting and how to split faces */
+ for (i=0,mf=mface,fs=facesplit; i<totface; i++,mf++,fs++) {
+ if(mf->v4){
+ v1=vertpa[mf->v1];
+ v2=vertpa[mf->v2];
+ v3=vertpa[mf->v3];
+ v4=vertpa[mf->v4];
+
+ if(v1!=v2){
+ BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL);
+ (*fs)++;
+ }
+
+ if(v2!=v3){
+ BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL);
+ (*fs)++;
+ }
+
+ if(v3!=v4){
+ BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL);
+ (*fs)++;
+ }
+
+ if(v1!=v4){
+ BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL);
+ (*fs)++;
+ }
+
+ if(*fs==2){
+ if((v1==v2 && v3==v4) || (v1==v4 && v2==v3))
+ *fs=1;
+ else if(v1!=v2){
+ if(v1!=v4)
+ BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL);
+ else
+ BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL);
+ }
+ else{
+ if(v1!=v4)
+ BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL);
+ else
+ BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL);
+ }
+ }
+ }
+ }
+
+ /* count splits & reindex */
+ ehi= BLI_edgehashIterator_new(edgehash);
+ totesplit=totvert;
+ for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totesplit));
+ totesplit++;
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /* count new faces due to splitting */
+ for(i=0,fs=facesplit; i<totface; i++,fs++){
+ if(*fs==1)
+ totfsplit+=1;
+ else if(*fs==2)
+ totfsplit+=2;
+ else if(*fs==3)
+ totfsplit+=3;
+ else if(*fs==4){
+ totfsplit+=3;
+
+ mf=dm->getFaceData(dm,i,CD_MFACE);//CDDM_get_face(dm,i);
+
+ if(vertpa[mf->v1]!=vertpa[mf->v2] && vertpa[mf->v2]!=vertpa[mf->v3])
+ totin++;
+ }
+ }
+
+ splitdm= CDDM_from_template(dm, totesplit+totin, dm->getNumEdges(dm),totface+totfsplit);
+
+ /* copy new faces & verts (is it really this painful with custom data??) */
+ for(i=0; i<totvert; i++){
+ MVert source;
+ MVert *dest;
+ dm->getVert(dm, i, &source);
+ dest = CDDM_get_vert(splitdm, i);
+
+ DM_copy_vert_data(dm, splitdm, i, i, 1);
+ *dest = source;
+ }
+ for(i=0; i<totface; i++){
+ MFace source;
+ MFace *dest;
+ dm->getFace(dm, i, &source);
+ dest = CDDM_get_face(splitdm, i);
+
+ DM_copy_face_data(dm, splitdm, i, i, 1);
+ *dest = source;
+ }
+
+ /* override original facepa (original pointer is saved in caller function) */
+ facepa= MEM_callocN(sizeof(int)*(totface+totfsplit),"explode_facepa");
+ memcpy(facepa,emd->facepa,totface*sizeof(int));
+ emd->facepa=facepa;
+
+ /* create new verts */
+ curdupvert=totvert;
+ ehi= BLI_edgehashIterator_new(edgehash);
+ for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ BLI_edgehashIterator_getKey(ehi, &i, &j);
+ esplit= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
+ mv=CDDM_get_vert(splitdm,j);
+ dupve=CDDM_get_vert(splitdm,esplit);
+
+ DM_copy_vert_data(splitdm,splitdm,j,esplit,1);
+
+ *dupve=*mv;
+
+ mv=CDDM_get_vert(splitdm,i);
+
+ VECADD(dupve->co,dupve->co,mv->co);
+ mul_v3_fl(dupve->co,0.5);
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /* create new faces */
+ curdupface=totface;
+ curdupin=totesplit;
+ for(i=0,fs=facesplit; i<totface; i++,fs++){
+ if(*fs){
+ mf=CDDM_get_face(splitdm,i);
+
+ v1=vertpa[mf->v1];
+ v2=vertpa[mf->v2];
+ v3=vertpa[mf->v3];
+ v4=vertpa[mf->v4];
+ /* ouch! creating new faces & remapping them to new verts is no fun */
+ if(*fs==1){
+ df1=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df1=*mf;
+ curdupface++;
+
+ if(v1==v2){
+ df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
+ df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
+ mf->v3=df1->v2;
+ mf->v4=df1->v1;
+ }
+ else{
+ df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4);
+ mf->v2=df1->v1;
+ mf->v3=df1->v4;
+ }
+
+ facepa[i]=v1;
+ facepa[curdupface-1]=v3;
+
+ test_index_face(df1, &splitdm->faceData, curdupface, (df1->v4 ? 4 : 3));
+ }
+ if(*fs==2){
+ df1=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df1=*mf;
+ curdupface++;
+
+ df2=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df2=*mf;
+ curdupface++;
+
+ if(v1!=v2){
+ if(v1!=v4){
+ df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
+ df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df2->v1=df1->v3=mf->v2;
+ df2->v3=df1->v4=mf->v4;
+ df2->v2=mf->v3;
+
+ mf->v2=df1->v2;
+ mf->v3=df1->v1;
+
+ df2->v4=mf->v4=0;
+
+ facepa[i]=v1;
+ }
+ else{
+ df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
+ df1->v4=mf->v3;
+ df2->v2=mf->v3;
+ df2->v3=mf->v4;
+
+ mf->v1=df1->v2;
+ mf->v3=df1->v3;
+
+ df2->v4=mf->v4=0;
+
+ facepa[i]=v2;
+ }
+ facepa[curdupface-1]=facepa[curdupface-2]=v3;
+ }
+ else{
+ if(v1!=v4){
+ df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
+ df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
+ df1->v2=mf->v3;
+
+ mf->v1=df1->v4;
+ mf->v2=df1->v3;
+ mf->v3=mf->v4;
+
+ df2->v4=mf->v4=0;
+
+ facepa[i]=v4;
+ }
+ else{
+ df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
+ df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4);
+ df1->v1=mf->v4;
+ df1->v2=mf->v2;
+ df2->v3=mf->v4;
+
+ mf->v1=df1->v4;
+ mf->v2=df1->v3;
+
+ df2->v4=mf->v4=0;
+
+ facepa[i]=v3;
+ }
+
+ facepa[curdupface-1]=facepa[curdupface-2]=v1;
+ }
+
+ test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
+ test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
+ }
+ else if(*fs==3){
+ df1=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df1=*mf;
+ curdupface++;
+
+ df2=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df2=*mf;
+ curdupface++;
+
+ df3=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df3=*mf;
+ curdupface++;
+
+ if(v1==v2){
+ df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
+ df3->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
+ df3->v3=df2->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
+ df3->v2=mf->v3;
+ df2->v3=mf->v4;
+ df1->v4=df2->v4=df3->v4=0;
+
+ mf->v3=df1->v2;
+ mf->v4=df1->v1;
+
+ facepa[i]=facepa[curdupface-3]=v1;
+ facepa[curdupface-1]=v3;
+ facepa[curdupface-2]=v4;
+ }
+ else if(v2==v3){
+ df3->v1=df2->v3=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
+ df2->v2=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df3->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
+
+ df3->v3=mf->v4;
+ df2->v1=mf->v1;
+ df1->v4=df2->v4=df3->v4=0;
+
+ mf->v1=df1->v2;
+ mf->v4=df1->v3;
+
+ facepa[i]=facepa[curdupface-3]=v2;
+ facepa[curdupface-1]=v4;
+ facepa[curdupface-2]=v1;
+ }
+ else if(v3==v4){
+ df3->v2=df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df2->v3=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
+ df3->v3=df1->v3=edgesplit_get(edgehash, mf->v1, mf->v4);
+
+ df3->v1=mf->v1;
+ df2->v2=mf->v2;
+ df1->v4=df2->v4=df3->v4=0;
+
+ mf->v1=df1->v3;
+ mf->v2=df1->v2;
+
+ facepa[i]=facepa[curdupface-3]=v3;
+ facepa[curdupface-1]=v1;
+ facepa[curdupface-2]=v2;
+ }
+ else{
+ df3->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df3->v3=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
+ df2->v3=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
+
+ df3->v2=mf->v2;
+ df2->v2=mf->v3;
+ df1->v4=df2->v4=df3->v4=0;
+
+ mf->v2=df1->v1;
+ mf->v3=df1->v3;
+
+ facepa[i]=facepa[curdupface-3]=v1;
+ facepa[curdupface-1]=v2;
+ facepa[curdupface-2]=v3;
+ }
+
+ test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
+ test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
+ test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
+ }
+ else if(*fs==4){
+ if(v1!=v2 && v2!=v3){
+
+ /* set new vert to face center */
+ mv=CDDM_get_vert(splitdm,mf->v1);
+ dupve=CDDM_get_vert(splitdm,curdupin);
+ DM_copy_vert_data(splitdm,splitdm,mf->v1,curdupin,1);
+ *dupve=*mv;
+
+ mv=CDDM_get_vert(splitdm,mf->v2);
+ VECADD(dupve->co,dupve->co,mv->co);
+ mv=CDDM_get_vert(splitdm,mf->v3);
+ VECADD(dupve->co,dupve->co,mv->co);
+ mv=CDDM_get_vert(splitdm,mf->v4);
+ VECADD(dupve->co,dupve->co,mv->co);
+ mul_v3_fl(dupve->co,0.25);
+
+
+ df1=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df1=*mf;
+ curdupface++;
+
+ df2=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df2=*mf;
+ curdupface++;
+
+ df3=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df3=*mf;
+ curdupface++;
+
+ df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df3->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
+
+ df2->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
+ df3->v4=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
+
+ df3->v1=df2->v2=df1->v4=curdupin;
+
+ mf->v2=df1->v1;
+ mf->v3=curdupin;
+ mf->v4=df2->v1;
+
+ curdupin++;
+
+ facepa[i]=v1;
+ facepa[curdupface-3]=v2;
+ facepa[curdupface-2]=v3;
+ facepa[curdupface-1]=v4;
+
+ test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
+
+ test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
+ test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
+ }
+ else{
+ df1=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df1=*mf;
+ curdupface++;
+
+ df2=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df2=*mf;
+ curdupface++;
+
+ df3=CDDM_get_face(splitdm,curdupface);
+ DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ *df3=*mf;
+ curdupface++;
+
+ if(v2==v3){
+ df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df3->v1=df1->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
+ df2->v1=df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
+
+ df3->v3=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
+
+ df3->v2=mf->v3;
+ df3->v4=0;
+
+ mf->v2=df1->v1;
+ mf->v3=df1->v4;
+ mf->v4=0;
+
+ facepa[i]=v1;
+ facepa[curdupface-3]=facepa[curdupface-2]=v2;
+ facepa[curdupface-1]=v3;
+ }
+ else{
+ df3->v1=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
+ df2->v4=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
+ df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
+
+ df3->v3=df2->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
+
+ df3->v4=0;
+
+ mf->v1=df1->v4;
+ mf->v2=df1->v3;
+ mf->v3=mf->v4;
+ mf->v4=0;
+
+ facepa[i]=v4;
+ facepa[curdupface-3]=facepa[curdupface-2]=v1;
+ facepa[curdupface-1]=v2;
+ }
+
+ test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
+ test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
+ test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
+ }
+ }
+
+ test_index_face(df1, &splitdm->faceData, i, (df1->v4 ? 4 : 3));
+ }
+ }
+
+ BLI_edgehash_free(edgehash, NULL);
+ MEM_freeN(facesplit);
+ MEM_freeN(vertpa);
+
+ return splitdm;
+
+}
+static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
+ ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
+ DerivedMesh *to_explode)
+{
+ DerivedMesh *explode, *dm=to_explode;
+ MFace *mf=0, *mface;
+ ParticleSettings *part=psmd->psys->part;
+ ParticleSimulationData sim = {scene, ob, psmd->psys, psmd};
+ ParticleData *pa=NULL, *pars=psmd->psys->particles;
+ ParticleKey state;
+ EdgeHash *vertpahash;
+ EdgeHashIterator *ehi;
+ float *vertco=0, imat[4][4];
+ float loc0[3], nor[3];
+ float timestep, cfra;
+ int *facepa=emd->facepa;
+ int totdup=0,totvert=0,totface=0,totpart=0;
+ int i, j, v, mindex=0;
+
+ totface= dm->getNumFaces(dm);
+ totvert= dm->getNumVerts(dm);
+ mface= dm->getFaceArray(dm);
+ totpart= psmd->psys->totpart;
+
+ timestep= psys_get_timestep(&sim);
+
+ //if(part->flag & PART_GLOB_TIME)
+ cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0);
+ //else
+ // cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0);
+
+ /* hash table for vertice <-> particle relations */
+ vertpahash= BLI_edgehash_new();
+
+ for (i=0; i<totface; i++) {
+ /* do mindex + totvert to ensure the vertex index to be the first
+ * with BLI_edgehashIterator_getKey */
+ if(facepa[i]==totpart || cfra <= (pars+facepa[i])->time)
+ mindex = totvert+totpart;
+ else
+ mindex = totvert+facepa[i];
+
+ mf= &mface[i];
+
+ /* set face vertices to exist in particle group */
+ BLI_edgehash_insert(vertpahash, mf->v1, mindex, NULL);
+ BLI_edgehash_insert(vertpahash, mf->v2, mindex, NULL);
+ BLI_edgehash_insert(vertpahash, mf->v3, mindex, NULL);
+ if(mf->v4)
+ BLI_edgehash_insert(vertpahash, mf->v4, mindex, NULL);
+ }
+
+ /* make new vertice indexes & count total vertices after duplication */
+ ehi= BLI_edgehashIterator_new(vertpahash);
+ for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup));
+ totdup++;
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /* the final duplicated vertices */
+ explode= CDDM_from_template(dm, totdup, 0,totface);
+ /*dupvert= CDDM_get_verts(explode);*/
+
+ /* getting back to object space */
+ invert_m4_m4(imat,ob->obmat);
+
+ psmd->psys->lattice = psys_get_lattice(&sim);
+
+ /* duplicate & displace vertices */
+ ehi= BLI_edgehashIterator_new(vertpahash);
+ for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ MVert source;
+ MVert *dest;
+
+ /* get particle + vertex from hash */
+ BLI_edgehashIterator_getKey(ehi, &j, &i);
+ i -= totvert;
+ v= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
+
+ dm->getVert(dm, j, &source);
+ dest = CDDM_get_vert(explode,v);
+
+ DM_copy_vert_data(dm,explode,j,v,1);
+ *dest = source;
+
+ if(i!=totpart) {
+ /* get particle */
+ pa= pars+i;
+
+ /* get particle state */
+ psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc0,nor,0,0,0,0);
+ mul_m4_v3(ob->obmat,loc0);
+
+ state.time=cfra;
+ psys_get_particle_state(&sim, i, &state, 1);
+
+ vertco=CDDM_get_vert(explode,v)->co;
+
+ mul_m4_v3(ob->obmat,vertco);
+
+ VECSUB(vertco,vertco,loc0);
+
+ /* apply rotation, size & location */
+ mul_qt_v3(state.rot,vertco);
+ if(emd->flag & eExplodeFlag_PaSize)
+ mul_v3_fl(vertco,pa->size);
+ VECADD(vertco,vertco,state.co);
+
+ mul_m4_v3(imat,vertco);
+ }
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /*map new vertices to faces*/
+ for (i=0; i<totface; i++) {
+ MFace source;
+ int orig_v4;
+
+ if(facepa[i]!=totpart)
+ {
+ pa=pars+facepa[i];
+
+ if(pa->alive==PARS_UNBORN && (emd->flag&eExplodeFlag_Unborn)==0) continue;
+ if(pa->alive==PARS_ALIVE && (emd->flag&eExplodeFlag_Alive)==0) continue;
+ if(pa->alive==PARS_DEAD && (emd->flag&eExplodeFlag_Dead)==0) continue;
+ }
+
+ dm->getFace(dm,i,&source);
+ mf=CDDM_get_face(explode,i);
+
+ orig_v4 = source.v4;
+
+ if(facepa[i]!=totpart && cfra <= pa->time)
+ mindex = totvert+totpart;
+ else
+ mindex = totvert+facepa[i];
+
+ source.v1 = edgesplit_get(vertpahash, source.v1, mindex);
+ source.v2 = edgesplit_get(vertpahash, source.v2, mindex);
+ source.v3 = edgesplit_get(vertpahash, source.v3, mindex);
+ if(source.v4)
+ source.v4 = edgesplit_get(vertpahash, source.v4, mindex);
+
+ DM_copy_face_data(dm,explode,i,i,1);
+
+ *mf = source;
+
+ test_index_face(mf, &explode->faceData, i, (orig_v4 ? 4 : 3));
+ }
+
+ /* cleanup */
+ BLI_edgehash_free(vertpahash, NULL);
+
+ /* finalization */
+ CDDM_calc_edges(explode);
+ CDDM_calc_normals(explode);
+
+ if(psmd->psys->lattice){
+ end_latt_deform(psmd->psys->lattice);
+ psmd->psys->lattice= NULL;
+ }
+
+ return explode;
+}
+
+static ParticleSystemModifierData * findPrecedingParticlesystem(Object *ob, ModifierData *emd)
+{
+ ModifierData *md;
+ ParticleSystemModifierData *psmd=0;
+
+ for (md=ob->modifiers.first; emd!=md; md=md->next){
+ if(md->type==eModifierType_ParticleSystem)
+ psmd= (ParticleSystemModifierData*) md;
+ }
+ return psmd;
+}
+static DerivedMesh * applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = derivedData;
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+ ParticleSystemModifierData *psmd=findPrecedingParticlesystem(ob,md);
+
+ if(psmd){
+ ParticleSystem * psys=psmd->psys;
+
+ if(psys==0 || psys->totpart==0) return derivedData;
+ if(psys->part==0 || psys->particles==0) return derivedData;
+ if(psmd->dm==0) return derivedData;
+
+ /* 1. find faces to be exploded if needed */
+ if(emd->facepa==0
+ || psmd->flag&eParticleSystemFlag_Pars
+ || emd->flag&eExplodeFlag_CalcFaces
+ || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumFaces(dm)){
+ if(psmd->flag & eParticleSystemFlag_Pars)
+ psmd->flag &= ~eParticleSystemFlag_Pars;
+
+ if(emd->flag & eExplodeFlag_CalcFaces)
+ emd->flag &= ~eExplodeFlag_CalcFaces;
+
+ createFacepa(emd,psmd,ob,derivedData);
+ }
+
+ /* 2. create new mesh */
+ if(emd->flag & eExplodeFlag_EdgeSplit){
+ int *facepa = emd->facepa;
+ DerivedMesh *splitdm=splitEdges(emd,dm);
+ DerivedMesh *explode=explodeMesh(emd, psmd, md->scene, ob, splitdm);
+
+ MEM_freeN(emd->facepa);
+ emd->facepa=facepa;
+ splitdm->release(splitdm);
+ return explode;
+ }
+ else
+ return explodeMesh(emd, psmd, md->scene, ob, derivedData);
+ }
+ return derivedData;
+}
+
+
+ModifierTypeInfo modifierType_Explode = {
+ /* name */ "Explode",
+ /* structName */ "ExplodeModifierData",
+ /* structSize */ sizeof(ExplodeModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh,
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ freeData,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
new file mode 100644
index 00000000000..34a15ed7856
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -0,0 +1,198 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_fluidsim_util.h"
+
+
+/* Fluidsim */
+static void initData(ModifierData *md)
+{
+ FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
+
+ fluidsim_init(fluidmd);
+}
+static void freeData(ModifierData *md)
+{
+ FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
+
+ fluidsim_free(fluidmd);
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
+ FluidsimModifierData *tfluidmd= (FluidsimModifierData*) target;
+
+ if(tfluidmd->fss)
+ MEM_freeN(tfluidmd->fss);
+
+ tfluidmd->fss = MEM_dupallocN(fluidmd->fss);
+}
+
+
+
+static DerivedMesh * applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
+ DerivedMesh *result = NULL;
+
+ /* check for alloc failing */
+ if(!fluidmd->fss)
+ {
+ initData(md);
+
+ if(!fluidmd->fss)
+ return derivedData;
+ }
+
+ result = fluidsimModifier_do(fluidmd, md->scene, ob, derivedData, useRenderParams, isFinalCalc);
+
+ if(result)
+ {
+ return result;
+ }
+
+ return derivedData;
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
+ Base *base;
+
+ if(fluidmd && fluidmd->fss)
+ {
+ if(fluidmd->fss->type == OB_FLUIDSIM_DOMAIN)
+ {
+ for(base = scene->base.first; base; base= base->next)
+ {
+ Object *ob1= base->object;
+ if(ob1 != ob)
+ {
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim);
+
+ // only put dependancies from NON-DOMAIN fluids in here
+ if(fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type!=OB_FLUIDSIM_DOMAIN))
+ {
+ DagNode *curNode = dag_get_node(forest, ob1);
+ dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Fluidsim Object");
+ }
+ }
+ }
+ }
+ }
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+
+ModifierTypeInfo modifierType_Fluidsim = {
+ /* name */ "Fluidsim",
+ /* structName */ "FluidsimModifierData",
+ /* structSize */ sizeof(FluidsimModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_RequiresOriginalData
+ | eModifierTypeFlag_Single,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ freeData,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c
new file mode 100644
index 00000000000..d9bfd25f45f
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c
@@ -0,0 +1,669 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+// headers for fluidsim bobj meshes
+#include <stdlib.h>
+#include "LBM_fluidsim.h"
+#include <zlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_fluidsim_util.h"
+
+
+#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_fluidsim.h"
+#include "DNA_object_force.h" // for pointcache
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h" // N_T
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_modifier.h"
+#include "BKE_mesh.h"
+#include "BKE_pointcache.h"
+#include "BKE_utildefines.h"
+
+#include "BLO_sys_types.h"
+
+void fluidsim_init(FluidsimModifierData *fluidmd)
+{
+#ifndef DISABLE_ELBEEM
+ if(fluidmd)
+ {
+ FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");
+
+ fluidmd->fss = fss;
+
+ if(!fss)
+ return;
+
+ fss->fmd = fluidmd;
+ fss->type = OB_FLUIDSIM_ENABLE;
+ fss->show_advancedoptions = 0;
+
+ fss->resolutionxyz = 65;
+ fss->previewresxyz = 45;
+ fss->realsize = 0.5;
+ fss->guiDisplayMode = 2; // preview
+ fss->renderDisplayMode = 3; // render
+
+ fss->viscosityMode = 2; // default to water
+ fss->viscosityValue = 1.0;
+ fss->viscosityExponent = 6;
+
+ // dg TODO: change this to []
+ fss->gravx = 0.0;
+ fss->gravy = 0.0;
+ fss->gravz = -9.81;
+ fss->animStart = 0.0;
+ fss->animEnd = 4.0;
+ fss->gstar = 0.005; // used as normgstar
+ fss->maxRefine = -1;
+ // maxRefine is set according to resolutionxyz during bake
+
+ // fluid/inflow settings
+ // fss->iniVel --> automatically set to 0
+
+ /* elubie: changed this to default to the same dir as the render output
+ to prevent saving to C:\ on Windows */
+ BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX);
+
+ // first init of bounding box
+ // no bounding box needed
+
+ // todo - reuse default init from elbeem!
+ fss->typeFlags = OB_FSBND_PARTSLIP;
+ fss->domainNovecgen = 0;
+ fss->volumeInitType = 1; // volume
+ fss->partSlipValue = 0.2;
+
+ fss->generateTracers = 0;
+ fss->generateParticles = 0.0;
+ fss->surfaceSmoothing = 1.0;
+ fss->surfaceSubdivs = 0.0;
+ fss->particleInfSize = 0.0;
+ fss->particleInfAlpha = 0.0;
+
+ // init fluid control settings
+ fss->attractforceStrength = 0.2;
+ fss->attractforceRadius = 0.75;
+ fss->velocityforceStrength = 0.2;
+ fss->velocityforceRadius = 0.75;
+ fss->cpsTimeStart = fss->animStart;
+ fss->cpsTimeEnd = fss->animEnd;
+ fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
+
+ /*
+ BAD TODO: this is done in buttons_object.c in the moment
+ Mesh *mesh = ob->data;
+ // calculate bounding box
+ fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
+ */
+
+ // (ab)used to store velocities
+ fss->meshSurfNormals = NULL;
+
+ fss->lastgoodframe = -1;
+
+ fss->flag |= OB_FLUIDSIM_ACTIVE;
+
+ }
+#endif
+ return;
+}
+
+void fluidsim_free(FluidsimModifierData *fluidmd)
+{
+#ifndef DISABLE_ELBEEM
+ if(fluidmd)
+ {
+ if(fluidmd->fss->meshSurfNormals)
+ {
+ MEM_freeN(fluidmd->fss->meshSurfNormals);
+ fluidmd->fss->meshSurfNormals = NULL;
+ }
+ MEM_freeN(fluidmd->fss);
+ }
+#endif
+ return;
+}
+
+#ifndef DISABLE_ELBEEM
+/* read .bobj.gz file into a fluidsimDerivedMesh struct */
+DerivedMesh *fluidsim_read_obj(char *filename)
+{
+ int wri,i,j;
+ float wrf;
+ int gotBytes;
+ gzFile gzf;
+ int numverts = 0, numfaces = 0;
+ DerivedMesh *dm = NULL;
+ MFace *mface;
+ MVert *mvert;
+ short *normals;
+
+ // ------------------------------------------------
+ // get numverts + numfaces first
+ // ------------------------------------------------
+ gzf = gzopen(filename, "rb");
+ if (!gzf)
+ {
+ return NULL;
+ }
+
+ // read numverts
+ gotBytes = gzread(gzf, &wri, sizeof(wri));
+ numverts = wri;
+
+ // skip verts
+ for(i=0; i<numverts*3; i++)
+ {
+ gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
+ }
+
+ // read number of normals
+ gotBytes = gzread(gzf, &wri, sizeof(wri));
+
+ // skip normals
+ for(i=0; i<numverts*3; i++)
+ {
+ gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
+ }
+
+ /* get no. of triangles */
+ gotBytes = gzread(gzf, &wri, sizeof(wri));
+ numfaces = wri;
+
+ gzclose( gzf );
+ // ------------------------------------------------
+
+ if(!numfaces || !numverts)
+ return NULL;
+
+ gzf = gzopen(filename, "rb");
+ if (!gzf)
+ {
+ return NULL;
+ }
+
+ dm = CDDM_new(numverts, 0, numfaces);
+
+ if(!dm)
+ {
+ gzclose( gzf );
+ return NULL;
+ }
+
+ // read numverts
+ gotBytes = gzread(gzf, &wri, sizeof(wri));
+
+ // read vertex position from file
+ mvert = CDDM_get_verts(dm);
+ for(i=0; i<numverts; i++)
+ {
+ MVert *mv = &mvert[i];
+
+ for(j=0; j<3; j++)
+ {
+ gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
+ mv->co[j] = wrf;
+ }
+ }
+
+ // should be the same as numverts
+ gotBytes = gzread(gzf, &wri, sizeof(wri));
+ if(wri != numverts)
+ {
+ if(dm)
+ dm->release(dm);
+ gzclose( gzf );
+ return NULL;
+ }
+
+ normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" );
+ if(!normals)
+ {
+ if(dm)
+ dm->release(dm);
+ gzclose( gzf );
+ return NULL;
+ }
+
+ // read normals from file (but don't save them yet)
+ for(i=0; i<numverts*3; i++)
+ {
+ gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
+ normals[i] = (short)(wrf*32767.0f);
+ }
+
+ /* read no. of triangles */
+ gotBytes = gzread(gzf, &wri, sizeof(wri));
+
+ if(wri!=numfaces)
+ printf("Fluidsim: error in reading data from file.\n");
+
+ // read triangles from file
+ mface = CDDM_get_faces(dm);
+ for(i=0; i<numfaces; i++)
+ {
+ int face[4];
+ MFace *mf = &mface[i];
+
+ gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] ));
+ gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] ));
+ gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] ));
+ face[3] = 0;
+
+ // check if 3rd vertex has index 0 (not allowed in blender)
+ if(face[2])
+ {
+ mf->v1 = face[0];
+ mf->v2 = face[1];
+ mf->v3 = face[2];
+ }
+ else
+ {
+ mf->v1 = face[1];
+ mf->v2 = face[2];
+ mf->v3 = face[0];
+ }
+ mf->v4 = face[3];
+
+ test_index_face(mf, NULL, 0, 3);
+ }
+
+ gzclose( gzf );
+
+ CDDM_calc_edges(dm);
+
+ CDDM_apply_vert_normals(dm, (short (*)[3])normals);
+ MEM_freeN(normals);
+
+ // CDDM_calc_normals(result);
+
+ return dm;
+}
+
+
+void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
+ /*RET*/ float start[3], /*RET*/ float size[3] )
+{
+ float bbsx=0.0, bbsy=0.0, bbsz=0.0;
+ float bbex=1.0, bbey=1.0, bbez=1.0;
+ int i;
+ float vec[3];
+
+ if(totvert == 0) {
+ zero_v3(start);
+ zero_v3(size);
+ return;
+ }
+
+ VECCOPY(vec, mvert[0].co);
+ mul_m4_v3(obmat, vec);
+ bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
+ bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
+
+ for(i = 1; i < totvert; i++) {
+ VECCOPY(vec, mvert[i].co);
+ mul_m4_v3(obmat, vec);
+
+ if(vec[0] < bbsx){ bbsx= vec[0]; }
+ if(vec[1] < bbsy){ bbsy= vec[1]; }
+ if(vec[2] < bbsz){ bbsz= vec[2]; }
+ if(vec[0] > bbex){ bbex= vec[0]; }
+ if(vec[1] > bbey){ bbey= vec[1]; }
+ if(vec[2] > bbez){ bbez= vec[2]; }
+ }
+
+ // return values...
+ if(start) {
+ start[0] = bbsx;
+ start[1] = bbsy;
+ start[2] = bbsz;
+ }
+ if(size) {
+ size[0] = bbex-bbsx;
+ size[1] = bbey-bbsy;
+ size[2] = bbez-bbsz;
+ }
+}
+
+//-------------------------------------------------------------------------------
+// old interface
+//-------------------------------------------------------------------------------
+
+void fluid_estimate_memory(Object *ob, FluidsimSettings *fss, char *value)
+{
+ Mesh *mesh;
+
+ value[0]= '\0';
+
+ if(ob->type == OB_MESH) {
+ /* use mesh bounding box and object scaling */
+ mesh= ob->data;
+
+ fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
+ elbeemEstimateMemreq(fss->resolutionxyz, fss->bbSize[0],fss->bbSize[1],fss->bbSize[2], fss->maxRefine, value);
+ }
+}
+
+
+/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
+void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh *dm, char *filename)
+{
+ int wri, i, j;
+ float wrf;
+ gzFile gzf;
+ FluidsimSettings *fss = fluidmd->fss;
+ int len = strlen(filename);
+ int totvert = dm->getNumVerts(dm);
+ float *velarray = NULL;
+
+ // mesh and vverts have to be valid from loading...
+
+ if(fss->meshSurfNormals)
+ MEM_freeN(fss->meshSurfNormals);
+
+ if(len<7)
+ {
+ return;
+ }
+
+ if(fss->domainNovecgen>0) return;
+
+ // abusing pointer to hold an array of 3d-velocities
+ fss->meshSurfNormals = MEM_callocN(sizeof(float)*3*dm->getNumVerts(dm), "Fluidsim_velocities");
+ // abusing pointer to hold an INT
+ fss->meshSurface = SET_INT_IN_POINTER(totvert);
+
+ velarray = (float *)fss->meshSurfNormals;
+
+ // .bobj.gz , correct filename
+ // 87654321
+ filename[len-6] = 'v';
+ filename[len-5] = 'e';
+ filename[len-4] = 'l';
+
+ gzf = gzopen(filename, "rb");
+ if (!gzf)
+ {
+ MEM_freeN(fss->meshSurfNormals);
+ fss->meshSurfNormals = NULL;
+ return;
+ }
+
+ gzread(gzf, &wri, sizeof( wri ));
+ if(wri != totvert)
+ {
+ MEM_freeN(fss->meshSurfNormals);
+ fss->meshSurfNormals = NULL;
+ return;
+ }
+
+ for(i=0; i<totvert;i++)
+ {
+ for(j=0; j<3; j++)
+ {
+ gzread(gzf, &wrf, sizeof( wrf ));
+ velarray[3*i + j] = wrf;
+ }
+ }
+
+ gzclose(gzf);
+}
+
+DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
+{
+ int displaymode = 0;
+ int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */
+ char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
+ FluidsimSettings *fss = fluidmd->fss;
+ DerivedMesh *dm = NULL;
+ MFace *mface;
+ int numfaces;
+ int mat_nr, flag, i;
+
+ if(!useRenderParams) {
+ displaymode = fss->guiDisplayMode;
+ } else {
+ displaymode = fss->renderDisplayMode;
+ }
+
+ strncpy(targetDir, fss->surfdataPath, FILE_MAXDIR);
+
+ // use preview or final mesh?
+ if(displaymode==1)
+ {
+ // just display original object
+ return NULL;
+ }
+ else if(displaymode==2)
+ {
+ strcat(targetDir,"fluidsurface_preview_####");
+ }
+ else
+ { // 3
+ strcat(targetDir,"fluidsurface_final_####");
+ }
+
+ BLI_path_abs(targetDir, G.sce);
+ BLI_path_frame(targetDir, curFrame, 0); // fixed #frame-no
+
+ strcpy(targetFile,targetDir);
+ strcat(targetFile, ".bobj.gz");
+
+ dm = fluidsim_read_obj(targetFile);
+
+ if(!dm)
+ {
+ // switch, abort background rendering when fluidsim mesh is missing
+ const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
+
+ if(G.background==1) {
+ if(getenv(strEnvName2)) {
+ int elevel = atoi(getenv(strEnvName2));
+ if(elevel>0) {
+ printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
+ exit(1);
+ }
+ }
+ }
+
+ // display org. object upon failure which is in dm
+ return NULL;
+ }
+
+ // assign material + flags to new dm
+ mface = orgdm->getFaceArray(orgdm);
+ mat_nr = mface[0].mat_nr;
+ flag = mface[0].flag;
+
+ mface = dm->getFaceArray(dm);
+ numfaces = dm->getNumFaces(dm);
+ for(i=0; i<numfaces; i++)
+ {
+ mface[i].mat_nr = mat_nr;
+ mface[i].flag = flag;
+ }
+
+ // load vertex velocities, if they exist...
+ // TODO? use generate flag as loading flag as well?
+ // warning, needs original .bobj.gz mesh loading filename
+ if(displaymode==3)
+ {
+ fluidsim_read_vel_cache(fluidmd, dm, targetFile);
+ }
+ else
+ {
+ if(fss->meshSurfNormals)
+ MEM_freeN(fss->meshSurfNormals);
+
+ fss->meshSurfNormals = NULL;
+ }
+
+ return dm;
+}
+
+#endif // DISABLE_ELBEEM
+
+DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
+{
+#ifndef DISABLE_ELBEEM
+ DerivedMesh *result = NULL;
+ int framenr;
+ FluidsimSettings *fss = NULL;
+
+ framenr= (int)scene->r.cfra;
+
+ // only handle fluidsim domains
+ if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN))
+ return dm;
+
+ // sanity check
+ if(!fluidmd || (fluidmd && !fluidmd->fss))
+ return dm;
+
+ fss = fluidmd->fss;
+
+ // timescale not supported yet
+ // clmd->sim_parms->timescale= timescale;
+
+ // support reversing of baked fluid frames here
+ if((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0))
+ {
+ framenr = fss->lastgoodframe - framenr + 1;
+ CLAMP(framenr, 1, fss->lastgoodframe);
+ }
+
+ /* try to read from cache */
+ if(((fss->lastgoodframe >= framenr) || (fss->lastgoodframe < 0)) && (result = fluidsim_read_cache(ob, dm, fluidmd, framenr, useRenderParams)))
+ {
+ // fss->lastgoodframe = framenr; // set also in src/fluidsim.c
+ return result;
+ }
+ else
+ {
+ // display last known good frame
+ if(fss->lastgoodframe >= 0)
+ {
+ if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams)))
+ {
+ return result;
+ }
+
+ // it was supposed to be a valid frame but it isn't!
+ fss->lastgoodframe = framenr - 1;
+
+
+ // this could be likely the case when you load an old fluidsim
+ if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams)))
+ {
+ return result;
+ }
+ }
+
+ result = CDDM_copy(dm);
+
+ if(result)
+ {
+ return result;
+ }
+ }
+
+ return dm;
+#else
+ return NULL;
+#endif
+}
diff --git a/source/blender/blenkernel/BKE_simple_deform.h b/source/blender/modifiers/intern/MOD_fluidsim_util.h
index b5f4a2514dd..8dfb40292d6 100644
--- a/source/blender/blenkernel/BKE_simple_deform.h
+++ b/source/blender/modifiers/intern/MOD_fluidsim_util.h
@@ -1,5 +1,5 @@
/**
- * BKE_shrinkwrap.h
+ * $Id: BKE_fluidsim.h 26841 2010-02-12 13:34:04Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) Blender Foundation.
+ * The Original Code is Copyright (C) Blender Foundation
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -26,14 +26,22 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef BKE_SIMPLE_DEFORM_H
-#define BKE_SIMPLE_DEFORM_H
+
+#ifndef MOD_FLUIDSIM_UTIL_H
+#define MOD_FLUIDSIM_UTIL_H
struct Object;
+struct Scene;
+struct FluidsimModifierData;
struct DerivedMesh;
-struct SimpleDeformModifierData;
-void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts);
+/* new fluid-modifier interface */
+void fluidsim_init(struct FluidsimModifierData *fluidmd);
+void fluidsim_free(struct FluidsimModifierData *fluidmd);
+struct DerivedMesh *fluidsimModifier_do(struct FluidsimModifierData *fluidmd,
+ struct Scene *scene, struct Object *ob, struct DerivedMesh *dm,
+ int useRenderParams, int isFinalCalc);
+
#endif
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
new file mode 100644
index 00000000000..8ea596f8f61
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -0,0 +1,320 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ HookModifierData *hmd = (HookModifierData*) md;
+
+ hmd->force= 1.0;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ HookModifierData *hmd = (HookModifierData*) md;
+ HookModifierData *thmd = (HookModifierData*) target;
+
+ VECCOPY(thmd->cent, hmd->cent);
+ thmd->falloff = hmd->falloff;
+ thmd->force = hmd->force;
+ thmd->object = hmd->object;
+ thmd->totindex = hmd->totindex;
+ thmd->indexar = MEM_dupallocN(hmd->indexar);
+ memcpy(thmd->parentinv, hmd->parentinv, sizeof(hmd->parentinv));
+ strncpy(thmd->name, hmd->name, 32);
+ strncpy(thmd->subtarget, hmd->subtarget, 32);
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ HookModifierData *hmd = (HookModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(!hmd->indexar && hmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void freeData(ModifierData *md)
+{
+ HookModifierData *hmd = (HookModifierData*) md;
+
+ if (hmd->indexar) MEM_freeN(hmd->indexar);
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ HookModifierData *hmd = (HookModifierData*) md;
+
+ return !hmd->object;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ HookModifierData *hmd = (HookModifierData*) md;
+
+ walk(userData, ob, &hmd->object);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ HookModifierData *hmd = (HookModifierData*) md;
+
+ if (hmd->object) {
+ DagNode *curNode = dag_get_node(forest, hmd->object);
+
+ if (hmd->subtarget[0])
+ dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA|DAG_RL_DATA_DATA, "Hook Modifier");
+ else
+ dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "Hook Modifier");
+ }
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ HookModifierData *hmd = (HookModifierData*) md;
+ bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget);
+ float vec[3], mat[4][4], dmat[4][4];
+ int i;
+ DerivedMesh *dm = derivedData;
+
+ /* get world-space matrix of target, corrected for the space the verts are in */
+ if (hmd->subtarget[0] && pchan) {
+ /* bone target if there's a matching pose-channel */
+ mul_m4_m4m4(dmat, pchan->pose_mat, hmd->object->obmat);
+ }
+ else {
+ /* just object target */
+ copy_m4_m4(dmat, hmd->object->obmat);
+ }
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv,
+ NULL, NULL, NULL, NULL, NULL);
+
+ /* vertex indices? */
+ if(hmd->indexar) {
+ for(i = 0; i < hmd->totindex; i++) {
+ int index = hmd->indexar[i];
+
+ /* This should always be true and I don't generally like
+ * "paranoid" style code like this, but old files can have
+ * indices that are out of range because old blender did
+ * not correct them on exit editmode. - zr
+ */
+ if(index < numVerts) {
+ float *co = vertexCos[index];
+ float fac = hmd->force;
+
+ /* if DerivedMesh is present and has original index data,
+ * use it
+ */
+ if(dm && dm->getVertDataArray(dm, CD_ORIGINDEX)) {
+ int j;
+ int orig_index;
+ for(j = 0; j < numVerts; ++j) {
+ fac = hmd->force;
+ orig_index = *(int *)dm->getVertData(dm, j,
+ CD_ORIGINDEX);
+ if(orig_index == index) {
+ co = vertexCos[j];
+ if(hmd->falloff != 0.0) {
+ float len = len_v3v3(co, hmd->cent);
+ if(len > hmd->falloff) fac = 0.0;
+ else if(len > 0.0)
+ fac *= sqrt(1.0 - len / hmd->falloff);
+ }
+
+ if(fac != 0.0) {
+ mul_v3_m4v3(vec, mat, co);
+ interp_v3_v3v3(co, co, vec, fac);
+ }
+ }
+ }
+ } else {
+ if(hmd->falloff != 0.0) {
+ float len = len_v3v3(co, hmd->cent);
+ if(len > hmd->falloff) fac = 0.0;
+ else if(len > 0.0)
+ fac *= sqrt(1.0 - len / hmd->falloff);
+ }
+
+ if(fac != 0.0) {
+ mul_v3_m4v3(vec, mat, co);
+ interp_v3_v3v3(co, co, vec, fac);
+ }
+ }
+ }
+ }
+ }
+ else if(hmd->name[0]) { /* vertex group hook */
+ Mesh *me = ob->data;
+ int use_dverts = 0;
+ int maxVerts = 0;
+ int defgrp_index = defgroup_name_index(ob, hmd->name);
+
+ if(dm) {
+ if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) {
+ maxVerts = dm->getNumVerts(dm);
+ use_dverts = 1;
+ }
+ }
+ else if(me->dvert) {
+ maxVerts = me->totvert;
+ use_dverts = 1;
+ }
+
+ if(defgrp_index >= 0 && use_dverts) {
+ MDeformVert *dvert = me->dvert;
+ int i, j;
+
+ for(i = 0; i < maxVerts; i++, dvert++) {
+ if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT);
+ for(j = 0; j < dvert->totweight; j++) {
+ if(dvert->dw[j].def_nr == defgrp_index) {
+ float fac = hmd->force*dvert->dw[j].weight;
+ float *co = vertexCos[i];
+
+ if(hmd->falloff != 0.0) {
+ float len = len_v3v3(co, hmd->cent);
+ if(len > hmd->falloff) fac = 0.0;
+ else if(len > 0.0)
+ fac *= sqrt(1.0 - len / hmd->falloff);
+ }
+
+ mul_v3_m4v3(vec, mat, co);
+ interp_v3_v3v3(co, co, vec, fac);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
+
+ if(!derivedData) dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Hook = {
+ /* name */ "Hook",
+ /* structName */ "HookModifierData",
+ /* structSize */ sizeof(HookModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode,
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
new file mode 100644
index 00000000000..2541c775af1
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -0,0 +1,189 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ LatticeModifierData *lmd = (LatticeModifierData*) md;
+ LatticeModifierData *tlmd = (LatticeModifierData*) target;
+
+ tlmd->object = lmd->object;
+ strncpy(tlmd->name, lmd->name, 32);
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ LatticeModifierData *lmd = (LatticeModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(lmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static int isDisabled(ModifierData *md, int userRenderParams)
+{
+ LatticeModifierData *lmd = (LatticeModifierData*) md;
+
+ return !lmd->object;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ LatticeModifierData *lmd = (LatticeModifierData*) md;
+
+ walk(userData, ob, &lmd->object);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ LatticeModifierData *lmd = (LatticeModifierData*) md;
+
+ if(lmd->object) {
+ DagNode *latNode = dag_get_node(forest, lmd->object);
+
+ dag_add_relation(forest, latNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Lattice Modifier");
+ }
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ LatticeModifierData *lmd = (LatticeModifierData*) md;
+
+
+ modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
+
+ lattice_deform_verts(lmd->object, ob, derivedData,
+ vertexCos, numVerts, lmd->name);
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
+
+ if(!derivedData) dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Lattice = {
+ /* name */ "Lattice",
+ /* structName */ "LatticeModifierData",
+ /* structSize */ sizeof(LatticeModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode,
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ 0,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
new file mode 100644
index 00000000000..f53feb72364
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -0,0 +1,449 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ MaskModifierData *mmd = (MaskModifierData*) md;
+ MaskModifierData *tmmd = (MaskModifierData*) target;
+
+ strcpy(tmmd->vgroup, mmd->vgroup);
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ return (1 << CD_MDEFORMVERT);
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ MaskModifierData *mmd = (MaskModifierData *)md;
+ walk(userData, ob, &mmd->ob_arm);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ MaskModifierData *mmd = (MaskModifierData *)md;
+
+ if (mmd->ob_arm)
+ {
+ DagNode *armNode = dag_get_node(forest, mmd->ob_arm);
+
+ dag_add_relation(forest, armNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier");
+ }
+}
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ MaskModifierData *mmd= (MaskModifierData *)md;
+ DerivedMesh *dm= derivedData, *result= NULL;
+ GHash *vertHash=NULL, *edgeHash, *faceHash;
+ GHashIterator *hashIter;
+ MDeformVert *dvert= NULL;
+ int numFaces=0, numEdges=0, numVerts=0;
+ int maxVerts, maxEdges, maxFaces;
+ int i;
+
+ /* Overview of Method:
+ * 1. Get the vertices that are in the vertexgroup of interest
+ * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices
+ * 3. Make a new mesh containing only the mapping data
+ */
+
+ /* get original number of verts, edges, and faces */
+ maxVerts= dm->getNumVerts(dm);
+ maxEdges= dm->getNumEdges(dm);
+ maxFaces= dm->getNumFaces(dm);
+
+ /* check if we can just return the original mesh
+ * - must have verts and therefore verts assigned to vgroups to do anything useful
+ */
+ if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) ||
+ (maxVerts == 0) || (ob->defbase.first == NULL) )
+ {
+ return derivedData;
+ }
+
+ /* if mode is to use selected armature bones, aggregate the bone groups */
+ if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */
+ {
+ GHash *vgroupHash, *boneHash;
+ Object *oba= mmd->ob_arm;
+ bPoseChannel *pchan;
+ bDeformGroup *def;
+
+ /* check that there is armature object with bones to use, otherwise return original mesh */
+ if (ELEM(NULL, mmd->ob_arm, mmd->ob_arm->pose))
+ return derivedData;
+
+ /* hashes for finding mapping of:
+ * - vgroups to indicies -> vgroupHash (string, int)
+ * - bones to vgroup indices -> boneHash (index of vgroup, dummy)
+ */
+ vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
+ boneHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+
+ /* build mapping of names of vertex groups to indices */
+ for (i = 0, def = ob->defbase.first; def; def = def->next, i++)
+ BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i));
+
+ /* get selected-posechannel <-> vertexgroup index mapping */
+ for (pchan= oba->pose->chanbase.first; pchan; pchan= pchan->next)
+ {
+ /* check if bone is selected */
+ // TODO: include checks for visibility too?
+ // FIXME: the depsgraph needs extensions to make this work in realtime...
+ if ( (pchan->bone) && (pchan->bone->flag & BONE_SELECTED) )
+ {
+ /* check if hash has group for this bone */
+ if (BLI_ghash_haskey(vgroupHash, pchan->name))
+ {
+ int defgrp_index= GET_INT_FROM_POINTER(BLI_ghash_lookup(vgroupHash, pchan->name));
+
+ /* add index to hash (store under key only) */
+ BLI_ghash_insert(boneHash, SET_INT_IN_POINTER(defgrp_index), pchan);
+ }
+ }
+ }
+
+ /* if no bones selected, free hashes and return original mesh */
+ if (BLI_ghash_size(boneHash) == 0)
+ {
+ BLI_ghash_free(vgroupHash, NULL, NULL);
+ BLI_ghash_free(boneHash, NULL, NULL);
+
+ return derivedData;
+ }
+
+ /* repeat the previous check, but for dverts */
+ dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT);
+ if (dvert == NULL)
+ {
+ BLI_ghash_free(vgroupHash, NULL, NULL);
+ BLI_ghash_free(boneHash, NULL, NULL);
+
+ return derivedData;
+ }
+
+ /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
+ vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+
+ /* add vertices which exist in vertexgroups into vertHash for filtering */
+ for (i = 0; i < maxVerts; i++)
+ {
+ MDeformWeight *def_weight = NULL;
+ int j;
+
+ for (j= 0; j < dvert[i].totweight; j++)
+ {
+ if (BLI_ghash_haskey(boneHash, SET_INT_IN_POINTER(dvert[i].dw[j].def_nr)))
+ {
+ def_weight = &dvert[i].dw[j];
+ break;
+ }
+ }
+
+ /* check if include vert in vertHash */
+ if (mmd->flag & MOD_MASK_INV) {
+ /* if this vert is in the vgroup, don't include it in vertHash */
+ if (def_weight) continue;
+ }
+ else {
+ /* if this vert isn't in the vgroup, don't include it in vertHash */
+ if (!def_weight) continue;
+ }
+
+ /* add to ghash for verts (numVerts acts as counter for mapping) */
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
+ numVerts++;
+ }
+
+ /* free temp hashes */
+ BLI_ghash_free(vgroupHash, NULL, NULL);
+ BLI_ghash_free(boneHash, NULL, NULL);
+ }
+ else /* --- Using Nominated VertexGroup only --- */
+ {
+ int defgrp_index = defgroup_name_index(ob, mmd->vgroup);
+
+ /* get dverts */
+ if (defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ /* if no vgroup (i.e. dverts) found, return the initial mesh */
+ if ((defgrp_index < 0) || (dvert == NULL))
+ return dm;
+
+ /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
+ vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+
+ /* add vertices which exist in vertexgroup into ghash for filtering */
+ for (i = 0; i < maxVerts; i++)
+ {
+ MDeformWeight *def_weight = NULL;
+ int j;
+
+ for (j= 0; j < dvert[i].totweight; j++)
+ {
+ if (dvert[i].dw[j].def_nr == defgrp_index)
+ {
+ def_weight = &dvert[i].dw[j];
+ break;
+ }
+ }
+
+ /* check if include vert in vertHash */
+ if (mmd->flag & MOD_MASK_INV) {
+ /* if this vert is in the vgroup, don't include it in vertHash */
+ if (def_weight) continue;
+ }
+ else {
+ /* if this vert isn't in the vgroup, don't include it in vertHash */
+ if (!def_weight) continue;
+ }
+
+ /* add to ghash for verts (numVerts acts as counter for mapping) */
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
+ numVerts++;
+ }
+ }
+
+ /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
+ edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+ faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+
+ /* loop over edges and faces, and do the same thing to
+ * ensure that they only reference existing verts
+ */
+ for (i = 0; i < maxEdges; i++)
+ {
+ MEdge me;
+ dm->getEdge(dm, i, &me);
+
+ /* only add if both verts will be in new mesh */
+ if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) &&
+ BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) )
+ {
+ BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
+ numEdges++;
+ }
+ }
+ for (i = 0; i < maxFaces; i++)
+ {
+ MFace mf;
+ dm->getFace(dm, i, &mf);
+
+ /* all verts must be available */
+ if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) &&
+ BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) &&
+ BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) &&
+ (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) )
+ {
+ BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces));
+ numFaces++;
+ }
+ }
+
+
+ /* now we know the number of verts, edges and faces,
+ * we can create the new (reduced) mesh
+ */
+ result = CDDM_from_template(dm, numVerts, numEdges, numFaces);
+
+
+ /* using ghash-iterators, map data into new mesh */
+ /* vertices */
+ for ( hashIter = BLI_ghashIterator_new(vertHash);
+ !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_step(hashIter) )
+ {
+ MVert source;
+ MVert *dest;
+ int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
+ int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
+
+ dm->getVert(dm, oldIndex, &source);
+ dest = CDDM_get_vert(result, newIndex);
+
+ DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
+ *dest = source;
+ }
+ BLI_ghashIterator_free(hashIter);
+
+ /* edges */
+ for ( hashIter = BLI_ghashIterator_new(edgeHash);
+ !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_step(hashIter) )
+ {
+ MEdge source;
+ MEdge *dest;
+ int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
+ int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
+
+ dm->getEdge(dm, oldIndex, &source);
+ dest = CDDM_get_edge(result, newIndex);
+
+ source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
+ source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
+
+ DM_copy_edge_data(dm, result, oldIndex, newIndex, 1);
+ *dest = source;
+ }
+ BLI_ghashIterator_free(hashIter);
+
+ /* faces */
+ for ( hashIter = BLI_ghashIterator_new(faceHash);
+ !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_step(hashIter) )
+ {
+ MFace source;
+ MFace *dest;
+ int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
+ int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
+ int orig_v4;
+
+ dm->getFace(dm, oldIndex, &source);
+ dest = CDDM_get_face(result, newIndex);
+
+ orig_v4 = source.v4;
+
+ source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
+ source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
+ source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
+ if (source.v4)
+ source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
+
+ DM_copy_face_data(dm, result, oldIndex, newIndex, 1);
+ *dest = source;
+
+ test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3));
+ }
+ BLI_ghashIterator_free(hashIter);
+
+ /* recalculate normals */
+ CDDM_calc_normals(result);
+
+ /* free hashes */
+ BLI_ghash_free(vertHash, NULL, NULL);
+ BLI_ghash_free(edgeHash, NULL, NULL);
+ BLI_ghash_free(faceHash, NULL, NULL);
+
+ /* return the new mesh */
+ return result;
+}
+
+
+ModifierTypeInfo modifierType_Mask = {
+ /* name */ "Mask",
+ /* structName */ "MaskModifierData",
+ /* structSize */ sizeof(MaskModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ 0,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
new file mode 100644
index 00000000000..80061ae7bc9
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -0,0 +1,422 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+static void initData(ModifierData *md)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
+
+ mmd->gridsize= 5;
+}
+
+static void freeData(ModifierData *md)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
+
+ if(mmd->bindweights) MEM_freeN(mmd->bindweights);
+ if(mmd->bindcos) MEM_freeN(mmd->bindcos);
+ if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
+ if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
+ if(mmd->dynverts) MEM_freeN(mmd->dynverts);
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
+ MeshDeformModifierData *tmmd = (MeshDeformModifierData*) target;
+
+ tmmd->gridsize = mmd->gridsize;
+ tmmd->object = mmd->object;
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(mmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
+
+ return !mmd->object;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
+
+ walk(userData, ob, &mmd->object);
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
+ DagNode *obNode)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
+
+ if (mmd->object) {
+ DagNode *curNode = dag_get_node(forest, mmd->object);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA|DAG_RL_OB_DATA|DAG_RL_DATA_OB|DAG_RL_OB_OB,
+ "Mesh Deform Modifier");
+ }
+}
+
+static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3], float *vec)
+{
+ MDefCell *cell;
+ MDefInfluence *inf;
+ float gridvec[3], dvec[3], ivec[3], co[3], wx, wy, wz;
+ float weight, cageweight, totweight, *cageco;
+ int i, j, a, x, y, z, size;
+
+ co[0]= co[1]= co[2]= 0.0f;
+ totweight= 0.0f;
+ size= mmd->dyngridsize;
+
+ for(i=0; i<3; i++) {
+ gridvec[i]= (vec[i] - mmd->dyncellmin[i] - mmd->dyncellwidth*0.5f)/mmd->dyncellwidth;
+ ivec[i]= (int)gridvec[i];
+ dvec[i]= gridvec[i] - ivec[i];
+ }
+
+ for(i=0; i<8; i++) {
+ if(i & 1) { x= ivec[0]+1; wx= dvec[0]; }
+ else { x= ivec[0]; wx= 1.0f-dvec[0]; }
+
+ if(i & 2) { y= ivec[1]+1; wy= dvec[1]; }
+ else { y= ivec[1]; wy= 1.0f-dvec[1]; }
+
+ if(i & 4) { z= ivec[2]+1; wz= dvec[2]; }
+ else { z= ivec[2]; wz= 1.0f-dvec[2]; }
+
+ CLAMP(x, 0, size-1);
+ CLAMP(y, 0, size-1);
+ CLAMP(z, 0, size-1);
+
+ a= x + y*size + z*size*size;
+ weight= wx*wy*wz;
+
+ cell= &mmd->dyngrid[a];
+ inf= mmd->dyninfluences + cell->offset;
+ for(j=0; j<cell->totinfluence; j++, inf++) {
+ cageco= dco[inf->vertex];
+ cageweight= weight*inf->weight;
+ co[0] += cageweight*cageco[0];
+ co[1] += cageweight*cageco[1];
+ co[2] += cageweight*cageco[2];
+ totweight += cageweight;
+ }
+ }
+
+ VECCOPY(vec, co);
+
+ return totweight;
+}
+
+static void meshdeformModifier_do(
+ ModifierData *md, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
+ Mesh *me= (mmd->object)? mmd->object->data: NULL;
+ EditMesh *em = (me)? BKE_mesh_get_editmesh(me): NULL;
+ DerivedMesh *tmpdm, *cagedm;
+ MDeformVert *dvert = NULL;
+ MDeformWeight *dw;
+ MVert *cagemvert;
+ float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
+ float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3];
+ int a, b, totvert, totcagevert, defgrp_index;
+
+ if(!mmd->object || (!mmd->bindcos && !mmd->bindfunc))
+ return;
+
+ /* get cage derivedmesh */
+ if(em) {
+ tmpdm= editmesh_get_derived_cage_and_final(md->scene, ob, em, &cagedm, 0);
+ if(tmpdm)
+ tmpdm->release(tmpdm);
+ BKE_mesh_end_editmesh(me, em);
+ }
+ else
+ cagedm= mmd->object->derivedFinal;
+
+ /* if we don't have one computed, use derivedmesh from data
+ * without any modifiers */
+ if(!cagedm) {
+ cagedm= get_dm(md->scene, mmd->object, NULL, NULL, NULL, 0);
+ if(cagedm)
+ cagedm->needsFree= 1;
+ }
+
+ if(!cagedm)
+ return;
+
+ /* compute matrices to go in and out of cage object space */
+ invert_m4_m4(imat, mmd->object->obmat);
+ mul_m4_m4m4(cagemat, ob->obmat, imat);
+ mul_m4_m4m4(cmat, cagemat, mmd->bindmat);
+ invert_m4_m4(iobmat, cmat);
+ copy_m3_m4(icagemat, iobmat);
+
+ /* bind weights if needed */
+ if(!mmd->bindcos) {
+ static int recursive = 0;
+
+ /* progress bar redraw can make this recursive .. */
+ if(!recursive) {
+ recursive = 1;
+ mmd->bindfunc(md->scene, dm, mmd, (float*)vertexCos, numVerts, cagemat);
+ recursive = 0;
+ }
+ }
+
+ /* verify we have compatible weights */
+ totvert= numVerts;
+ totcagevert= cagedm->getNumVerts(cagedm);
+
+ if(mmd->totvert!=totvert || mmd->totcagevert!=totcagevert || !mmd->bindcos) {
+ cagedm->release(cagedm);
+ return;
+ }
+
+ /* setup deformation data */
+ cagemvert= cagedm->getVertArray(cagedm);
+ weights= mmd->bindweights;
+ bindcos= (float(*)[3])mmd->bindcos;
+
+ dco= MEM_callocN(sizeof(*dco)*totcagevert, "MDefDco");
+ for(a=0; a<totcagevert; a++) {
+ /* get cage vertex in world space with binding transform */
+ VECCOPY(co, cagemvert[a].co);
+
+ if(G.rt != 527) {
+ mul_m4_v3(mmd->bindmat, co);
+ /* compute difference with world space bind coord */
+ VECSUB(dco[a], co, bindcos[a]);
+ }
+ else
+ VECCOPY(dco[a], co)
+ }
+
+ defgrp_index = defgroup_name_index(ob, mmd->defgrp_name);
+
+ if (defgrp_index >= 0)
+ dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ /* do deformation */
+ fac= 1.0f;
+
+ for(b=0; b<totvert; b++) {
+ if(mmd->flag & MOD_MDEF_DYNAMIC_BIND)
+ if(!mmd->dynverts[b])
+ continue;
+
+ if(dvert) {
+ for(dw=NULL, a=0; a<dvert[b].totweight; a++) {
+ if(dvert[b].dw[a].def_nr == defgrp_index) {
+ dw = &dvert[b].dw[a];
+ break;
+ }
+ }
+
+ if(mmd->flag & MOD_MDEF_INVERT_VGROUP) {
+ if(!dw) fac= 1.0f;
+ else if(dw->weight == 1.0f) continue;
+ else fac=1.0f-dw->weight;
+ }
+ else {
+ if(!dw) continue;
+ else fac= dw->weight;
+ }
+ }
+
+ if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
+ /* transform coordinate into cage's local space */
+ VECCOPY(co, vertexCos[b]);
+ mul_m4_v3(cagemat, co);
+ totweight= meshdeform_dynamic_bind(mmd, dco, co);
+ }
+ else {
+ totweight= 0.0f;
+ co[0]= co[1]= co[2]= 0.0f;
+
+ for(a=0; a<totcagevert; a++) {
+ weight= weights[a + b*totcagevert];
+ co[0]+= weight*dco[a][0];
+ co[1]+= weight*dco[a][1];
+ co[2]+= weight*dco[a][2];
+ totweight += weight;
+ }
+ }
+
+ if(totweight > 0.0f) {
+ mul_v3_fl(co, fac/totweight);
+ mul_m3_v3(icagemat, co);
+ if(G.rt != 527)
+ VECADD(vertexCos[b], vertexCos[b], co)
+ else
+ VECCOPY(vertexCos[b], co)
+ }
+ }
+
+ /* release cage derivedmesh */
+ MEM_freeN(dco);
+ cagedm->release(cagedm);
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm= get_dm(md->scene, ob, NULL, derivedData, NULL, 0);;
+
+ if(!dm)
+ return;
+
+ modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
+
+ meshdeformModifier_do(md, ob, dm, vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm;
+
+ if(!derivedData && ob->type == OB_MESH)
+ dm = CDDM_from_editmesh(editData, ob->data);
+ else
+ dm = derivedData;
+
+ meshdeformModifier_do(md, ob, dm, vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_MeshDeform = {
+ /* name */ "MeshDeform",
+ /* structName */ "MeshDeformModifierData",
+ /* structSize */ sizeof(MeshDeformModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
new file mode 100644
index 00000000000..0c5bcb4238f
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -0,0 +1,392 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
+ mmd->tolerance = 0.001;
+ mmd->mirror_ob = NULL;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+ MirrorModifierData *tmmd = (MirrorModifierData*) target;
+
+ tmmd->axis = mmd->axis;
+ tmmd->flag = mmd->flag;
+ tmmd->tolerance = mmd->tolerance;
+ tmmd->mirror_ob = mmd->mirror_ob;;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ walk(userData, ob, &mmd->mirror_ob);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->mirror_ob) {
+ DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
+
+ dag_add_relation(forest, latNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
+ }
+}
+
+static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
+ Object *ob,
+ DerivedMesh *dm,
+ int initFlags,
+ int axis)
+{
+ int i;
+ float tolerance = mmd->tolerance;
+ DerivedMesh *result;
+ int numVerts, numEdges, numFaces;
+ int maxVerts = dm->getNumVerts(dm);
+ int maxEdges = dm->getNumEdges(dm);
+ int maxFaces = dm->getNumFaces(dm);
+ int *flip_map= NULL;
+ int do_vgroup_mirr= (mmd->flag & MOD_MIR_VGROUP);
+ int (*indexMap)[2];
+ float mtx[4][4], imtx[4][4];
+
+ numVerts = numEdges = numFaces = 0;
+
+ indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
+
+ result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
+
+
+ if (do_vgroup_mirr) {
+ flip_map= defgroup_flip_map(ob, 0);
+ if(flip_map == NULL)
+ do_vgroup_mirr= 0;
+ }
+
+ if (mmd->mirror_ob) {
+ float obinv[4][4];
+
+ invert_m4_m4(obinv, mmd->mirror_ob->obmat);
+ mul_m4_m4m4(mtx, ob->obmat, obinv);
+ invert_m4_m4(imtx, mtx);
+ }
+
+ for(i = 0; i < maxVerts; i++) {
+ MVert inMV;
+ MVert *mv = CDDM_get_vert(result, numVerts);
+ int isShared;
+ float co[3];
+
+ dm->getVert(dm, i, &inMV);
+
+ copy_v3_v3(co, inMV.co);
+
+ if (mmd->mirror_ob) {
+ mul_v3_m4v3(co, mtx, co);
+ }
+ isShared = ABS(co[axis])<=tolerance;
+
+ /* Because the topology result (# of vertices) must be the same if
+ * the mesh data is overridden by vertex cos, have to calc sharedness
+ * based on original coordinates. This is why we test before copy.
+ */
+ DM_copy_vert_data(dm, result, i, numVerts, 1);
+ *mv = inMV;
+ numVerts++;
+
+ indexMap[i][0] = numVerts - 1;
+ indexMap[i][1] = !isShared;
+
+ if(isShared) {
+ co[axis] = 0;
+ if (mmd->mirror_ob) {
+ mul_v3_m4v3(co, imtx, co);
+ }
+ copy_v3_v3(mv->co, co);
+
+ mv->flag |= ME_VERT_MERGED;
+ } else {
+ MVert *mv2 = CDDM_get_vert(result, numVerts);
+
+ DM_copy_vert_data(dm, result, i, numVerts, 1);
+ *mv2 = *mv;
+
+ co[axis] = -co[axis];
+ if (mmd->mirror_ob) {
+ mul_v3_m4v3(co, imtx, co);
+ }
+ copy_v3_v3(mv2->co, co);
+
+ if (do_vgroup_mirr) {
+ MDeformVert *dvert= DM_get_vert_data(result, numVerts, CD_MDEFORMVERT);
+ if(dvert) {
+ defvert_flip(dvert, flip_map);
+ }
+ }
+
+ numVerts++;
+ }
+ }
+
+ for(i = 0; i < maxEdges; i++) {
+ MEdge inMED;
+ MEdge *med = CDDM_get_edge(result, numEdges);
+
+ dm->getEdge(dm, i, &inMED);
+
+ DM_copy_edge_data(dm, result, i, numEdges, 1);
+ *med = inMED;
+ numEdges++;
+
+ med->v1 = indexMap[inMED.v1][0];
+ med->v2 = indexMap[inMED.v2][0];
+ if(initFlags)
+ med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
+
+ if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
+ MEdge *med2 = CDDM_get_edge(result, numEdges);
+
+ DM_copy_edge_data(dm, result, i, numEdges, 1);
+ *med2 = *med;
+ numEdges++;
+
+ med2->v1 += indexMap[inMED.v1][1];
+ med2->v2 += indexMap[inMED.v2][1];
+ }
+ }
+
+ for(i = 0; i < maxFaces; i++) {
+ MFace inMF;
+ MFace *mf = CDDM_get_face(result, numFaces);
+
+ dm->getFace(dm, i, &inMF);
+
+ DM_copy_face_data(dm, result, i, numFaces, 1);
+ *mf = inMF;
+ numFaces++;
+
+ mf->v1 = indexMap[inMF.v1][0];
+ mf->v2 = indexMap[inMF.v2][0];
+ mf->v3 = indexMap[inMF.v3][0];
+ mf->v4 = indexMap[inMF.v4][0];
+
+ if(indexMap[inMF.v1][1]
+ || indexMap[inMF.v2][1]
+ || indexMap[inMF.v3][1]
+ || (mf->v4 && indexMap[inMF.v4][1])) {
+ MFace *mf2 = CDDM_get_face(result, numFaces);
+ static int corner_indices[4] = {2, 1, 0, 3};
+
+ DM_copy_face_data(dm, result, i, numFaces, 1);
+ *mf2 = *mf;
+
+ mf2->v1 += indexMap[inMF.v1][1];
+ mf2->v2 += indexMap[inMF.v2][1];
+ mf2->v3 += indexMap[inMF.v3][1];
+ if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
+
+ /* mirror UVs if enabled */
+ if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
+ MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
+ if(tf) {
+ int j;
+ for(j = 0; j < 4; ++j) {
+ if(mmd->flag & MOD_MIR_MIRROR_U)
+ tf->uv[j][0] = 1.0f - tf->uv[j][0];
+ if(mmd->flag & MOD_MIR_MIRROR_V)
+ tf->uv[j][1] = 1.0f - tf->uv[j][1];
+ }
+ }
+ }
+
+ /* Flip face normal */
+ SWAP(int, mf2->v1, mf2->v3);
+ DM_swap_face_data(result, numFaces, corner_indices);
+
+ test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
+ numFaces++;
+ }
+ }
+
+ if (flip_map) MEM_freeN(flip_map);
+
+ MEM_freeN(indexMap);
+
+ CDDM_lower_num_verts(result, numVerts);
+ CDDM_lower_num_edges(result, numEdges);
+ CDDM_lower_num_faces(result, numFaces);
+
+ return result;
+}
+
+static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
+ Object *ob, DerivedMesh *dm,
+ int initFlags)
+{
+ DerivedMesh *result = dm;
+
+ /* check which axes have been toggled and mirror accordingly */
+ if(mmd->flag & MOD_MIR_AXIS_X) {
+ result = doMirrorOnAxis(mmd, ob, result, initFlags, 0);
+ }
+ if(mmd->flag & MOD_MIR_AXIS_Y) {
+ DerivedMesh *tmp = result;
+ result = doMirrorOnAxis(mmd, ob, result, initFlags, 1);
+ if(tmp != dm) tmp->release(tmp); /* free intermediate results */
+ }
+ if(mmd->flag & MOD_MIR_AXIS_Z) {
+ DerivedMesh *tmp = result;
+ result = doMirrorOnAxis(mmd, ob, result, initFlags, 2);
+ if(tmp != dm) tmp->release(tmp); /* free intermediate results */
+ }
+
+ return result;
+}
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ result = mirrorModifier__doMirror(mmd, ob, derivedData, 0);
+
+ if(result != derivedData)
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+
+ModifierTypeInfo modifierType_Mirror = {
+ /* name */ "Mirror",
+ /* structName */ "MirrorModifierData",
+ /* structSize */ sizeof(MirrorModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode
+ | eModifierTypeFlag_AcceptsCVs,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
new file mode 100644
index 00000000000..bd122e1c8f9
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -0,0 +1,157 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ MultiresModifierData *mmd = (MultiresModifierData*)md;
+
+ mmd->lvl = 0;
+ mmd->sculptlvl = 0;
+ mmd->renderlvl = 0;
+ mmd->totlvl = 0;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ MultiresModifierData *mmd = (MultiresModifierData*) md;
+ MultiresModifierData *tmmd = (MultiresModifierData*) target;
+
+ tmmd->lvl = mmd->lvl;
+ tmmd->sculptlvl = mmd->sculptlvl;
+ tmmd->renderlvl = mmd->renderlvl;
+ tmmd->totlvl = mmd->totlvl;
+}
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
+ int useRenderParams, int isFinalCalc)
+{
+ MultiresModifierData *mmd = (MultiresModifierData*)md;
+ DerivedMesh *result;
+
+ result = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams, isFinalCalc);
+
+ if(result == dm)
+ return dm;
+
+ if(useRenderParams || !isFinalCalc) {
+ DerivedMesh *cddm= CDDM_copy(result);
+ result->release(result);
+ result= cddm;
+ }
+ else if((ob->mode & OB_MODE_SCULPT) && ob->sculpt) {
+ /* would be created on the fly too, just nicer this
+ way on first stroke after e.g. switching levels */
+ ob->sculpt->pbvh= result->getPBVH(ob, result);
+ }
+
+ return result;
+}
+
+
+ModifierTypeInfo modifierType_Multires = {
+ /* name */ "Multires",
+ /* structName */ "MultiresModifierData",
+ /* structSize */ sizeof(MultiresModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_RequiresOriginalData,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c
new file mode 100644
index 00000000000..49eaba5b6a9
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_none.c
@@ -0,0 +1,70 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful;
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation;
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel Dunbar
+ * Ton Roosendaal,
+ * Ben Batt,
+ * Brecht Van Lommel,
+ * Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MOD_modifiertypes.h"
+
+/* We only need to define isDisabled; because it always returns 1,
+ * no other functions will be called
+ */
+
+static int isDisabled(ModifierData *md, int userRenderParams)
+{
+ return 1;
+}
+
+ModifierTypeInfo modifierType_None = {
+ /* name */ "None",
+ /* structName */ "ModifierData",
+ /* structSize */ sizeof(ModifierData),
+ /* type */ eModifierType_None,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_AcceptsCVs,
+
+ /* copyData */ 0,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ 0,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
new file mode 100644
index 00000000000..693ed4480ac
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -0,0 +1,374 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
+
+ pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn|
+ eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead;
+ pimd->psys = 1;
+ pimd->position = 1.0f;
+ pimd->axis = 2;
+
+}
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
+ ParticleInstanceModifierData *tpimd= (ParticleInstanceModifierData*) target;
+
+ tpimd->ob = pimd->ob;
+ tpimd->psys = pimd->psys;
+ tpimd->flag = pimd->flag;
+ tpimd->axis = pimd->axis;
+ tpimd->position = pimd->position;
+ tpimd->random_position = pimd->random_position;
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 0;
+}
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ Scene *scene,Object *ob, DagNode *obNode)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
+
+ if (pimd->ob) {
+ DagNode *curNode = dag_get_node(forest, pimd->ob);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
+ "Particle Instance Modifier");
+ }
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
+
+ walk(userData, ob, &pimd->ob);
+}
+
+static DerivedMesh * applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = derivedData, *result;
+ ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
+ ParticleSimulationData sim;
+ ParticleSystem * psys=0;
+ ParticleData *pa=0, *pars=0;
+ MFace *mface, *orig_mface;
+ MVert *mvert, *orig_mvert;
+ int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
+ short track=ob->trackflag%3, trackneg, axis = pimd->axis;
+ float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
+ float *size=NULL;
+
+ trackneg=((ob->trackflag>2)?1:0);
+
+ if(pimd->ob==ob){
+ pimd->ob=0;
+ return derivedData;
+ }
+
+ if(pimd->ob){
+ psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
+ if(psys==0 || psys->totpart==0)
+ return derivedData;
+ }
+ else return derivedData;
+
+ if(pimd->flag & eParticleInstanceFlag_Parents)
+ totpart+=psys->totpart;
+ if(pimd->flag & eParticleInstanceFlag_Children){
+ if(totpart==0)
+ first_particle=psys->totpart;
+ totpart+=psys->totchild;
+ }
+
+ if(totpart==0)
+ return derivedData;
+
+ sim.scene = md->scene;
+ sim.ob = pimd->ob;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(pimd->ob, psys);
+
+ if(pimd->flag & eParticleInstanceFlag_UseSize) {
+ int p;
+ float *si;
+ si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
+
+ if(pimd->flag & eParticleInstanceFlag_Parents) {
+ for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
+ *si = pa->size;
+ }
+
+ if(pimd->flag & eParticleInstanceFlag_Children) {
+ ChildParticle *cpa = psys->child;
+
+ for(p=0; p<psys->totchild; p++, cpa++, si++) {
+ *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
+ }
+ }
+ }
+
+ pars=psys->particles;
+
+ totvert=dm->getNumVerts(dm);
+ totface=dm->getNumFaces(dm);
+
+ maxvert=totvert*totpart;
+ maxface=totface*totpart;
+
+ psys->lattice=psys_get_lattice(&sim);
+
+ if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){
+
+ float min_r[3], max_r[3];
+ INIT_MINMAX(min_r, max_r);
+ dm->getMinMax(dm, min_r, max_r);
+ min_co=min_r[track];
+ max_co=max_r[track];
+ }
+
+ result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);
+
+ mvert=result->getVertArray(result);
+ orig_mvert=dm->getVertArray(dm);
+
+ for(i=0; i<maxvert; i++){
+ MVert *inMV;
+ MVert *mv = mvert + i;
+ ParticleKey state;
+
+ inMV = orig_mvert + i%totvert;
+ DM_copy_vert_data(dm, result, i%totvert, i, 1);
+ *mv = *inMV;
+
+ /*change orientation based on object trackflag*/
+ VECCOPY(temp_co,mv->co);
+ mv->co[axis]=temp_co[track];
+ mv->co[(axis+1)%3]=temp_co[(track+1)%3];
+ mv->co[(axis+2)%3]=temp_co[(track+2)%3];
+
+ if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
+ float ran = 0.0f;
+ if(pimd->random_position != 0.0f) {
+ BLI_srandom(psys->seed + (i/totvert)%totpart);
+ ran = pimd->random_position * BLI_frand();
+ }
+
+ if(pimd->flag & eParticleInstanceFlag_KeepShape) {
+ state.time = pimd->position * (1.0f - ran);
+ }
+ else {
+ state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);
+
+ if(trackneg)
+ state.time=1.0f-state.time;
+
+ mv->co[axis] = 0.0;
+ }
+
+ psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);
+
+ normalize_v3(state.vel);
+
+ /* TODO: incremental rotations somehow */
+ if(state.vel[axis] < -0.9999 || state.vel[axis] > 0.9999) {
+ state.rot[0] = 1;
+ state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
+ }
+ else {
+ float temp[3] = {0.0f,0.0f,0.0f};
+ temp[axis] = 1.0f;
+
+ cross_v3_v3v3(cross, temp, state.vel);
+
+ /* state.vel[axis] is the only component surviving from a dot product with the axis */
+ axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis]));
+ }
+
+ }
+ else{
+ state.time=-1.0;
+ psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
+ }
+
+ mul_qt_v3(state.rot,mv->co);
+ if(pimd->flag & eParticleInstanceFlag_UseSize)
+ mul_v3_fl(mv->co, size[i/totvert]);
+ VECADD(mv->co,mv->co,state.co);
+ }
+
+ mface=result->getFaceArray(result);
+ orig_mface=dm->getFaceArray(dm);
+
+ for(i=0; i<maxface; i++){
+ MFace *inMF;
+ MFace *mf = mface + i;
+
+ if(pimd->flag & eParticleInstanceFlag_Parents){
+ if(i/totface>=psys->totpart){
+ if(psys->part->childtype==PART_CHILD_PARTICLES)
+ pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
+ else
+ pa=0;
+ }
+ else
+ pa=pars+i/totface;
+ }
+ else{
+ if(psys->part->childtype==PART_CHILD_PARTICLES)
+ pa=psys->particles+(psys->child+i/totface)->parent;
+ else
+ pa=0;
+ }
+
+ if(pa){
+ if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
+ if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
+ if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
+ }
+
+ inMF = orig_mface + i%totface;
+ DM_copy_face_data(dm, result, i%totface, i, 1);
+ *mf = *inMF;
+
+ mf->v1+=(i/totface)*totvert;
+ mf->v2+=(i/totface)*totvert;
+ mf->v3+=(i/totface)*totvert;
+ if(mf->v4)
+ mf->v4+=(i/totface)*totvert;
+ }
+
+ CDDM_calc_edges(result);
+ CDDM_calc_normals(result);
+
+ if(psys->lattice){
+ end_latt_deform(psys->lattice);
+ psys->lattice= NULL;
+ }
+
+ if(size)
+ MEM_freeN(size);
+
+ return result;
+}
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+
+ModifierTypeInfo modifierType_ParticleInstance = {
+ /* name */ "ParticleInstance",
+ /* structName */ "ParticleInstanceModifierData",
+ /* structSize */ sizeof(ParticleInstanceModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsMapping |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
new file mode 100644
index 00000000000..5c5166ae44d
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -0,0 +1,273 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+static void initData(ModifierData *md)
+{
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+ psmd->psys= 0;
+ psmd->dm=0;
+ psmd->totdmvert= psmd->totdmedge= psmd->totdmface= 0;
+}
+static void freeData(ModifierData *md)
+{
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+
+ if(psmd->dm){
+ psmd->dm->needsFree = 1;
+ psmd->dm->release(psmd->dm);
+ psmd->dm=0;
+ }
+
+ /* ED_object_modifier_remove may have freed this first before calling
+ * modifier_free (which calls this function) */
+ if(psmd->psys)
+ psmd->psys->flag |= PSYS_DELETE;
+}
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+ ParticleSystemModifierData *tpsmd= (ParticleSystemModifierData*) target;
+
+ tpsmd->dm = 0;
+ tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
+ //tpsmd->facepa = 0;
+ tpsmd->flag = psmd->flag;
+ /* need to keep this to recognise a bit later in copy_object */
+ tpsmd->psys = psmd->psys;
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+ CustomDataMask dataMask = 0;
+ Material *ma;
+ MTex *mtex;
+ int i;
+
+ if(!psmd->psys->part)
+ return 0;
+
+ ma= give_current_material(ob, psmd->psys->part->omat);
+ if(ma) {
+ for(i=0; i<MAX_MTEX; i++) {
+ mtex=ma->mtex[i];
+ if(mtex && (ma->septex & (1<<i))==0)
+ if(mtex->pmapto && (mtex->texco & TEXCO_UV))
+ dataMask |= (1 << CD_MTFACE);
+ }
+ }
+
+ if(psmd->psys->part->tanfac!=0.0)
+ dataMask |= (1 << CD_MTFACE);
+
+ /* ask for vertexgroups if we need them */
+ for(i=0; i<PSYS_TOT_VG; i++){
+ if(psmd->psys->vgroup[i]){
+ dataMask |= (1 << CD_MDEFORMVERT);
+ break;
+ }
+ }
+
+ /* particles only need this if they are after a non deform modifier, and
+ * the modifier stack will only create them in that case. */
+ dataMask |= CD_MASK_ORIGSPACE;
+
+ dataMask |= CD_MASK_ORCO;
+
+ return dataMask;
+}
+
+/* saves the current emitter state for a particle system and calculates particles */
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = derivedData;
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+ ParticleSystem * psys=0;
+ int needsFree=0;
+
+ if(ob->particlesystem.first)
+ psys=psmd->psys;
+ else
+ return;
+
+ if(!psys_check_enabled(ob, psys))
+ return;
+
+ if(dm==0) {
+ dm= get_dm(md->scene, ob, NULL, NULL, vertexCos, 1);
+
+ if(!dm)
+ return;
+
+ needsFree= 1;
+ }
+
+ /* clear old dm */
+ if(psmd->dm){
+ psmd->dm->needsFree = 1;
+ psmd->dm->release(psmd->dm);
+ }
+
+ /* make new dm */
+ psmd->dm=CDDM_copy(dm);
+ CDDM_apply_vert_coords(psmd->dm, vertexCos);
+ CDDM_calc_normals(psmd->dm);
+
+ if(needsFree){
+ dm->needsFree = 1;
+ dm->release(dm);
+ }
+
+ /* protect dm */
+ psmd->dm->needsFree = 0;
+
+ /* report change in mesh structure */
+ if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert ||
+ psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge ||
+ psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){
+ /* in file read dm hasn't really changed but just wasn't saved in file */
+
+ psys->recalc |= PSYS_RECALC_RESET;
+ psmd->flag |= eParticleSystemFlag_DM_changed;
+
+ psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm);
+ psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm);
+ psmd->totdmface= psmd->dm->getNumFaces(psmd->dm);
+ }
+
+ if(psys) {
+ psmd->flag &= ~eParticleSystemFlag_psys_updated;
+ particle_system_update(md->scene, ob, psys);
+ psmd->flag |= eParticleSystemFlag_psys_updated;
+ psmd->flag &= ~eParticleSystemFlag_DM_changed;
+ }
+}
+
+/* disabled particles in editmode for now, until support for proper derivedmesh
+ * updates is coded */
+#if 0
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ deformVerts(md, ob, dm, vertexCos, numVerts);
+
+ if(!derivedData) dm->release(dm);
+}
+#endif
+
+
+ModifierTypeInfo modifierType_ParticleSystem = {
+ /* name */ "ParticleSystem",
+ /* structName */ "ParticleSystemModifierData",
+ /* structSize */ sizeof(ParticleSystemModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsMapping |
+ eModifierTypeFlag_UsesPointCache /* |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_EnableInEditmode */,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ 0 /* deformVertsEM */ ,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ freeData,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
new file mode 100644
index 00000000000..228719aecc1
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -0,0 +1,925 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+/* Screw modifier: revolves the edges about an axis
+*/
+
+/* used for gathering edge connectivity */
+typedef struct ScrewVertConnect {
+ float dist; /* distance from the center axis */
+ float co[3]; /* loaction relative to the transformed axis */
+ float no[3]; /* calc normal of the vertex */
+ int v[2]; /* 2 verts on either side of this one */
+ MEdge *e[2]; /* edges on either side, a bit of a waste since each edge ref's 2 edges */
+ char flag;
+} ScrewVertConnect;
+
+typedef struct ScrewVertIter {
+ ScrewVertConnect * v_array;
+ ScrewVertConnect * v_poin;
+ int v;
+ int v_other;
+ MEdge *e;
+} ScrewVertIter;
+
+#define ScrewVertIter_INIT(iter, array, v_init, dir)\
+ iter.v_array = array;\
+ iter.v = v_init;\
+ if (v_init>=0) {\
+ iter.v_poin = &array[v_init];\
+ iter.v_other = iter.v_poin->v[dir];\
+ if (dir)\
+ iter.e = iter.v_poin->e[0];\
+ else\
+ iter.e = iter.v_poin->e[1];\
+ } else {\
+ iter.v_poin= NULL;\
+ iter.e= NULL;\
+ }
+
+
+#define ScrewVertIter_NEXT(iter)\
+ if (iter.v_poin->v[0] == iter.v_other) {\
+ iter.v_other= iter.v;\
+ iter.v= iter.v_poin->v[1];\
+ } else if (iter.v_poin->v[1] == iter.v_other) {\
+ iter.v_other= iter.v;\
+ iter.v= iter.v_poin->v[0];\
+ }\
+ if (iter.v >=0) {\
+ iter.v_poin= &iter.v_array[iter.v];\
+ if ( iter.v_poin->e[0] != iter.e ) iter.e= iter.v_poin->e[0];\
+ else iter.e= iter.v_poin->e[1];\
+ } else {\
+ iter.e= NULL;\
+ iter.v_poin= NULL;\
+ }
+
+static void initData(ModifierData *md)
+{
+ ScrewModifierData *ltmd= (ScrewModifierData*) md;
+ ltmd->ob_axis= NULL;
+ ltmd->angle= M_PI * 2.0;
+ ltmd->axis= 2;
+ ltmd->flag= 0;
+ ltmd->steps= 16;
+ ltmd->render_steps= 16;
+ ltmd->iter= 1;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ ScrewModifierData *sltmd= (ScrewModifierData*) md;
+ ScrewModifierData *tltmd= (ScrewModifierData*) target;
+
+ tltmd->ob_axis= sltmd->ob_axis;
+ tltmd->angle= sltmd->angle;
+ tltmd->axis= sltmd->axis;
+ tltmd->flag= sltmd->flag;
+ tltmd->steps= sltmd->steps;
+ tltmd->render_steps= sltmd->render_steps;
+ tltmd->screw_ofs= sltmd->screw_ofs;
+ tltmd->iter= sltmd->iter;
+}
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm= derivedData;
+ DerivedMesh *result;
+ ScrewModifierData *ltmd= (ScrewModifierData*) md;
+
+ int *origindex;
+ int mface_index=0;
+ int i, j;
+ int i1,i2;
+ int steps= ltmd->steps;
+ int maxVerts=0, maxEdges=0, maxFaces=0;
+ int totvert= dm->getNumVerts(dm);
+ int totedge= dm->getNumEdges(dm);
+
+ char axis_char, close;
+ float angle= ltmd->angle;
+ float screw_ofs= ltmd->screw_ofs;
+ float axis_vec[3]= {0.0f, 0.0f, 0.0f};
+ float tmp_vec1[3], tmp_vec2[3];
+ float mat3[3][3];
+ float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */
+ float mtx_tx_inv[4][4]; /* inverted */
+ float mtx_tmp_a[4][4];
+
+ int vc_tot_linked= 0;
+ short other_axis_1, other_axis_2;
+ float *tmpf1, *tmpf2;
+
+ MFace *mface_new, *mf_new;
+ MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
+ MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;
+
+ ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL;
+
+ float mat[4][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}};
+
+ /* dont do anything? */
+ if (!totvert)
+ return CDDM_from_template(dm, 0, 0, 0);
+
+ steps= useRenderParams ? ltmd->render_steps : ltmd->steps;
+
+ switch(ltmd->axis) {
+ case 0:
+ other_axis_1=1;
+ other_axis_2=2;
+ break;
+ case 1:
+ other_axis_1=0;
+ other_axis_2=2;
+ break;
+ case 2:
+ other_axis_1=0;
+ other_axis_2=1;
+ break;
+ }
+
+ axis_vec[ltmd->axis]= 1.0f;
+
+ if (ltmd->ob_axis) {
+ float mtx3_tx[3][3];
+ /* calc the matrix relative to the axis object */
+ invert_m4_m4(mtx_tmp_a, ob->obmat);
+ copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat);
+ mul_m4_m4m4(mtx_tx, mtx_tx_inv, mtx_tmp_a);
+
+ copy_m3_m4(mtx3_tx, mtx_tx);
+
+ /* calc the axis vec */
+ mul_m3_v3(mtx3_tx, axis_vec);
+ normalize_v3(axis_vec);
+
+ /* screw */
+ if(ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
+ /* find the offset along this axis relative to this objects matrix */
+ float totlen = len_v3(mtx_tx[3]);
+
+ if(totlen != 0.0f) {
+ float zero[3]={0.0f, 0.0f, 0.0f};
+ float cp[3];
+ screw_ofs= closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
+ }
+ else {
+ screw_ofs= 0.0f;
+ }
+ }
+
+ /* angle */
+
+#if 0 // cant incluide this, not pradictable enough, though quite fun,.
+ if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
+
+
+ float vec[3] = {0,1,0};
+ float cross1[3];
+ float cross2[3];
+ cross_v3_v3v3(cross1, vec, axis_vec);
+
+ mul_v3_m3v3(cross2, mtx3_tx, cross1);
+ {
+ float c1[3];
+ float c2[3];
+ float axis_tmp[3];
+
+ cross_v3_v3v3(c1, cross2, axis_vec);
+ cross_v3_v3v3(c2, axis_vec, c1);
+
+
+ angle= angle_v3v3(cross1, c2);
+
+ cross_v3_v3v3(axis_tmp, cross1, c2);
+ normalize_v3(axis_tmp);
+
+ if(len_v3v3(axis_tmp, axis_vec) > 1.0f)
+ angle= -angle;
+
+ }
+ }
+#endif
+ }
+ else {
+ /* exis char is used by i_rotate*/
+ axis_char= 'X' + ltmd->axis;
+
+ /* useful to be able to use the axis vec in some cases still */
+ zero_v3(axis_vec);
+ axis_vec[ltmd->axis]= 1.0f;
+ }
+
+ /* apply the multiplier */
+ angle *= ltmd->iter;
+ screw_ofs *= ltmd->iter;
+
+ /* multiplying the steps is a bit tricky, this works best */
+ steps = ((steps + 1) * ltmd->iter) - (ltmd->iter - 1);
+
+ /* will the screw be closed?
+ * Note! smaller then FLT_EPSILON*100 gives problems with float precission so its never closed. */
+ if (fabs(screw_ofs) <= (FLT_EPSILON*100) && fabs(fabs(angle) - (M_PI * 2)) <= (FLT_EPSILON*100)) {
+ close= 1;
+ steps--;
+ if(steps < 2) steps= 2;
+
+ maxVerts = totvert * steps; /* -1 because we're joining back up */
+ maxEdges = (totvert * steps) + /* these are the edges between new verts */
+ (totedge * steps); /* -1 because vert edges join */
+ maxFaces = totedge * steps;
+
+ screw_ofs= 0.0f;
+ }
+ else {
+ close= 0;
+ if(steps < 2) steps= 2;
+
+ maxVerts = totvert * steps; /* -1 because we're joining back up */
+ maxEdges = (totvert * (steps-1)) + /* these are the edges between new verts */
+ (totedge * steps); /* -1 because vert edges join */
+ maxFaces = totedge * (steps-1);
+ }
+
+ result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces);
+
+ /* copy verts from mesh */
+ mvert_orig = dm->getVertArray(dm);
+ medge_orig = dm->getEdgeArray(dm);
+
+ mvert_new = result->getVertArray(result);
+ mface_new = result->getFaceArray(result);
+ medge_new = result->getEdgeArray(result);
+
+ origindex= result->getFaceDataArray(result, CD_ORIGINDEX);
+
+ /* Set the locations of the first set of verts */
+
+ mv_new= mvert_new;
+ mv_orig= mvert_orig;
+
+ /* Copy the first set of edges */
+ med_orig= medge_orig;
+ med_new= medge_new;
+ for (i=0; i < totedge; i++, med_orig++, med_new++) {
+ med_new->v1= med_orig->v1;
+ med_new->v2= med_orig->v2;
+ med_new->crease= med_orig->crease;
+ med_new->flag= med_orig->flag & ~ME_LOOSEEDGE;
+ }
+
+ if(ltmd->flag & MOD_SCREW_NORMAL_CALC) {
+ /*
+ * Normal Calculation (for face flipping)
+ * Sort edge verts for correct face flipping
+ * NOT REALLY NEEDED but face flipping is nice.
+ *
+ * */
+
+
+ /* Notice!
+ *
+ * Since we are only ordering the edges here it can avoid mallocing the
+ * extra space by abusing the vert array berfore its filled with new verts.
+ * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert
+ * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3
+ * so its safe to use the second 2 thrids of MVert the array for vert_connect,
+ * just make sure ScrewVertConnect struct is no more then twice as big as MVert,
+ * at the moment there is no chance of that being a problem,
+ * unless MVert becomes half its current size.
+ *
+ * once the edges are ordered, vert_connect is not needed and it can be used for verts
+ *
+ * This makes the modifier faster with one less alloc.
+ */
+
+ vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect");
+ //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */
+ vc= vert_connect;
+
+ /* Copy Vert Locations */
+ /* - We can do this in a later loop - only do here if no normal calc */
+ if (!totedge) {
+ for (i=0; i < totvert; i++, mv_orig++, mv_new++) {
+ copy_v3_v3(mv_new->co, mv_orig->co);
+ normalize_v3_v3(vc->no, mv_new->co); /* no edges- this is realy a dummy normal */
+ }
+ }
+ else {
+ /*printf("\n\n\n\n\nStarting Modifier\n");*/
+ /* set edge users */
+ med_new= medge_new;
+ mv_new= mvert_new;
+
+ if (ltmd->ob_axis) {
+ /*mtx_tx is initialized early on */
+ for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
+ vc->co[0]= mv_new->co[0]= mv_orig->co[0];
+ vc->co[1]= mv_new->co[1]= mv_orig->co[1];
+ vc->co[2]= mv_new->co[2]= mv_orig->co[2];
+
+ vc->flag= 0;
+ vc->e[0]= vc->e[1]= NULL;
+ vc->v[0]= vc->v[1]= -1;
+
+ mul_m4_v3(mtx_tx, vc->co);
+ /* length in 2d, dont sqrt because this is only for comparison */
+ vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] +
+ vc->co[other_axis_2]*vc->co[other_axis_2];
+
+ /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
+ }
+ }
+ else {
+ for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
+ vc->co[0]= mv_new->co[0]= mv_orig->co[0];
+ vc->co[1]= mv_new->co[1]= mv_orig->co[1];
+ vc->co[2]= mv_new->co[2]= mv_orig->co[2];
+
+ vc->flag= 0;
+ vc->e[0]= vc->e[1]= NULL;
+ vc->v[0]= vc->v[1]= -1;
+
+ /* length in 2d, dont sqrt because this is only for comparison */
+ vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] +
+ vc->co[other_axis_2]*vc->co[other_axis_2];
+
+ /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
+ }
+ }
+
+ /* this loop builds connectivity info for verts */
+ for (i=0; i<totedge; i++, med_new++) {
+ vc= &vert_connect[med_new->v1];
+
+ if (vc->v[0]==-1) { /* unused */
+ vc->v[0]= med_new->v2;
+ vc->e[0]= med_new;
+ }
+ else if (vc->v[1]==-1) {
+ vc->v[1]= med_new->v2;
+ vc->e[1]= med_new;
+ }
+ else {
+ vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */
+ }
+
+ vc= &vert_connect[med_new->v2];
+
+ /* same as above but swap v1/2 */
+ if (vc->v[0]==-1) { /* unused */
+ vc->v[0]= med_new->v1;
+ vc->e[0]= med_new;
+ }
+ else if (vc->v[1]==-1) {
+ vc->v[1]= med_new->v1;
+ vc->e[1]= med_new;
+ }
+ else {
+ vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */
+ }
+ }
+
+ /* find the first vert */
+ vc= vert_connect;
+ for (i=0; i < totvert; i++, vc++) {
+ int VBEST=-1, ed_loop_closed=0; /* vert and vert new */
+ int ed_loop_flip;
+ float fl= -1.0f;
+ ScrewVertIter lt_iter;
+
+ /* Now do search for connected verts, order all edges and flip them
+ * so resulting faces are flipped the right way */
+ vc_tot_linked= 0; /* count the number of linked verts for this loop */
+ if (vc->flag==0) {
+ /*printf("Loop on connected vert: %i\n", i);*/
+
+ for(j=0; j<2; j++) {
+ /*printf("\tSide: %i\n", j);*/
+ ScrewVertIter_INIT(lt_iter, vert_connect, i, j);
+ if (j==1) {
+ ScrewVertIter_NEXT(lt_iter);
+ }
+ while (lt_iter.v_poin) {
+ /*printf("\t\tVERT: %i\n", lt_iter.v);*/
+ if (lt_iter.v_poin->flag) {
+ /*printf("\t\t\tBreaking Found end\n");*/
+ //endpoints[0]= endpoints[1]= -1;
+ ed_loop_closed= 1; /* circle */
+ break;
+ }
+ lt_iter.v_poin->flag= 1;
+ vc_tot_linked++;
+ /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/
+ if (fl <= lt_iter.v_poin->dist) {
+ fl= lt_iter.v_poin->dist;
+ VBEST= lt_iter.v;
+ /*printf("\t\t\tVERT BEST: %i\n", VBEST);*/
+ }
+ ScrewVertIter_NEXT(lt_iter);
+ if (!lt_iter.v_poin) {
+ /*printf("\t\t\tFound End Also Num %i\n", j);*/
+ /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */
+ break;
+ }
+ }
+ }
+
+ /* now we have a collection of used edges. flip their edges the right way*/
+ /*if (VBEST !=-1) - */
+
+ /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/
+
+ if (vc_tot_linked>1) {
+ float vf_1, vf_2, vf_best;
+
+ vc_tmp= &vert_connect[VBEST];
+
+ tmpf1= vert_connect[vc_tmp->v[0]].co;
+ tmpf2= vert_connect[vc_tmp->v[1]].co;
+
+
+ /* edge connects on each side! */
+ if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) {
+ /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
+ /* find out which is higher */
+
+ vf_1= tmpf1[ltmd->axis];
+ vf_2= tmpf2[ltmd->axis];
+ vf_best= vc_tmp->co[ltmd->axis];
+
+ if (vf_1 < vf_best && vf_best < vf_2) {
+ ed_loop_flip= 0;
+ }
+ else if (vf_1 > vf_best && vf_best > vf_2) {
+ ed_loop_flip= 1;
+ }
+ else {
+ /* not so simple to work out which edge is higher */
+ sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co);
+ sub_v3_v3v3(tmp_vec1, tmpf2, vc_tmp->co);
+ normalize_v3(tmp_vec1);
+ normalize_v3(tmp_vec2);
+
+ if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) {
+ ed_loop_flip= 1;
+ }
+ else {
+ ed_loop_flip= 0;
+ }
+ }
+ }
+ else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */
+ /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
+ if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
+ ed_loop_flip= 1;
+ }
+ else { /* best is below or even... in even case we cant know whet to do. */
+ ed_loop_flip= 0;
+ }
+
+ }/* else {
+ printf("No Connected ___\n");
+ }*/
+
+ /*printf("flip direction %i\n", ed_loop_flip);*/
+
+
+ /* switch the flip option if set */
+ if (ltmd->flag & MOD_SCREW_NORMAL_FLIP)
+ ed_loop_flip= !ed_loop_flip;
+
+ if (angle < 0.0f)
+ ed_loop_flip= !ed_loop_flip;
+
+ /* if its closed, we only need 1 loop */
+ for(j=ed_loop_closed; j<2; j++) {
+ /*printf("Ordering Side J %i\n", j);*/
+
+ ScrewVertIter_INIT(lt_iter, vert_connect, VBEST, j);
+ /*printf("\n\nStarting - Loop\n");*/
+ lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */
+
+
+ /* If this is the vert off the best vert and
+ * the best vert has 2 edges connected too it
+ * then swap the flip direction */
+ if (j==1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1))
+ ed_loop_flip= !ed_loop_flip;
+
+ while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
+ /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/
+
+ lt_iter.v_poin->flag= 2;
+ if (lt_iter.e) {
+ if (lt_iter.v == lt_iter.e->v1) {
+ if (ed_loop_flip==0) {
+ /*printf("\t\t\tFlipping 0\n");*/
+ SWAP(int, lt_iter.e->v1, lt_iter.e->v2);
+ }/* else {
+ printf("\t\t\tFlipping Not 0\n");
+ }*/
+ }
+ else if (lt_iter.v == lt_iter.e->v2) {
+ if (ed_loop_flip==1) {
+ /*printf("\t\t\tFlipping 1\n");*/
+ SWAP(int, lt_iter.e->v1, lt_iter.e->v2);
+ }/* else {
+ printf("\t\t\tFlipping Not 1\n");
+ }*/
+ }/* else {
+ printf("\t\tIncorrect edge topology");
+ }*/
+ }/* else {
+ printf("\t\tNo Edge at this point\n");
+ }*/
+ ScrewVertIter_NEXT(lt_iter);
+ }
+ }
+ }
+ }
+
+ /* *VERTEX NORMALS*
+ * we know the surrounding edges are ordered correctly now
+ * so its safe to create vertex normals.
+ *
+ * calculate vertex normals that can be propodated on lathing
+ * use edge connectivity work this out */
+ if (vc->v[0]>=0) {
+ if (vc->v[1]>=0) {
+ /* 2 edges connedted */
+ /* make 2 connecting vert locations relative to the middle vert */
+ sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
+ sub_v3_v3v3(tmp_vec2, mvert_new[vc->v[1]].co, mvert_new[i].co);
+ /* normalize so both edges have the same influence, no matter their length */
+ normalize_v3(tmp_vec1);
+ normalize_v3(tmp_vec2);
+
+ /* vc_no_tmp1 - this line is the average direction of both connecting edges
+ *
+ * Use the edge order to make the subtraction, flip the normal the right way
+ * edge should be there but check just in case... */
+ if (vc->e && vc->e[0]->v1 == i) {
+ sub_v3_v3v3(tmp_vec1, tmp_vec1, tmp_vec2);
+ }
+ else {
+ sub_v3_v3v3(tmp_vec1, tmp_vec2, tmp_vec1);
+ }
+ }
+ else {
+ /* only 1 edge connected - same as above except
+ * dont need to average edge direction */
+ if (vc->e && vc->e[0]->v2 == i) {
+ sub_v3_v3v3(tmp_vec1, mvert_new[i].co, mvert_new[vc->v[0]].co);
+ }
+ else {
+ sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
+ }
+ }
+
+ /* vc_no_tmp2 - is a line 90d from the pivot to the vec
+ * This is used so the resulting normal points directly away from the middle */
+ cross_v3_v3v3(tmp_vec2, axis_vec, vc->co);
+
+ /* edge average vector and right angle to the pivot make the normal */
+ cross_v3_v3v3(vc->no, tmp_vec1, tmp_vec2);
+
+ }
+ else {
+ copy_v3_v3(vc->no, vc->co);
+ }
+
+ /* we wont be looping on this data again so copy normals here */
+ if (angle < 0.0f)
+ negate_v3(vc->no);
+
+ normalize_v3(vc->no);
+ normal_float_to_short_v3(mvert_new[i].no, vc->no);
+
+ /* Done with normals */
+ }
+ }
+ }
+ else {
+
+ if (ltmd->flag & MOD_SCREW_NORMAL_FLIP) {
+ mv_orig= mvert_orig;
+ mv_new= mvert_new + (totvert-1);
+
+ for (i=0; i < totvert; i++, mv_new--, mv_orig++) {
+ copy_v3_v3(mv_new->co, mv_orig->co);
+ }
+ }
+ else {
+ mv_orig= mvert_orig;
+ mv_new= mvert_new;
+
+ for (i=0; i < totvert; i++, mv_new++, mv_orig++) {
+ copy_v3_v3(mv_new->co, mv_orig->co);
+ }
+ }
+ }
+ /* done with edge connectivity based normal flipping */
+
+
+ /* Add Faces */
+ for (i=1; i < steps; i++) {
+ float step_angle;
+ float no_tx[3];
+ /* Rotation Matrix */
+ if (close) step_angle= (angle / steps) * i;
+ else step_angle= (angle / (steps-1)) * i;
+
+ if (ltmd->ob_axis) {
+ axis_angle_to_mat3(mat3, axis_vec, step_angle);
+ copy_m4_m3(mat, mat3);
+ }
+ else {
+ unit_m4(mat);
+ rotate_m4(mat, axis_char, step_angle);
+ copy_m3_m4(mat3, mat);
+ }
+
+ if(screw_ofs)
+ madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)i / (float)(steps-1)));
+
+ mv_new_base= mvert_new;
+ mv_new= &mvert_new[totvert*i]; /* advance to the next slice */
+
+ for (j=0; j<totvert; j++, mv_new_base++, mv_new++) {
+ /* set normal */
+ if(vert_connect) {
+ mul_v3_m3v3(no_tx, mat3, vert_connect[j].no);
+
+ /* set the normal now its transformed */
+ normal_float_to_short_v3(mv_new->no, no_tx);
+ }
+
+ /* set location */
+ copy_v3_v3(mv_new->co, mv_new_base->co);
+
+ /* only need to set these if using non cleared memory */
+ /*mv_new->mat_nr= mv_new->flag= 0;*/
+
+ if (ltmd->ob_axis) {
+ sub_v3_v3(mv_new->co, mtx_tx[3]);
+
+ mul_m4_v3(mat, mv_new->co);
+
+ add_v3_v3(mv_new->co, mtx_tx[3]);
+ }
+ else {
+ mul_m4_v3(mat, mv_new->co);
+ }
+
+ /* add the new edge */
+ med_new->v1= j+(i*totvert);
+ med_new->v2= med_new->v1 - totvert;
+ med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
+ med_new++;
+ }
+ }
+
+ /* we can avoid if using vert alloc trick */
+ if(vert_connect) {
+ MEM_freeN(vert_connect);
+ vert_connect= NULL;
+ }
+
+ if (close) {
+ /* last loop of edges, previous loop dosnt account for the last set of edges */
+ for (i=0; i<totvert; i++) {
+ med_new->v1= i;
+ med_new->v2= i+((steps-1)*totvert);
+ med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
+ med_new++;
+ }
+ }
+
+ mf_new= mface_new;
+ med_new_firstloop= medge_new;
+
+ for (i=0; i < totedge; i++, med_new_firstloop++) {
+ /* for each edge, make a cylinder of quads */
+ i1= med_new_firstloop->v1;
+ i2= med_new_firstloop->v2;
+
+ for (j=0; j < steps-1; j++) {
+
+ /* new face */
+ mf_new->v1= i1;
+ mf_new->v2= i2;
+ mf_new->v3= i2 + totvert;
+ mf_new->v4= i1 + totvert;
+
+ if( !mf_new->v3 || !mf_new->v4 ) {
+ SWAP(int, mf_new->v1, mf_new->v3);
+ SWAP(int, mf_new->v2, mf_new->v4);
+ }
+ mf_new->flag= ME_SMOOTH;
+ origindex[mface_index]= ORIGINDEX_NONE;
+ mf_new++;
+ mface_index++;
+
+ /* new vertical edge */
+ if (j) { /* The first set is alredy dome */
+ med_new->v1= i1;
+ med_new->v2= i2;
+ med_new->flag= med_new_firstloop->flag;
+ med_new->crease= med_new_firstloop->crease;
+ med_new++;
+ }
+ i1 += totvert;
+ i2 += totvert;
+ }
+
+ /* close the loop*/
+ if (close) {
+ mf_new->v1= i1;
+ mf_new->v2= i2;
+ mf_new->v3= med_new_firstloop->v2;
+ mf_new->v4= med_new_firstloop->v1;
+
+ if( !mf_new->v3 || !mf_new->v4 ) {
+ SWAP(int, mf_new->v1, mf_new->v3);
+ SWAP(int, mf_new->v2, mf_new->v4);
+ }
+ mf_new->flag= ME_SMOOTH;
+ origindex[mface_index]= ORIGINDEX_NONE;
+ mf_new++;
+ mface_index++;
+ }
+
+ /* new vertical edge */
+ med_new->v1= i1;
+ med_new->v2= i2;
+ med_new->flag= med_new_firstloop->flag & ~ME_LOOSEEDGE;
+ med_new->crease= med_new_firstloop->crease;
+ med_new++;
+ }
+
+ if((ltmd->flag & MOD_SCREW_NORMAL_CALC)==0) {
+ CDDM_calc_normals(result);
+ }
+
+ return result;
+}
+
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest,
+ Scene *scene, Object *ob, DagNode *obNode)
+{
+ ScrewModifierData *ltmd= (ScrewModifierData*) md;
+
+ if(ltmd->ob_axis) {
+ DagNode *curNode= dag_get_node(forest, ltmd->ob_axis);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
+ "Screw Modifier");
+ }
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ ScrewModifierData *ltmd= (ScrewModifierData*) md;
+
+ walk(userData, ob, &ltmd->ob_axis);
+}
+
+/* This dosnt work with material*/
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 0;
+}
+
+
+ModifierTypeInfo modifierType_Screw = {
+ /* name */ "Screw",
+ /* structName */ "ScrewModifierData",
+ /* structSize */ sizeof(ScrewModifierData),
+ /* type */ eModifierTypeType_Constructive,
+
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
new file mode 100644
index 00000000000..943a4bcdda2
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -0,0 +1,157 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ KeyBlock *kb= ob_get_keyblock(ob);
+ float (*deformedVerts)[3];
+
+ if(kb && kb->totelem == numVerts) {
+ deformedVerts= (float(*)[3])do_ob_key(md->scene, ob);
+ if(deformedVerts) {
+ memcpy(vertexCos, deformedVerts, sizeof(float)*3*numVerts);
+ MEM_freeN(deformedVerts);
+ }
+ }
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ Key *key= ob_get_key(ob);
+
+ if(key && key->type == KEY_RELATIVE)
+ deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
+}
+
+static void deformMatricesEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3],
+ float (*defMats)[3][3], int numVerts)
+{
+ Key *key= ob_get_key(ob);
+ KeyBlock *kb= ob_get_keyblock(ob);
+ float scale[3][3];
+ int a;
+
+ if(kb && kb->totelem==numVerts && kb!=key->refkey) {
+ scale_m3_fl(scale, kb->curval);
+
+ for(a=0; a<numVerts; a++)
+ copy_m3_m3(defMats[a], scale);
+ }
+}
+
+
+ModifierTypeInfo modifierType_ShapeKey = {
+ /* name */ "ShapeKey",
+ /* structName */ "ShapeKeyModifierData",
+ /* structSize */ sizeof(ShapeKeyModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ 0,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ deformMatricesEM,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ 0,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
new file mode 100644
index 00000000000..43df8c27b7a
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -0,0 +1,218 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+/* Shrinkwrap */
+
+static void initData(ModifierData *md)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
+ smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
+ smd->shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR;
+ smd->keepDist = 0.0f;
+
+ smd->target = NULL;
+ smd->auxTarget = NULL;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*)md;
+ ShrinkwrapModifierData *tsmd = (ShrinkwrapModifierData*)target;
+
+ tsmd->target = smd->target;
+ tsmd->auxTarget = smd->auxTarget;
+
+ strcpy(tsmd->vgroup_name, smd->vgroup_name);
+
+ tsmd->keepDist = smd->keepDist;
+ tsmd->shrinkType= smd->shrinkType;
+ tsmd->shrinkOpts= smd->shrinkOpts;
+ tsmd->projAxis = smd->projAxis;
+ tsmd->subsurfLevels = smd->subsurfLevels;
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(smd->vgroup_name[0])
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ if(smd->shrinkType == MOD_SHRINKWRAP_PROJECT
+ && smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL)
+ dataMask |= (1 << CD_MVERT);
+
+ return dataMask;
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
+ return !smd->target;
+}
+
+
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
+
+ walk(userData, ob, &smd->target);
+ walk(userData, ob, &smd->auxTarget);
+}
+
+static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = derivedData;
+ CustomDataMask dataMask = requiredDataMask(ob, md);
+
+ /* ensure we get a CDDM with applied vertex coords */
+ if(dataMask)
+ dm= get_cddm(md->scene, ob, NULL, dm, vertexCos);
+
+ shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static void deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+ CustomDataMask dataMask = requiredDataMask(ob, md);
+
+ /* ensure we get a CDDM with applied vertex coords */
+ if(dataMask)
+ dm= get_cddm(md->scene, ob, editData, dm, vertexCos);
+
+ shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
+
+ if (smd->target)
+ dag_add_relation(forest, dag_get_node(forest, smd->target), obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
+
+ if (smd->auxTarget)
+ dag_add_relation(forest, dag_get_node(forest, smd->auxTarget), obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
+}
+
+
+ModifierTypeInfo modifierType_Shrinkwrap = {
+ /* name */ "Shrinkwrap",
+ /* structName */ "ShrinkwrapModifierData",
+ /* structSize */ sizeof(ShrinkwrapModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
new file mode 100644
index 00000000000..01b70f20806
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -0,0 +1,424 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+#include "DNA_object_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_lattice.h"
+#include "BKE_deform.h"
+#include "BKE_utildefines.h"
+#include "BLI_math.h"
+#include "BKE_shrinkwrap.h"
+
+#include <string.h>
+#include <math.h>
+
+
+/* Clamps/Limits the given coordinate to: limits[0] <= co[axis] <= limits[1]
+ * The ammount of clamp is saved on dcut */
+static void axis_limit(int axis, const float limits[2], float co[3], float dcut[3])
+{
+ float val = co[axis];
+ if(limits[0] > val) val = limits[0];
+ if(limits[1] < val) val = limits[1];
+
+ dcut[axis] = co[axis] - val;
+ co[axis] = val;
+}
+
+static void simpleDeform_taper(const float factor, const float dcut[3], float *co)
+{
+ float x = co[0], y = co[1], z = co[2];
+ float scale = z*factor;
+
+ co[0] = x + x*scale;
+ co[1] = y + y*scale;
+ co[2] = z;
+
+ if(dcut)
+ {
+ co[0] += dcut[0];
+ co[1] += dcut[1];
+ co[2] += dcut[2];
+ }
+}
+
+static void simpleDeform_stretch(const float factor, const float dcut[3], float *co)
+{
+ float x = co[0], y = co[1], z = co[2];
+ float scale;
+
+ scale = (z*z*factor-factor + 1.0);
+
+ co[0] = x*scale;
+ co[1] = y*scale;
+ co[2] = z*(1.0+factor);
+
+
+ if(dcut)
+ {
+ co[0] += dcut[0];
+ co[1] += dcut[1];
+ co[2] += dcut[2];
+ }
+}
+
+static void simpleDeform_twist(const float factor, const float *dcut, float *co)
+{
+ float x = co[0], y = co[1], z = co[2];
+ float theta, sint, cost;
+
+ theta = z*factor;
+ sint = sin(theta);
+ cost = cos(theta);
+
+ co[0] = x*cost - y*sint;
+ co[1] = x*sint + y*cost;
+ co[2] = z;
+
+ if(dcut)
+ {
+ co[0] += dcut[0];
+ co[1] += dcut[1];
+ co[2] += dcut[2];
+ }
+}
+
+static void simpleDeform_bend(const float factor, const float dcut[3], float *co)
+{
+ float x = co[0], y = co[1], z = co[2];
+ float theta, sint, cost;
+
+ theta = x*factor;
+ sint = sin(theta);
+ cost = cos(theta);
+
+ if(fabs(factor) > 1e-7f)
+ {
+ co[0] = -(y-1.0f/factor)*sint;
+ co[1] = (y-1.0f/factor)*cost + 1.0f/factor;
+ co[2] = z;
+ }
+
+
+ if(dcut)
+ {
+ co[0] += cost*dcut[0];
+ co[1] += sint*dcut[0];
+ co[2] += dcut[2];
+ }
+
+}
+
+
+/* simple deform modifier */
+void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
+{
+ static const float lock_axis[2] = {0.0f, 0.0f};
+
+ int i;
+ int limit_axis = 0;
+ float smd_limit[2], smd_factor;
+ SpaceTransform *transf = NULL, tmp_transf;
+ void (*simpleDeform_callback)(const float factor, const float dcut[3], float *co) = NULL; //Mode callback
+ int vgroup = defgroup_name_index(ob, smd->vgroup_name);
+ MDeformVert *dvert = NULL;
+
+ //Safe-check
+ if(smd->origin == ob) smd->origin = NULL; //No self references
+
+ if(smd->limit[0] < 0.0) smd->limit[0] = 0.0f;
+ if(smd->limit[0] > 1.0) smd->limit[0] = 1.0f;
+
+ smd->limit[0] = MIN2(smd->limit[0], smd->limit[1]); //Upper limit >= than lower limit
+
+ //Calculate matrixs do convert between coordinate spaces
+ if(smd->origin)
+ {
+ transf = &tmp_transf;
+
+ if(smd->originOpts & MOD_SIMPLEDEFORM_ORIGIN_LOCAL)
+ {
+ space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat);
+ }
+ else
+ {
+ copy_m4_m4(transf->local2target, smd->origin->obmat);
+ invert_m4_m4(transf->target2local, transf->local2target);
+ }
+ }
+
+ //Setup vars
+ limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; //Bend limits on X.. all other modes limit on Z
+
+ //Update limits if needed
+ {
+ float lower = FLT_MAX;
+ float upper = -FLT_MAX;
+
+ for(i=0; i<numVerts; i++)
+ {
+ float tmp[3];
+ VECCOPY(tmp, vertexCos[i]);
+
+ if(transf) space_transform_apply(transf, tmp);
+
+ lower = MIN2(lower, tmp[limit_axis]);
+ upper = MAX2(upper, tmp[limit_axis]);
+ }
+
+
+ //SMD values are normalized to the BV, calculate the absolut values
+ smd_limit[1] = lower + (upper-lower)*smd->limit[1];
+ smd_limit[0] = lower + (upper-lower)*smd->limit[0];
+
+ smd_factor = smd->factor / MAX2(FLT_EPSILON, smd_limit[1]-smd_limit[0]);
+ }
+
+
+ if(dm)
+ {
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+ }
+ else if(ob->type == OB_LATTICE)
+ {
+ dvert = lattice_get_deform_verts(ob);
+ }
+
+
+
+ switch(smd->mode)
+ {
+ case MOD_SIMPLEDEFORM_MODE_TWIST: simpleDeform_callback = simpleDeform_twist; break;
+ case MOD_SIMPLEDEFORM_MODE_BEND: simpleDeform_callback = simpleDeform_bend; break;
+ case MOD_SIMPLEDEFORM_MODE_TAPER: simpleDeform_callback = simpleDeform_taper; break;
+ case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch; break;
+ default:
+ return; //No simpledeform mode?
+ }
+
+ for(i=0; i<numVerts; i++)
+ {
+ float weight = defvert_array_find_weight_safe(dvert, i, vgroup);
+
+ if(weight != 0.0f)
+ {
+ float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};
+
+ if(transf) space_transform_apply(transf, vertexCos[i]);
+
+ VECCOPY(co, vertexCos[i]);
+
+ //Apply axis limits
+ if(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) //Bend mode shoulnt have any lock axis
+ {
+ if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut);
+ if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut);
+ }
+ axis_limit(limit_axis, smd_limit, co, dcut);
+
+ simpleDeform_callback(smd_factor, dcut, co); //Apply deform
+ interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight); //Use vertex weight has coef of linear interpolation
+
+ if(transf) space_transform_invert(transf, vertexCos[i]);
+ }
+ }
+}
+
+
+
+
+/* SimpleDeform */
+static void initData(ModifierData *md)
+{
+ SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
+
+ smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST;
+ smd->axis = 0;
+
+ smd->origin = NULL;
+ smd->factor = 0.35f;
+ smd->limit[0] = 0.0f;
+ smd->limit[1] = 1.0f;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md;
+ SimpleDeformModifierData *tsmd = (SimpleDeformModifierData*)target;
+
+ tsmd->mode = smd->mode;
+ tsmd->axis = smd->axis;
+ tsmd->origin= smd->origin;
+ tsmd->factor= smd->factor;
+ memcpy(tsmd->limit, smd->limit, sizeof(tsmd->limit));
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(smd->vgroup_name[0])
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
+{
+ SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md;
+ walk(userData, ob, &smd->origin);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode)
+{
+ SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md;
+
+ if (smd->origin)
+ dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier");
+}
+
+static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = derivedData;
+ CustomDataMask dataMask = requiredDataMask(ob, md);
+
+ /* we implement requiredDataMask but thats not really usefull since
+ mesh_calc_modifiers pass a NULL derivedData */
+ if(dataMask)
+ dm= get_dm(md->scene, ob, NULL, dm, NULL, 0);
+
+ SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static void deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+ CustomDataMask dataMask = requiredDataMask(ob, md);
+
+ /* we implement requiredDataMask but thats not really usefull since
+ mesh_calc_modifiers pass a NULL derivedData */
+ if(dataMask)
+ dm= get_dm(md->scene, ob, editData, dm, NULL, 0);
+
+ SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_SimpleDeform = {
+ /* name */ "SimpleDeform",
+ /* structName */ "SimpleDeformModifierData",
+ /* structSize */ sizeof(SimpleDeformModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
new file mode 100644
index 00000000000..73054a90706
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -0,0 +1,181 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+static void initData(ModifierData *md)
+{
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+
+ smd->domain = NULL;
+ smd->flow = NULL;
+ smd->coll = NULL;
+ smd->type = 0;
+ smd->time = -1;
+}
+
+static void freeData(ModifierData *md)
+{
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+
+ smokeModifier_free (smd);
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+ DerivedMesh *dm = dm= get_cddm(md->scene, ob, NULL, derivedData, vertexCos);
+
+ smokeModifier_do(smd, md->scene, ob, dm, useRenderParams, isFinalCalc);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
+ DagNode *obNode)
+{
+ /*SmokeModifierData *smd = (SmokeModifierData *) md;
+ if(smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
+ {
+ if(smd->domain->fluid_group)
+ {
+ GroupObject *go = NULL;
+
+ for(go = smd->domain->fluid_group->gobject.first; go; go = go->next)
+ {
+ if(go->ob)
+ {
+ SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
+
+ // check for initialized smoke object
+ if(smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
+ {
+ DagNode *curNode = dag_get_node(forest, go->ob);
+ dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Smoke Flow");
+ }
+ }
+ }
+ }
+ }
+ */
+}
+
+
+ModifierTypeInfo modifierType_Smoke = {
+ /* name */ "Smoke",
+ /* structName */ "SmokeModifierData",
+ /* structSize */ sizeof(SmokeModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_UsesPointCache
+ | eModifierTypeFlag_Single,
+
+ /* copyData */ 0,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ freeData,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
new file mode 100644
index 00000000000..da7d1929e4a
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -0,0 +1,313 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+static void initData(ModifierData *md)
+{
+ SmoothModifierData *smd = (SmoothModifierData*) md;
+
+ smd->fac = 0.5f;
+ smd->repeat = 1;
+ smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
+ smd->defgrp_name[0] = '\0';
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ SmoothModifierData *smd = (SmoothModifierData*) md;
+ SmoothModifierData *tsmd = (SmoothModifierData*) target;
+
+ tsmd->fac = smd->fac;
+ tsmd->repeat = smd->repeat;
+ tsmd->flag = smd->flag;
+ strncpy(tsmd->defgrp_name, smd->defgrp_name, 32);
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ SmoothModifierData *smd = (SmoothModifierData*) md;
+ short flag;
+
+ flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
+
+ /* disable if modifier is off for X, Y and Z or if factor is 0 */
+ if((smd->fac == 0.0f) || flag == 0) return 1;
+
+ return 0;
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ SmoothModifierData *smd = (SmoothModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(smd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void smoothModifier_do(
+ SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ MDeformVert *dvert = NULL;
+ MEdge *medges = NULL;
+
+ int i, j, numDMEdges, defgrp_index;
+ unsigned char *uctmp;
+ float *ftmp, fac, facm;
+
+ ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
+ "smoothmodifier_f");
+ if (!ftmp) return;
+ uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
+ "smoothmodifier_uc");
+ if (!uctmp) {
+ if (ftmp) MEM_freeN(ftmp);
+ return;
+ }
+
+ fac = smd->fac;
+ facm = 1 - fac;
+
+ medges = dm->getEdgeArray(dm);
+ numDMEdges = dm->getNumEdges(dm);
+
+ defgrp_index = defgroup_name_index(ob, smd->defgrp_name);
+
+ if (defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ /* NOTICE: this can be optimized a little bit by moving the
+ * if (dvert) out of the loop, if needed */
+ for (j = 0; j < smd->repeat; j++) {
+ for (i = 0; i < numDMEdges; i++) {
+ float fvec[3];
+ float *v1, *v2;
+ unsigned int idx1, idx2;
+
+ idx1 = medges[i].v1;
+ idx2 = medges[i].v2;
+
+ v1 = vertexCos[idx1];
+ v2 = vertexCos[idx2];
+
+ fvec[0] = (v1[0] + v2[0]) / 2.0;
+ fvec[1] = (v1[1] + v2[1]) / 2.0;
+ fvec[2] = (v1[2] + v2[2]) / 2.0;
+
+ v1 = &ftmp[idx1*3];
+ v2 = &ftmp[idx2*3];
+
+ if (uctmp[idx1] < 255) {
+ uctmp[idx1]++;
+ add_v3_v3v3(v1, v1, fvec);
+ }
+ if (uctmp[idx2] < 255) {
+ uctmp[idx2]++;
+ add_v3_v3v3(v2, v2, fvec);
+ }
+ }
+
+ if (dvert) {
+ for (i = 0; i < numVerts; i++) {
+ MDeformWeight *dw = NULL;
+ float f, fm, facw, *fp, *v;
+ int k;
+ short flag = smd->flag;
+
+ v = vertexCos[i];
+ fp = &ftmp[i*3];
+
+ for (k = 0; k < dvert[i].totweight; ++k) {
+ if(dvert[i].dw[k].def_nr == defgrp_index) {
+ dw = &dvert[i].dw[k];
+ break;
+ }
+ }
+ if (!dw) continue;
+
+ f = fac * dw->weight;
+ fm = 1.0f - f;
+
+ /* fp is the sum of uctmp[i] verts, so must be averaged */
+ facw = 0.0f;
+ if (uctmp[i])
+ facw = f / (float)uctmp[i];
+
+ if (flag & MOD_SMOOTH_X)
+ v[0] = fm * v[0] + facw * fp[0];
+ if (flag & MOD_SMOOTH_Y)
+ v[1] = fm * v[1] + facw * fp[1];
+ if (flag & MOD_SMOOTH_Z)
+ v[2] = fm * v[2] + facw * fp[2];
+ }
+ }
+ else { /* no vertex group */
+ for (i = 0; i < numVerts; i++) {
+ float facw, *fp, *v;
+ short flag = smd->flag;
+
+ v = vertexCos[i];
+ fp = &ftmp[i*3];
+
+ /* fp is the sum of uctmp[i] verts, so must be averaged */
+ facw = 0.0f;
+ if (uctmp[i])
+ facw = fac / (float)uctmp[i];
+
+ if (flag & MOD_SMOOTH_X)
+ v[0] = facm * v[0] + facw * fp[0];
+ if (flag & MOD_SMOOTH_Y)
+ v[1] = facm * v[1] + facw * fp[1];
+ if (flag & MOD_SMOOTH_Z)
+ v[2] = facm * v[2] + facw * fp[2];
+ }
+
+ }
+
+ memset(ftmp, 0, 3*sizeof(float)*numVerts);
+ memset(uctmp, 0, sizeof(unsigned char)*numVerts);
+ }
+
+ MEM_freeN(ftmp);
+ MEM_freeN(uctmp);
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm= get_dm(md->scene, ob, NULL, derivedData, NULL, 0);
+
+ smoothModifier_do((SmoothModifierData *)md, ob, dm,
+ vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm= get_dm(md->scene, ob, editData, derivedData, NULL, 0);
+
+ smoothModifier_do((SmoothModifierData *)md, ob, dm,
+ vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Smooth = {
+ /* name */ "Smooth",
+ /* structName */ "SmoothModifierData",
+ /* structSize */ sizeof(SmoothModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
new file mode 100644
index 00000000000..50c7df572af
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -0,0 +1,125 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ sbObjectStep(md->scene, ob, (float)md->scene->r.cfra, vertexCos, numVerts);
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+
+ModifierTypeInfo modifierType_Softbody = {
+ /* name */ "Softbody",
+ /* structName */ "SoftbodyModifierData",
+ /* structSize */ sizeof(SoftbodyModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_RequiresOriginalData
+ | eModifierTypeFlag_Single,
+
+ /* copyData */ 0,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ 0,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
new file mode 100644
index 00000000000..70feef967dc
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -0,0 +1,692 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+typedef struct EdgeFaceRef {
+ int f1; /* init as -1 */
+ int f2;
+} EdgeFaceRef;
+
+static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
+{
+ int i, numVerts, numEdges, numFaces;
+ MFace *mface, *mf;
+ MVert *mvert, *mv;
+
+ float (*face_nors)[3];
+ float *f_no;
+ int calc_face_nors= 0;
+
+ numVerts = dm->getNumVerts(dm);
+ numEdges = dm->getNumEdges(dm);
+ numFaces = dm->getNumFaces(dm);
+ mface = dm->getFaceArray(dm);
+ mvert = dm->getVertArray(dm);
+
+ /* we don't want to overwrite any referenced layers */
+
+ /*
+ Dosnt work here!
+ mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
+ cddm->mvert = mv;
+ */
+
+ face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ if(!face_nors) {
+ calc_face_nors = 1;
+ face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, numFaces);
+ }
+
+ mv = mvert;
+ mf = mface;
+
+ {
+ EdgeHash *edge_hash = BLI_edgehash_new();
+ EdgeHashIterator *edge_iter;
+ int edge_ref_count = 0;
+ int ed_v1, ed_v2; /* use when getting the key */
+ EdgeFaceRef *edge_ref_array = MEM_callocN(numEdges * sizeof(EdgeFaceRef), "Edge Connectivity");
+ EdgeFaceRef *edge_ref;
+ float edge_normal[3];
+
+ /* This function adds an edge hash if its not there, and adds the face index */
+#define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \
+ edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \
+ if (!edge_ref) { \
+ edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \
+ edge_ref->f1=i; \
+ edge_ref->f2=-1; \
+ BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \
+ } else { \
+ edge_ref->f2=i; \
+ }
+
+ for(i = 0; i < numFaces; i++, mf++) {
+ f_no = face_nors[i];
+
+ if(mf->v4) {
+ if(calc_face_nors)
+ normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
+
+ NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
+ NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
+ NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v4);
+ NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v4, mf->v1);
+ } else {
+ if(calc_face_nors)
+ normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
+
+ NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
+ NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
+ NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v1);
+ }
+ }
+
+ for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) {
+ /* Get the edge vert indicies, and edge value (the face indicies that use it)*/
+ BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2);
+ edge_ref = BLI_edgehashIterator_getValue(edge_iter);
+
+ if (edge_ref->f2 != -1) {
+ /* We have 2 faces using this edge, calculate the edges normal
+ * using the angle between the 2 faces as a weighting */
+ add_v3_v3v3(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]);
+ normalize_v3(edge_normal);
+ mul_v3_fl(edge_normal, angle_normalized_v3v3(face_nors[edge_ref->f1], face_nors[edge_ref->f2]));
+ } else {
+ /* only one face attached to that edge */
+ /* an edge without another attached- the weight on this is
+ * undefined, M_PI/2 is 90d in radians and that seems good enough */
+ VECCOPY(edge_normal, face_nors[edge_ref->f1])
+ mul_v3_fl(edge_normal, M_PI/2);
+ }
+ add_v3_v3(temp_nors[ed_v1], edge_normal);
+ add_v3_v3(temp_nors[ed_v2], edge_normal);
+ }
+ BLI_edgehashIterator_free(edge_iter);
+ BLI_edgehash_free(edge_hash, NULL);
+ MEM_freeN(edge_ref_array);
+ }
+
+ /* normalize vertex normals and assign */
+ for(i = 0; i < numVerts; i++, mv++) {
+ if(normalize_v3(temp_nors[i]) == 0.0f) {
+ normal_short_to_float_v3(temp_nors[i], mv->no);
+ }
+ }
+}
+
+static void initData(ModifierData *md)
+{
+ SolidifyModifierData *smd = (SolidifyModifierData*) md;
+ smd->offset = 0.01f;
+ smd->flag = MOD_SOLIDIFY_RIM;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ SolidifyModifierData *smd = (SolidifyModifierData*) md;
+ SolidifyModifierData *tsmd = (SolidifyModifierData*) target;
+ tsmd->offset = smd->offset;
+ tsmd->offset_fac = smd->offset_fac;
+ tsmd->crease_inner = smd->crease_inner;
+ tsmd->crease_outer = smd->crease_outer;
+ tsmd->crease_rim = smd->crease_rim;
+ tsmd->flag = smd->flag;
+ strcpy(tsmd->defgrp_name, smd->defgrp_name);
+}
+
+static DerivedMesh *applyModifier(ModifierData *md,
+ Object *ob,
+ DerivedMesh *dm,
+ int useRenderParams,
+ int isFinalCalc)
+{
+ int i;
+ DerivedMesh *result;
+ SolidifyModifierData *smd = (SolidifyModifierData*) md;
+
+ MFace *mf, *mface, *orig_mface;
+ MEdge *ed, *medge, *orig_medge;
+ MVert *mv, *mvert, *orig_mvert;
+
+ int numVerts = dm->getNumVerts(dm);
+ int numEdges = dm->getNumEdges(dm);
+ int numFaces = dm->getNumFaces(dm);
+
+ /* use for edges */
+ int *new_vert_arr= NULL;
+ int newFaces = 0;
+
+ int *new_edge_arr= NULL;
+ int newEdges = 0;
+
+ int *edge_users= NULL;
+ char *edge_order= NULL;
+
+ float (*vert_nors)[3]= NULL;
+
+ float ofs_orig= - (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset);
+ float ofs_new= smd->offset - (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset);
+
+ /* weights */
+ MDeformVert *dvert= NULL, *dv= NULL;
+ int defgrp_index= -1;
+ int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0);
+
+ defgrp_index= defgroup_name_index(ob, smd->defgrp_name);
+
+ if (defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ orig_mface = dm->getFaceArray(dm);
+ orig_medge = dm->getEdgeArray(dm);
+ orig_mvert = dm->getVertArray(dm);
+
+ if(smd->flag & MOD_SOLIDIFY_RIM) {
+ EdgeHash *edgehash = BLI_edgehash_new();
+ EdgeHashIterator *ehi;
+ int v1, v2;
+ int eidx;
+
+ for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) {
+ mv->flag &= ~ME_VERT_TMP_TAG;
+ }
+
+ for(i=0, ed=orig_medge; i<numEdges; i++, ed++) {
+ BLI_edgehash_insert(edgehash, ed->v1, ed->v2, SET_INT_IN_POINTER(i));
+ }
+
+#define INVALID_UNUSED -1
+#define INVALID_PAIR -2
+
+#define ADD_EDGE_USER(_v1, _v2, edge_ord) \
+ eidx= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, _v1, _v2)); \
+ if(edge_users[eidx] == INVALID_UNUSED) { \
+ ed= orig_medge + eidx; \
+ edge_users[eidx]= (_v1 < _v2) == (ed->v1 < ed->v2) ? i:(i+numFaces); \
+ edge_order[eidx]= edge_ord; \
+ } else { \
+ edge_users[eidx]= INVALID_PAIR; \
+ } \
+
+
+ edge_users= MEM_mallocN(sizeof(int) * numEdges, "solid_mod edges");
+ edge_order= MEM_mallocN(sizeof(char) * numEdges, "solid_mod eorder");
+ memset(edge_users, INVALID_UNUSED, sizeof(int) * numEdges);
+
+ for(i=0, mf=orig_mface; i<numFaces; i++, mf++) {
+ if(mf->v4) {
+ ADD_EDGE_USER(mf->v1, mf->v2, 0);
+ ADD_EDGE_USER(mf->v2, mf->v3, 1);
+ ADD_EDGE_USER(mf->v3, mf->v4, 2);
+ ADD_EDGE_USER(mf->v4, mf->v1, 3);
+ }
+ else {
+ ADD_EDGE_USER(mf->v1, mf->v2, 0);
+ ADD_EDGE_USER(mf->v2, mf->v3, 1);
+ ADD_EDGE_USER(mf->v3, mf->v1, 2);
+ }
+ }
+
+#undef ADD_EDGE_USER
+#undef INVALID_UNUSED
+#undef INVALID_PAIR
+
+
+ new_edge_arr= MEM_callocN(sizeof(int) * numEdges, "solid_mod arr");
+
+ ehi= BLI_edgehashIterator_new(edgehash);
+ for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ int eidx= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
+ if(edge_users[eidx] >= 0) {
+ BLI_edgehashIterator_getKey(ehi, &v1, &v2);
+ orig_mvert[v1].flag |= ME_VERT_TMP_TAG;
+ orig_mvert[v2].flag |= ME_VERT_TMP_TAG;
+ new_edge_arr[newFaces]= eidx;
+ newFaces++;
+ }
+ }
+ BLI_edgehashIterator_free(ehi);
+
+
+
+ new_vert_arr= MEM_callocN(sizeof(int) * numVerts, "solid_mod new_varr");
+ for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) {
+ if(mv->flag & ME_VERT_TMP_TAG) {
+ new_vert_arr[newEdges] = i;
+ newEdges++;
+
+ mv->flag &= ~ME_VERT_TMP_TAG;
+ }
+ }
+
+ BLI_edgehash_free(edgehash, NULL);
+ }
+
+ if(smd->flag & MOD_SOLIDIFY_NORMAL_CALC) {
+ vert_nors= MEM_callocN(sizeof(float) * numVerts * 3, "mod_solid_vno_hq");
+ dm_calc_normal(dm, vert_nors);
+ }
+
+ result = CDDM_from_template(dm, numVerts * 2, (numEdges * 2) + newEdges, (numFaces * 2) + newFaces);
+
+ mface = result->getFaceArray(result);
+ medge = result->getEdgeArray(result);
+ mvert = result->getVertArray(result);
+
+ DM_copy_face_data(dm, result, 0, 0, numFaces);
+ DM_copy_face_data(dm, result, 0, numFaces, numFaces);
+
+ DM_copy_edge_data(dm, result, 0, 0, numEdges);
+ DM_copy_edge_data(dm, result, 0, numEdges, numEdges);
+
+ DM_copy_vert_data(dm, result, 0, 0, numVerts);
+ DM_copy_vert_data(dm, result, 0, numVerts, numVerts);
+
+ {
+ static int corner_indices[4] = {2, 1, 0, 3};
+ int is_quad;
+
+ for(i=0, mf=mface+numFaces; i<numFaces; i++, mf++) {
+ mf->v1 += numVerts;
+ mf->v2 += numVerts;
+ mf->v3 += numVerts;
+ if(mf->v4)
+ mf->v4 += numVerts;
+
+ /* Flip face normal */
+ {
+ is_quad = mf->v4;
+ SWAP(int, mf->v1, mf->v3);
+ DM_swap_face_data(result, i+numFaces, corner_indices);
+ test_index_face(mf, &result->faceData, numFaces, is_quad ? 4:3);
+ }
+ }
+ }
+
+ for(i=0, ed=medge+numEdges; i<numEdges; i++, ed++) {
+ ed->v1 += numVerts;
+ ed->v2 += numVerts;
+ }
+
+ /* note, copied vertex layers dont have flipped normals yet. do this after applying offset */
+ if((smd->flag & MOD_SOLIDIFY_EVEN) == 0) {
+ /* no even thickness, very simple */
+ float scalar_short;
+ float scalar_short_vgroup;
+
+
+ if(ofs_new != 0.0f) {
+ scalar_short= scalar_short_vgroup= ofs_new / 32767.0f;
+ mv= mvert + ((ofs_new >= ofs_orig) ? 0 : numVerts);
+ dv= dvert;
+ for(i=0; i<numVerts; i++, mv++) {
+ if(dv) {
+ if(defgrp_invert) scalar_short_vgroup = scalar_short * (1.0f - defvert_find_weight(dv, defgrp_index));
+ else scalar_short_vgroup = scalar_short * defvert_find_weight(dv, defgrp_index);
+ dv++;
+ }
+ VECADDFAC(mv->co, mv->co, mv->no, scalar_short_vgroup);
+ }
+ }
+
+ if(ofs_orig != 0.0f) {
+ scalar_short= scalar_short_vgroup= ofs_orig / 32767.0f;
+ mv= mvert + ((ofs_new >= ofs_orig) ? numVerts : 0); /* same as above but swapped, intentional use of 'ofs_new' */
+ dv= dvert;
+ for(i=0; i<numVerts; i++, mv++) {
+ if(dv) {
+ if(defgrp_invert) scalar_short_vgroup = scalar_short * (1.0f - defvert_find_weight(dv, defgrp_index));
+ else scalar_short_vgroup = scalar_short * defvert_find_weight(dv, defgrp_index);
+ dv++;
+ }
+ VECADDFAC(mv->co, mv->co, mv->no, scalar_short_vgroup);
+ }
+ }
+
+ }
+ else {
+ /* make a face normal layer if not present */
+ float (*face_nors)[3];
+ int face_nors_calc= 0;
+
+ /* same as EM_solidify() in editmesh_lib.c */
+ float *vert_angles= MEM_callocN(sizeof(float) * numVerts * 2, "mod_solid_pair"); /* 2 in 1 */
+ float *vert_accum= vert_angles + numVerts;
+ float face_angles[4];
+ int i, j, vidx;
+
+ face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ if(!face_nors) {
+ face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, dm->numFaceData);
+ face_nors_calc= 1;
+ }
+
+ if(vert_nors==NULL) {
+ vert_nors= MEM_mallocN(sizeof(float) * numVerts * 3, "mod_solid_vno");
+ for(i=0, mv=mvert; i<numVerts; i++, mv++) {
+ normal_short_to_float_v3(vert_nors[i], mv->no);
+ }
+ }
+
+ for(i=0, mf=mface; i<numFaces; i++, mf++) {
+
+ /* just added, calc the normal */
+ if(face_nors_calc) {
+ if(mf->v4)
+ normal_quad_v3(face_nors[i], mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
+ else
+ normal_tri_v3(face_nors[i] , mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
+ }
+
+ if(mf->v4) {
+ angle_quad_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
+ j= 3;
+ }
+ else {
+ angle_tri_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
+ j= 2;
+ }
+
+ for(; j>=0; j--) {
+ vidx = *(&mf->v1 + j);
+ vert_accum[vidx] += face_angles[j];
+ vert_angles[vidx]+= shell_angle_to_dist(angle_normalized_v3v3(vert_nors[vidx], face_nors[i])) * face_angles[j];
+ }
+ }
+
+ /* vertex group support */
+ if(dvert) {
+ dv= dvert;
+ if(defgrp_invert) {
+ for(i=0; i<numVerts; i++, dv++) {
+ vert_angles[i] *= (1.0f - defvert_find_weight(dv, defgrp_index));
+ }
+ }
+ else {
+ for(i=0; i<numVerts; i++, dv++) {
+ vert_angles[i] *= defvert_find_weight(dv, defgrp_index);
+ }
+ }
+ }
+
+ if(ofs_new) {
+ mv= mvert + ((ofs_new >= ofs_orig) ? 0 : numVerts);
+
+ for(i=0; i<numVerts; i++, mv++) {
+ if(vert_accum[i]) { /* zero if unselected */
+ madd_v3_v3fl(mv->co, vert_nors[i], ofs_new * (vert_angles[i] / vert_accum[i]));
+ }
+ }
+ }
+
+ if(ofs_orig) {
+ mv= mvert + ((ofs_new >= ofs_orig) ? numVerts : 0); /* same as above but swapped, intentional use of 'ofs_new' */
+
+ for(i=0; i<numVerts; i++, mv++) {
+ if(vert_accum[i]) { /* zero if unselected */
+ madd_v3_v3fl(mv->co, vert_nors[i], ofs_orig * (vert_angles[i] / vert_accum[i]));
+ }
+ }
+ }
+
+ MEM_freeN(vert_angles);
+ }
+
+ if(vert_nors)
+ MEM_freeN(vert_nors);
+
+ /* flip vertex normals for copied verts */
+ mv= mvert + numVerts;
+ for(i=0; i<numVerts; i++, mv++) {
+ mv->no[0]= -mv->no[0];
+ mv->no[1]= -mv->no[1];
+ mv->no[2]= -mv->no[2];
+ }
+
+ if(smd->flag & MOD_SOLIDIFY_RIM) {
+
+
+ /* bugger, need to re-calculate the normals for the new edge faces.
+ * This could be done in many ways, but probably the quickest way is to calculate the average normals for side faces only.
+ * Then blend them with the normals of the edge verts.
+ *
+ * at the moment its easiest to allocate an entire array for every vertex, even though we only need edge verts - campbell
+ */
+
+#define SOLIDIFY_SIDE_NORMALS
+
+#ifdef SOLIDIFY_SIDE_NORMALS
+ /* annoying to allocate these since we only need the edge verts, */
+ float (*edge_vert_nos)[3]= MEM_callocN(sizeof(float) * numVerts * 3, "solidify_edge_nos");
+ float nor[3];
+#endif
+
+ const unsigned char crease_rim= smd->crease_rim * 255.0f;
+ const unsigned char crease_outer= smd->crease_outer * 255.0f;
+ const unsigned char crease_inner= smd->crease_inner * 255.0f;
+
+ const int edge_indices[4][4] = {
+ {1, 0, 0, 1},
+ {2, 1, 1, 2},
+ {3, 2, 2, 3},
+ {0, 3, 3, 0}};
+
+ /* add faces & edges */
+ ed= medge + (numEdges * 2);
+ for(i=0; i<newEdges; i++, ed++) {
+ ed->v1= new_vert_arr[i];
+ ed->v2= new_vert_arr[i] + numVerts;
+ ed->flag |= ME_EDGEDRAW;
+
+ if(crease_rim)
+ ed->crease= crease_rim;
+ }
+
+ /* faces */
+ mf= mface + (numFaces * 2);
+ for(i=0; i<newFaces; i++, mf++) {
+ int eidx= new_edge_arr[i];
+ int fidx= edge_users[eidx];
+ int flip;
+
+ if(fidx >= numFaces) {
+ fidx -= numFaces;
+ flip= 1;
+ }
+ else {
+ flip= 0;
+ }
+
+ ed= medge + eidx;
+
+ /* copy most of the face settings */
+ DM_copy_face_data(dm, result, fidx, (numFaces * 2) + i, 1);
+
+ if(flip) {
+ DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]);
+
+ mf->v1= ed->v1;
+ mf->v2= ed->v2;
+ mf->v3= ed->v2 + numVerts;
+ mf->v4= ed->v1 + numVerts;
+ }
+ else {
+ DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]);
+
+ mf->v1= ed->v2;
+ mf->v2= ed->v1;
+ mf->v3= ed->v1 + numVerts;
+ mf->v4= ed->v2 + numVerts;
+ }
+
+ if(crease_outer)
+ ed->crease= crease_outer;
+
+ if(crease_inner) {
+ medge[numEdges + eidx].crease= crease_inner;
+ }
+
+#ifdef SOLIDIFY_SIDE_NORMALS
+ normal_quad_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
+
+ add_v3_v3(edge_vert_nos[ed->v1], nor);
+ add_v3_v3(edge_vert_nos[ed->v2], nor);
+#endif
+ }
+
+#ifdef SOLIDIFY_SIDE_NORMALS
+ ed= medge + (numEdges * 2);
+ for(i=0; i<newEdges; i++, ed++) {
+ float nor_cpy[3];
+ short *nor_short;
+ int j;
+
+ /* note, only the first vertex (lower half of the index) is calculated */
+ normalize_v3_v3(nor_cpy, edge_vert_nos[ed->v1]);
+
+ for(j=0; j<2; j++) { /* loop over both verts of the edge */
+ nor_short= mvert[*(&ed->v1 + j)].no;
+ normal_short_to_float_v3(nor, nor_short);
+ add_v3_v3(nor, nor_cpy);
+ normalize_v3(nor);
+ normal_float_to_short_v3(nor_short, nor);
+ }
+ }
+
+ MEM_freeN(edge_vert_nos);
+#endif
+
+ MEM_freeN(new_vert_arr);
+ MEM_freeN(new_edge_arr);
+ MEM_freeN(edge_users);
+ MEM_freeN(edge_order);
+ }
+
+ return result;
+}
+
+#undef SOLIDIFY_SIDE_NORMALS
+
+static DerivedMesh *applyModifierEM(ModifierData *md,
+ Object *ob,
+ EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+
+ModifierTypeInfo modifierType_Solidify = {
+ /* name */ "Solidify",
+ /* structName */ "SolidifyModifierData",
+ /* structSize */ sizeof(SolidifyModifierData),
+ /* type */ eModifierTypeType_Constructive,
+
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
new file mode 100644
index 00000000000..c33951dd640
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -0,0 +1,185 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+
+
+static void initData(ModifierData *md)
+{
+ SubsurfModifierData *smd = (SubsurfModifierData*) md;
+
+ smd->levels = 1;
+ smd->renderLevels = 2;
+ smd->flags |= eSubsurfModifierFlag_SubsurfUv;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ SubsurfModifierData *smd = (SubsurfModifierData*) md;
+ SubsurfModifierData *tsmd = (SubsurfModifierData*) target;
+
+ tsmd->flags = smd->flags;
+ tsmd->levels = smd->levels;
+ tsmd->renderLevels = smd->renderLevels;
+ tsmd->subdivType = smd->subdivType;
+}
+
+static void freeData(ModifierData *md)
+{
+ SubsurfModifierData *smd = (SubsurfModifierData*) md;
+
+ if(smd->mCache) {
+ ccgSubSurf_free(smd->mCache);
+ }
+ if(smd->emCache) {
+ ccgSubSurf_free(smd->emCache);
+ }
+}
+
+static int isDisabled(ModifierData *md, int useRenderParams)
+{
+ SubsurfModifierData *smd = (SubsurfModifierData*) md;
+ int levels= (useRenderParams)? smd->renderLevels: smd->levels;
+
+ return get_render_subsurf_level(&md->scene->r, levels) == 0;
+}
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ SubsurfModifierData *smd = (SubsurfModifierData*) md;
+ DerivedMesh *result;
+
+ result = subsurf_make_derived_from_derived(derivedData, smd,
+ useRenderParams, NULL, isFinalCalc, 0);
+
+ if(useRenderParams || !isFinalCalc) {
+ DerivedMesh *cddm= CDDM_copy(result);
+ result->release(result);
+ result= cddm;
+ }
+
+ return result;
+}
+
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ SubsurfModifierData *smd = (SubsurfModifierData*) md;
+ DerivedMesh *result;
+
+ result = subsurf_make_derived_from_derived(derivedData, smd, 0,
+ NULL, 0, 1);
+
+ return result;
+}
+
+
+ModifierTypeInfo modifierType_Subsurf = {
+ /* name */ "Subsurf",
+ /* structName */ "SubsurfModifierData",
+ /* structSize */ sizeof(SubsurfModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode
+ | eModifierTypeFlag_AcceptsCVs,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
new file mode 100644
index 00000000000..a3b19580a99
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -0,0 +1,228 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "LOD_decimation.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+/* Surface */
+
+static void initData(ModifierData *md)
+{
+ SurfaceModifierData *surmd = (SurfaceModifierData*) md;
+
+ surmd->bvhtree = NULL;
+}
+
+static void freeData(ModifierData *md)
+{
+ SurfaceModifierData *surmd = (SurfaceModifierData*) md;
+
+ if (surmd)
+ {
+ if(surmd->bvhtree) {
+ free_bvhtree_from_mesh(surmd->bvhtree);
+ MEM_freeN(surmd->bvhtree);
+ }
+
+ if(surmd->dm)
+ surmd->dm->release(surmd->dm);
+
+ if(surmd->x)
+ MEM_freeN(surmd->x);
+
+ if(surmd->v)
+ MEM_freeN(surmd->v);
+
+ surmd->bvhtree = NULL;
+ surmd->dm = NULL;
+ }
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ SurfaceModifierData *surmd = (SurfaceModifierData*) md;
+ unsigned int numverts = 0, i = 0;
+
+ if(surmd->dm)
+ surmd->dm->release(surmd->dm);
+
+ /* if possible use/create DerivedMesh */
+ if(derivedData) surmd->dm = CDDM_copy(derivedData);
+ else surmd->dm = get_dm(md->scene, ob, NULL, NULL, NULL, 0);
+
+ if(!ob->pd)
+ {
+ printf("SurfaceModifier deformVerts: Should not happen!\n");
+ return;
+ }
+
+ if(surmd->dm)
+ {
+ int init = 0;
+ float *vec;
+ MVert *x, *v;
+
+ CDDM_apply_vert_coords(surmd->dm, vertexCos);
+ CDDM_calc_normals(surmd->dm);
+
+ numverts = surmd->dm->getNumVerts ( surmd->dm );
+
+ if(numverts != surmd->numverts || surmd->x == NULL || surmd->v == NULL || md->scene->r.cfra != surmd->cfra+1) {
+ if(surmd->x) {
+ MEM_freeN(surmd->x);
+ surmd->x = NULL;
+ }
+ if(surmd->v) {
+ MEM_freeN(surmd->v);
+ surmd->v = NULL;
+ }
+
+ surmd->x = MEM_callocN(numverts * sizeof(MVert), "MVert");
+ surmd->v = MEM_callocN(numverts * sizeof(MVert), "MVert");
+
+ surmd->numverts = numverts;
+
+ init = 1;
+ }
+
+ /* convert to global coordinates and calculate velocity */
+ for(i = 0, x = surmd->x, v = surmd->v; i<numverts; i++, x++, v++) {
+ vec = CDDM_get_vert(surmd->dm, i)->co;
+ mul_m4_v3(ob->obmat, vec);
+
+ if(init)
+ v->co[0] = v->co[1] = v->co[2] = 0.0f;
+ else
+ sub_v3_v3v3(v->co, vec, x->co);
+
+ copy_v3_v3(x->co, vec);
+ }
+
+ surmd->cfra = md->scene->r.cfra;
+
+ if(surmd->bvhtree)
+ free_bvhtree_from_mesh(surmd->bvhtree);
+ else
+ surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");
+
+ if(surmd->dm->getNumFaces(surmd->dm))
+ bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
+ else
+ bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
+ }
+}
+
+
+ModifierTypeInfo modifierType_Surface = {
+ /* name */ "Surface",
+ /* structName */ "SurfaceModifierData",
+ /* structSize */ sizeof(SurfaceModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_NoUserAdd,
+
+ /* copyData */ 0,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ freeData,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
new file mode 100644
index 00000000000..d8762eb9533
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -0,0 +1,173 @@
+/**
+ * $Id: CMP_node.h 14061 2008-03-11 14:40:27Z blendix $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful;
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation;
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Ben Batt
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "DNA_modifier_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_curve_types.h"
+
+#include "MEM_guardedalloc.h"
+#include "MOD_util.h"
+
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_mesh.h"
+#include "BKE_displist.h"
+
+#include "RE_shader_ext.h"
+
+#include "BKE_utildefines.h"
+
+#include "stdlib.h"
+#include "string.h"
+
+void get_texture_value(Tex *texture, float *tex_co, TexResult *texres)
+{
+ int result_type;
+
+ result_type = multitex_ext(texture, tex_co, NULL, NULL, 0, texres);
+
+ /* if the texture gave an RGB value, we assume it didn't give a valid
+ * intensity, so calculate one (formula from do_material_tex).
+ * if the texture didn't give an RGB value, copy the intensity across
+ */
+ if(result_type & TEX_RGB)
+ texres->tin = (0.35f * texres->tr + 0.45f * texres->tg
+ + 0.2f * texres->tb);
+ else
+ texres->tr = texres->tg = texres->tb = texres->tin;
+}
+
+void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3])
+{
+ while((md=md->next) && md->type==eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+ if(amd->multi && amd->prevCos==NULL)
+ amd->prevCos= MEM_dupallocN(vertexCos);
+ else
+ break;
+ }
+ /* lattice/mesh modifier too */
+}
+
+void validate_layer_name(const CustomData *data, int type, char *name, char *outname)
+{
+ int index = -1;
+
+ /* if a layer name was given, try to find that layer */
+ if(name[0])
+ index = CustomData_get_named_layer_index(data, CD_MTFACE, name);
+
+ if(index < 0) {
+ /* either no layer was specified, or the layer we want has been
+ * deleted, so assign the active layer to name
+ */
+ index = CustomData_get_active_layer_index(data, CD_MTFACE);
+ strcpy(outname, data->layers[index].name);
+ }
+ else
+ strcpy(outname, name);
+}
+
+/* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */
+DerivedMesh *get_cddm(struct Scene *scene, Object *ob, struct EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3])
+{
+ if(dm && dm->type == DM_TYPE_CDDM)
+ return dm;
+
+ if(!dm) {
+ dm= get_dm(scene, ob, em, dm, vertexCos, 0);
+ }
+ else {
+ dm= CDDM_copy(dm);
+ CDDM_apply_vert_coords(dm, vertexCos);
+ }
+
+ if(dm)
+ CDDM_calc_normals(dm);
+
+ return dm;
+}
+
+
+static int is_last_displist(Object *ob)
+{
+ Curve *cu = ob->data;
+ static int curvecount=0, totcurve=0;
+
+ if(curvecount == 0){
+ DispList *dl;
+
+ totcurve = 0;
+ for(dl=cu->disp.first; dl; dl=dl->next)
+ totcurve++;
+ }
+
+ curvecount++;
+
+ if(curvecount == totcurve){
+ curvecount = 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */
+DerivedMesh *get_dm(struct Scene *scene, Object *ob, struct EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int orco)
+{
+ if(dm)
+ return dm;
+
+ if(ob->type==OB_MESH) {
+ if(em) dm= CDDM_from_editmesh(em, ob->data);
+ else dm = CDDM_from_mesh((struct Mesh *)(ob->data), ob);
+
+ if(vertexCos) {
+ CDDM_apply_vert_coords(dm, vertexCos);
+ //CDDM_calc_normals(dm);
+ }
+
+ if(orco)
+ DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
+ }
+ else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) {
+ if(is_last_displist(ob)) {
+ dm= CDDM_from_curve(ob);
+ }
+ }
+
+ return dm;
+}
diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h
new file mode 100644
index 00000000000..6abfdf899f4
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_util.h
@@ -0,0 +1,45 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful;
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation;
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Ben Batt
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef MOD_UTIL_H
+#define MOD_UTIL_H
+
+struct Tex;
+struct TexResult;
+struct CustomData;
+struct DerivedMesh;
+struct Object;
+struct Scene;
+struct EditMesh;
+struct ModifierData;
+
+void get_texture_value(struct Tex *texture, float *tex_co, struct TexResult *texres);
+void modifier_vgroup_cache(struct ModifierData *md, float (*vertexCos)[3]);
+void validate_layer_name(const struct CustomData *data, int type, char *name, char *outname);
+struct DerivedMesh *get_cddm(struct Scene *scene, struct Object *ob, struct EditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3]);
+struct DerivedMesh *get_dm(struct Scene *scene, struct Object *ob, struct EditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3], int orco);
+#endif /* MOD_UTIL_H */
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
new file mode 100644
index 00000000000..f86650be39a
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -0,0 +1,491 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+
+/* UVProject */
+/* UV Project modifier: Generates UVs projected from an object
+*/
+
+static void initData(ModifierData *md)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+ int i;
+
+ for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
+ umd->projectors[i] = NULL;
+ umd->image = NULL;
+ umd->flags = 0;
+ umd->num_projectors = 1;
+ umd->aspectx = umd->aspecty = 1.0f;
+ umd->scalex = umd->scaley = 1.0f;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+ UVProjectModifierData *tumd = (UVProjectModifierData*) target;
+ int i;
+
+ for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
+ tumd->projectors[i] = umd->projectors[i];
+ tumd->image = umd->image;
+ tumd->flags = umd->flags;
+ tumd->num_projectors = umd->num_projectors;
+ tumd->aspectx = umd->aspectx;
+ tumd->aspecty = umd->aspecty;
+ tumd->scalex = umd->scalex;
+ tumd->scaley = umd->scaley;
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ CustomDataMask dataMask = 0;
+
+ /* ask for UV coordinates */
+ dataMask |= (1 << CD_MTFACE);
+
+ return dataMask;
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+ int i;
+
+ for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
+ walk(userData, ob, &umd->projectors[i]);
+}
+
+static void foreachIDLink(ModifierData *md, Object *ob,
+ IDWalkFunc walk, void *userData)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+
+ walk(userData, ob, (ID **)&umd->image);
+
+ foreachObjectLink(md, ob, (ObjectWalkFunc)walk,
+ userData);
+}
+
+static void updateDepgraph(ModifierData *md,
+ DagForest *forest, Scene *scene, Object *ob, DagNode *obNode)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+ int i;
+
+ for(i = 0; i < umd->num_projectors; ++i) {
+ if(umd->projectors[i]) {
+ DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "UV Project Modifier");
+ }
+ }
+}
+
+typedef struct Projector {
+ Object *ob; /* object this projector is derived from */
+ float projmat[4][4]; /* projection matrix */
+ float normal[3]; /* projector normal in world space */
+ void *uci; /* optional uv-project info (panorama projection) */
+} Projector;
+
+static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
+ Object *ob, DerivedMesh *dm)
+{
+ float (*coords)[3], (*co)[3];
+ MTFace *tface;
+ int i, numVerts, numFaces;
+ Image *image = umd->image;
+ MFace *mface, *mf;
+ int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
+ Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
+ int num_projectors = 0;
+ float aspect;
+ char uvname[32];
+ float aspx= umd->aspectx ? umd->aspectx : 1.0f;
+ float aspy= umd->aspecty ? umd->aspecty : 1.0f;
+ float scax= umd->scalex ? umd->scalex : 1.0f;
+ float scay= umd->scaley ? umd->scaley : 1.0f;
+ int free_uci= 0;
+
+ aspect = aspx / aspy;
+
+ for(i = 0; i < umd->num_projectors; ++i)
+ if(umd->projectors[i])
+ projectors[num_projectors++].ob = umd->projectors[i];
+
+ if(num_projectors == 0) return dm;
+
+ /* make sure there are UV layers available */
+
+ if(!CustomData_has_layer(&dm->faceData, CD_MTFACE)) return dm;
+
+ /* make sure we're using an existing layer */
+ validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname);
+
+ /* calculate a projection matrix and normal for each projector */
+ for(i = 0; i < num_projectors; ++i) {
+ float tmpmat[4][4];
+ float offsetmat[4][4];
+ Camera *cam = NULL;
+ /* calculate projection matrix */
+ invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat);
+
+ projectors[i].uci= NULL;
+
+ if(projectors[i].ob->type == OB_CAMERA) {
+ cam = (Camera *)projectors[i].ob->data;
+
+ if(cam->flag & CAM_PANORAMA) {
+ projectors[i].uci= project_camera_info(projectors[i].ob, NULL, aspx, aspy);
+ free_uci= 1;
+ }
+ else if(cam->type == CAM_PERSP) {
+ float perspmat[4][4];
+ float xmax;
+ float xmin;
+ float ymax;
+ float ymin;
+ float pixsize = cam->clipsta * 32.0 / cam->lens;
+
+ if(aspect > 1.0f) {
+ xmax = 0.5f * pixsize;
+ ymax = xmax / aspect;
+ } else {
+ ymax = 0.5f * pixsize;
+ xmax = ymax * aspect;
+ }
+ xmin = -xmax;
+ ymin = -ymax;
+
+ perspective_m4( perspmat,xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend);
+ mul_m4_m4m4(tmpmat, projectors[i].projmat, perspmat);
+ } else if(cam->type == CAM_ORTHO) {
+ float orthomat[4][4];
+ float xmax;
+ float xmin;
+ float ymax;
+ float ymin;
+
+ if(aspect > 1.0f) {
+ xmax = 0.5f * cam->ortho_scale;
+ ymax = xmax / aspect;
+ } else {
+ ymax = 0.5f * cam->ortho_scale;
+ xmax = ymax * aspect;
+ }
+ xmin = -xmax;
+ ymin = -ymax;
+
+ orthographic_m4( orthomat,xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend);
+ mul_m4_m4m4(tmpmat, projectors[i].projmat, orthomat);
+ }
+ } else {
+ copy_m4_m4(tmpmat, projectors[i].projmat);
+ }
+
+ unit_m4(offsetmat);
+ mul_mat3_m4_fl(offsetmat, 0.5);
+ offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5;
+
+ if (cam) {
+ if (aspx == aspy) {
+ offsetmat[3][0] -= cam->shiftx;
+ offsetmat[3][1] -= cam->shifty;
+ } else if (aspx < aspy) {
+ offsetmat[3][0] -=(cam->shiftx * aspy/aspx);
+ offsetmat[3][1] -= cam->shifty;
+ } else {
+ offsetmat[3][0] -= cam->shiftx;
+ offsetmat[3][1] -=(cam->shifty * aspx/aspy);
+ }
+ }
+
+ mul_m4_m4m4(projectors[i].projmat, tmpmat, offsetmat);
+
+ /* calculate worldspace projector normal (for best projector test) */
+ projectors[i].normal[0] = 0;
+ projectors[i].normal[1] = 0;
+ projectors[i].normal[2] = 1;
+ mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal);
+ }
+
+ /* make sure we are not modifying the original UV layer */
+ tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
+ CD_MTFACE, uvname);
+
+
+ numVerts = dm->getNumVerts(dm);
+
+ coords = MEM_callocN(sizeof(*coords) * numVerts,
+ "uvprojectModifier_do coords");
+ dm->getVertCos(dm, coords);
+
+ /* convert coords to world space */
+ for(i = 0, co = coords; i < numVerts; ++i, ++co)
+ mul_m4_v3(ob->obmat, *co);
+
+ /* if only one projector, project coords to UVs */
+ if(num_projectors == 1 && projectors[0].uci==NULL)
+ for(i = 0, co = coords; i < numVerts; ++i, ++co)
+ mul_project_m4_v4(projectors[0].projmat, *co);
+
+ mface = dm->getFaceArray(dm);
+ numFaces = dm->getNumFaces(dm);
+
+ /* apply coords as UVs, and apply image if tfaces are new */
+ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) {
+ if(override_image || !image || tface->tpage == image) {
+ if(num_projectors == 1) {
+ if(projectors[0].uci) {
+ project_from_camera(tface->uv[0], coords[mf->v1], projectors[0].uci);
+ project_from_camera(tface->uv[1], coords[mf->v2], projectors[0].uci);
+ project_from_camera(tface->uv[2], coords[mf->v3], projectors[0].uci);
+ if(mf->v3)
+ project_from_camera(tface->uv[3], coords[mf->v4], projectors[0].uci);
+
+ if(scax != 1.0f) {
+ tface->uv[0][0] = ((tface->uv[0][0] - 0.5f) * scax) + 0.5f;
+ tface->uv[1][0] = ((tface->uv[1][0] - 0.5f) * scax) + 0.5f;
+ tface->uv[2][0] = ((tface->uv[2][0] - 0.5f) * scax) + 0.5f;
+ if(mf->v3)
+ tface->uv[3][0] = ((tface->uv[3][0] - 0.5f) * scax) + 0.5f;
+ }
+
+ if(scay != 1.0f) {
+ tface->uv[0][1] = ((tface->uv[0][1] - 0.5f) * scay) + 0.5f;
+ tface->uv[1][1] = ((tface->uv[1][1] - 0.5f) * scay) + 0.5f;
+ tface->uv[2][1] = ((tface->uv[2][1] - 0.5f) * scay) + 0.5f;
+ if(mf->v3)
+ tface->uv[3][1] = ((tface->uv[3][1] - 0.5f) * scay) + 0.5f;
+ }
+ }
+ else {
+ /* apply transformed coords as UVs */
+ tface->uv[0][0] = coords[mf->v1][0];
+ tface->uv[0][1] = coords[mf->v1][1];
+ tface->uv[1][0] = coords[mf->v2][0];
+ tface->uv[1][1] = coords[mf->v2][1];
+ tface->uv[2][0] = coords[mf->v3][0];
+ tface->uv[2][1] = coords[mf->v3][1];
+ if(mf->v4) {
+ tface->uv[3][0] = coords[mf->v4][0];
+ tface->uv[3][1] = coords[mf->v4][1];
+ }
+ }
+ } else {
+ /* multiple projectors, select the closest to face normal
+ * direction
+ */
+ float co1[3], co2[3], co3[3], co4[3];
+ float face_no[3];
+ int j;
+ Projector *best_projector;
+ float best_dot;
+
+ VECCOPY(co1, coords[mf->v1]);
+ VECCOPY(co2, coords[mf->v2]);
+ VECCOPY(co3, coords[mf->v3]);
+
+ /* get the untransformed face normal */
+ if(mf->v4) {
+ VECCOPY(co4, coords[mf->v4]);
+ normal_quad_v3( face_no,co1, co2, co3, co4);
+ } else {
+ normal_tri_v3( face_no,co1, co2, co3);
+ }
+
+ /* find the projector which the face points at most directly
+ * (projector normal with largest dot product is best)
+ */
+ best_dot = dot_v3v3(projectors[0].normal, face_no);
+ best_projector = &projectors[0];
+
+ for(j = 1; j < num_projectors; ++j) {
+ float tmp_dot = dot_v3v3(projectors[j].normal,
+ face_no);
+ if(tmp_dot > best_dot) {
+ best_dot = tmp_dot;
+ best_projector = &projectors[j];
+ }
+ }
+
+ if(best_projector->uci) {
+ project_from_camera(tface->uv[0], coords[mf->v1], best_projector->uci);
+ project_from_camera(tface->uv[1], coords[mf->v2], best_projector->uci);
+ project_from_camera(tface->uv[2], coords[mf->v3], best_projector->uci);
+ if(mf->v3)
+ project_from_camera(tface->uv[3], coords[mf->v4], best_projector->uci);
+ }
+ else {
+ mul_project_m4_v4(best_projector->projmat, co1);
+ mul_project_m4_v4(best_projector->projmat, co2);
+ mul_project_m4_v4(best_projector->projmat, co3);
+ if(mf->v4)
+ mul_project_m4_v4(best_projector->projmat, co4);
+
+ /* apply transformed coords as UVs */
+ tface->uv[0][0] = co1[0];
+ tface->uv[0][1] = co1[1];
+ tface->uv[1][0] = co2[0];
+ tface->uv[1][1] = co2[1];
+ tface->uv[2][0] = co3[0];
+ tface->uv[2][1] = co3[1];
+ if(mf->v4) {
+ tface->uv[3][0] = co4[0];
+ tface->uv[3][1] = co4[1];
+ }
+ }
+ }
+ }
+
+ if(override_image) {
+ tface->mode = TF_TEX;
+ tface->tpage = image;
+ }
+ }
+
+ MEM_freeN(coords);
+
+ if(free_uci) {
+ int j;
+ for(j = 0; j < num_projectors; ++j) {
+ if(projectors[j].uci) {
+ MEM_freeN(projectors[j].uci);
+ }
+ }
+ }
+ return dm;
+}
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+
+ result = uvprojectModifier_do(umd, ob, derivedData);
+
+ return result;
+}
+
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+
+ModifierTypeInfo modifierType_UVProject = {
+ /* name */ "UVProject",
+ /* structName */ "UVProjectModifierData",
+ /* structSize */ sizeof(UVProjectModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ foreachIDLink,
+};
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
new file mode 100644
index 00000000000..968a2a66692
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -0,0 +1,497 @@
+/*
+* $Id:
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+#include "stddef.h"
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_uvproject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_fluidsim.h"
+
+
+#include "BKE_action.h"
+#include "BKE_bmesh.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_smoke.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "CCGSubSurf.h"
+
+#include "RE_shader_ext.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+static void initData(ModifierData *md)
+{
+ WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
+
+ wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
+ | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
+
+ wmd->objectcenter = NULL;
+ wmd->texture = NULL;
+ wmd->map_object = NULL;
+ wmd->height= 0.5f;
+ wmd->width= 1.5f;
+ wmd->speed= 0.25f;
+ wmd->narrow= 1.5f;
+ wmd->lifetime= 0.0f;
+ wmd->damp= 10.0f;
+ wmd->falloff= 0.0f;
+ wmd->texmapping = MOD_WAV_MAP_LOCAL;
+ wmd->defgrp_name[0] = 0;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ WaveModifierData *wmd = (WaveModifierData*) md;
+ WaveModifierData *twmd = (WaveModifierData*) target;
+
+ twmd->damp = wmd->damp;
+ twmd->flag = wmd->flag;
+ twmd->height = wmd->height;
+ twmd->lifetime = wmd->lifetime;
+ twmd->narrow = wmd->narrow;
+ twmd->speed = wmd->speed;
+ twmd->startx = wmd->startx;
+ twmd->starty = wmd->starty;
+ twmd->timeoffs = wmd->timeoffs;
+ twmd->width = wmd->width;
+ twmd->falloff = wmd->falloff;
+ twmd->objectcenter = wmd->objectcenter;
+ twmd->texture = wmd->texture;
+ twmd->map_object = wmd->map_object;
+ twmd->texmapping = wmd->texmapping;
+ strncpy(twmd->defgrp_name, wmd->defgrp_name, 32);
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ WaveModifierData *wmd = (WaveModifierData*) md;
+
+ walk(userData, ob, &wmd->objectcenter);
+ walk(userData, ob, &wmd->map_object);
+}
+
+static void foreachIDLink(ModifierData *md, Object *ob,
+ IDWalkFunc walk, void *userData)
+{
+ WaveModifierData *wmd = (WaveModifierData*) md;
+
+ walk(userData, ob, (ID **)&wmd->texture);
+
+ foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
+}
+
+static void updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
+ DagNode *obNode)
+{
+ WaveModifierData *wmd = (WaveModifierData*) md;
+
+ if(wmd->objectcenter) {
+ DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
+
+ dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
+ "Wave Modifier");
+ }
+
+ if(wmd->map_object) {
+ DagNode *curNode = dag_get_node(forest, wmd->map_object);
+
+ dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
+ "Wave Modifer");
+ }
+}
+
+static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
+{
+ WaveModifierData *wmd = (WaveModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+
+ /* ask for UV coordinates if we need them */
+ if(wmd->texture && wmd->texmapping == MOD_WAV_MAP_UV)
+ dataMask |= (1 << CD_MTFACE);
+
+ /* ask for vertexgroups if we need them */
+ if(wmd->defgrp_name[0])
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
+ DerivedMesh *dm,
+ float (*co)[3], float (*texco)[3],
+ int numVerts)
+{
+ int i;
+ int texmapping = wmd->texmapping;
+
+ if(texmapping == MOD_WAV_MAP_OBJECT) {
+ if(wmd->map_object)
+ invert_m4_m4(wmd->map_object->imat, wmd->map_object->obmat);
+ else /* if there is no map object, default to local */
+ texmapping = MOD_WAV_MAP_LOCAL;
+ }
+
+ /* UVs need special handling, since they come from faces */
+ if(texmapping == MOD_WAV_MAP_UV) {
+ if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
+ MFace *mface = dm->getFaceArray(dm);
+ MFace *mf;
+ char *done = MEM_callocN(sizeof(*done) * numVerts,
+ "get_texture_coords done");
+ int numFaces = dm->getNumFaces(dm);
+ char uvname[32];
+ MTFace *tf;
+
+ validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name, uvname);
+ tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
+
+ /* verts are given the UV from the first face that uses them */
+ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
+ if(!done[mf->v1]) {
+ texco[mf->v1][0] = tf->uv[0][0];
+ texco[mf->v1][1] = tf->uv[0][1];
+ texco[mf->v1][2] = 0;
+ done[mf->v1] = 1;
+ }
+ if(!done[mf->v2]) {
+ texco[mf->v2][0] = tf->uv[1][0];
+ texco[mf->v2][1] = tf->uv[1][1];
+ texco[mf->v2][2] = 0;
+ done[mf->v2] = 1;
+ }
+ if(!done[mf->v3]) {
+ texco[mf->v3][0] = tf->uv[2][0];
+ texco[mf->v3][1] = tf->uv[2][1];
+ texco[mf->v3][2] = 0;
+ done[mf->v3] = 1;
+ }
+ if(!done[mf->v4]) {
+ texco[mf->v4][0] = tf->uv[3][0];
+ texco[mf->v4][1] = tf->uv[3][1];
+ texco[mf->v4][2] = 0;
+ done[mf->v4] = 1;
+ }
+ }
+
+ /* remap UVs from [0, 1] to [-1, 1] */
+ for(i = 0; i < numVerts; ++i) {
+ texco[i][0] = texco[i][0] * 2 - 1;
+ texco[i][1] = texco[i][1] * 2 - 1;
+ }
+
+ MEM_freeN(done);
+ return;
+ } else /* if there are no UVs, default to local */
+ texmapping = MOD_WAV_MAP_LOCAL;
+ }
+
+ for(i = 0; i < numVerts; ++i, ++co, ++texco) {
+ switch(texmapping) {
+ case MOD_WAV_MAP_LOCAL:
+ VECCOPY(*texco, *co);
+ break;
+ case MOD_WAV_MAP_GLOBAL:
+ VECCOPY(*texco, *co);
+ mul_m4_v3(ob->obmat, *texco);
+ break;
+ case MOD_WAV_MAP_OBJECT:
+ VECCOPY(*texco, *co);
+ mul_m4_v3(ob->obmat, *texco);
+ mul_m4_v3(wmd->map_object->imat, *texco);
+ break;
+ }
+ }
+}
+
+static void waveModifier_do(WaveModifierData *md,
+ Scene *scene, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ WaveModifierData *wmd = (WaveModifierData*) md;
+ MVert *mvert = NULL;
+ MDeformVert *dvert = NULL;
+ int defgrp_index;
+ float ctime = bsystem_time(scene, ob, (float)scene->r.cfra, 0.0);
+ float minfac =
+ (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
+ float lifefac = wmd->height;
+ float (*tex_co)[3] = NULL;
+
+ if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH)
+ mvert = dm->getVertArray(dm);
+
+ if(wmd->objectcenter){
+ float mat[4][4];
+ /* get the control object's location in local coordinates */
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_m4m4(mat, wmd->objectcenter->obmat, ob->imat);
+
+ wmd->startx = mat[3][0];
+ wmd->starty = mat[3][1];
+ }
+
+ /* get the index of the deform group */
+ defgrp_index = defgroup_name_index(ob, wmd->defgrp_name);
+
+ if(defgrp_index >= 0){
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+ }
+
+ if(wmd->damp == 0) wmd->damp = 10.0f;
+
+ if(wmd->lifetime != 0.0) {
+ float x = ctime - wmd->timeoffs;
+
+ if(x > wmd->lifetime) {
+ lifefac = x - wmd->lifetime;
+
+ if(lifefac > wmd->damp) lifefac = 0.0;
+ else lifefac =
+ (float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp)));
+ }
+ }
+
+ if(wmd->texture) {
+ tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
+ "waveModifier_do tex_co");
+ wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts);
+ }
+
+ if(lifefac != 0.0) {
+ int i;
+
+ for(i = 0; i < numVerts; i++) {
+ float *co = vertexCos[i];
+ float x = co[0] - wmd->startx;
+ float y = co[1] - wmd->starty;
+ float amplit= 0.0f;
+ float dist = 0.0f;
+ float falloff_fac = 0.0f;
+ TexResult texres;
+ MDeformWeight *def_weight = NULL;
+
+ /* get weights */
+ if(dvert) {
+ int j;
+ for(j = 0; j < dvert[i].totweight; ++j) {
+ if(dvert[i].dw[j].def_nr == defgrp_index) {
+ def_weight = &dvert[i].dw[j];
+ break;
+ }
+ }
+
+ /* if this vert isn't in the vgroup, don't deform it */
+ if(!def_weight) continue;
+ }
+
+ if(wmd->texture) {
+ texres.nor = NULL;
+ get_texture_value(wmd->texture, tex_co[i], &texres);
+ }
+
+ /*get dist*/
+ if(wmd->flag & MOD_WAVE_X) {
+ if(wmd->flag & MOD_WAVE_Y){
+ dist = (float)sqrt(x*x + y*y);
+ }
+ else{
+ dist = fabs(x);
+ }
+ }
+ else if(wmd->flag & MOD_WAVE_Y) {
+ dist = fabs(y);
+ }
+
+ falloff_fac = (1.0-(dist / wmd->falloff));
+ CLAMP(falloff_fac,0,1);
+
+ if(wmd->flag & MOD_WAVE_X) {
+ if(wmd->flag & MOD_WAVE_Y) amplit = (float)sqrt(x*x + y*y);
+ else amplit = x;
+ }
+ else if(wmd->flag & MOD_WAVE_Y)
+ amplit= y;
+
+ /* this way it makes nice circles */
+ amplit -= (ctime - wmd->timeoffs) * wmd->speed;
+
+ if(wmd->flag & MOD_WAVE_CYCL) {
+ amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width)
+ + wmd->width;
+ }
+
+ /* GAUSSIAN */
+ if(amplit > -wmd->width && amplit < wmd->width) {
+ amplit = amplit * wmd->narrow;
+ amplit = (float)(1.0 / exp(amplit * amplit) - minfac);
+
+ /*apply texture*/
+ if(wmd->texture)
+ amplit = amplit * texres.tin;
+
+ /*apply weight*/
+ if(def_weight)
+ amplit = amplit * def_weight->weight;
+
+ /*apply falloff*/
+ if (wmd->falloff > 0)
+ amplit = amplit * falloff_fac;
+
+ if(mvert) {
+ /* move along normals */
+ if(wmd->flag & MOD_WAVE_NORM_X) {
+ co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
+ }
+ if(wmd->flag & MOD_WAVE_NORM_Y) {
+ co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
+ }
+ if(wmd->flag & MOD_WAVE_NORM_Z) {
+ co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
+ }
+ }
+ else {
+ /* move along local z axis */
+ co[2] += lifefac * amplit;
+ }
+ }
+ }
+ }
+
+ if(wmd->texture) MEM_freeN(tex_co);
+}
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm= derivedData;
+ WaveModifierData *wmd = (WaveModifierData *)md;
+
+ if(wmd->flag & MOD_WAVE_NORM)
+ dm= get_cddm(md->scene, ob, NULL, dm, vertexCos);
+ else if(wmd->texture || wmd->defgrp_name[0])
+ dm= get_dm(md->scene, ob, NULL, dm, NULL, 0);
+
+ waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm= derivedData;
+ WaveModifierData *wmd = (WaveModifierData *)md;
+
+ if(wmd->flag & MOD_WAVE_NORM)
+ dm= get_cddm(md->scene, ob, editData, dm, vertexCos);
+ else if(wmd->texture || wmd->defgrp_name[0])
+ dm= get_dm(md->scene, ob, editData, dm, NULL, 0);
+
+ waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
+
+ if(dm != derivedData)
+ dm->release(dm);
+}
+
+
+ModifierTypeInfo modifierType_Wave = {
+ /* name */ "Wave",
+ /* structName */ "WaveModifierData",
+ /* structSize */ sizeof(WaveModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode,
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ 0,
+ /* applyModifierEM */ 0,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ foreachIDLink,
+};