This fixes most of the UV distortion issues with subsurf. Near seams however there might still be some distortion, but this should at least not be worse than before. Subsurf UV is enabled by default on new meshes, and can be enabled in the modifier panel for existing ones. Before and after: http://users.pandora.be/blendix/notsmooth.png http://users.pandora.be/blendix/smooth.png
		
			
				
	
	
		
			1614 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1614 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "string.h"
 | 
						|
#include "stdarg.h"
 | 
						|
#include "math.h"
 | 
						|
 | 
						|
#include "BLI_blenlib.h"
 | 
						|
#include "BLI_rand.h"
 | 
						|
#include "BLI_arithb.h"
 | 
						|
 | 
						|
#include "MEM_guardedalloc.h"
 | 
						|
 | 
						|
#include "DNA_armature_types.h"
 | 
						|
#include "DNA_effect_types.h"
 | 
						|
#include "DNA_mesh_types.h"
 | 
						|
#include "DNA_meshdata_types.h"
 | 
						|
#include "DNA_modifier_types.h"
 | 
						|
#include "DNA_object_types.h"
 | 
						|
#include "DNA_object_force.h"
 | 
						|
#include "DNA_scene_types.h"
 | 
						|
 | 
						|
#include "BLI_editVert.h"
 | 
						|
 | 
						|
#include "BKE_bad_level_calls.h"
 | 
						|
#include "BKE_global.h"
 | 
						|
#include "BKE_utildefines.h"
 | 
						|
#include "BKE_DerivedMesh.h"
 | 
						|
#include "BKE_booleanops.h"
 | 
						|
#include "BKE_displist.h"
 | 
						|
#include "BKE_modifier.h"
 | 
						|
#include "BKE_lattice.h"
 | 
						|
#include "BKE_subsurf.h"
 | 
						|
#include "BKE_object.h"
 | 
						|
#include "BKE_mesh.h"
 | 
						|
#include "BKE_softbody.h"
 | 
						|
#include "depsgraph_private.h"
 | 
						|
 | 
						|
#include "LOD_DependKludge.h"
 | 
						|
#include "LOD_decimation.h"
 | 
						|
 | 
						|
#include "CCGSubSurf.h"
 | 
						|
 | 
						|
/***/
 | 
						|
 | 
						|
static int noneModifier_isDisabled(ModifierData *md)
 | 
						|
{
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
/* Curve */
 | 
						|
 | 
						|
static void curveModifier_copyData(ModifierData *md, ModifierData *target)
 | 
						|
{
 | 
						|
	CurveModifierData *cmd = (CurveModifierData*) md;
 | 
						|
	CurveModifierData *tcmd = (CurveModifierData*) target;
 | 
						|
 | 
						|
	tcmd->object = cmd->object;
 | 
						|
}
 | 
						|
 | 
						|
static int curveModifier_isDisabled(ModifierData *md)
 | 
						|
{
 | 
						|
	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, 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);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void curveModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	CurveModifierData *cmd = (CurveModifierData*) md;
 | 
						|
 | 
						|
	curve_deform_verts(cmd->object, ob, vertexCos, numVerts, cmd->name);
 | 
						|
}
 | 
						|
 | 
						|
static void curveModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	curveModifier_deformVerts(md, ob, NULL, vertexCos, numVerts);
 | 
						|
}
 | 
						|
 | 
						|
/* Lattice */
 | 
						|
 | 
						|
static void latticeModifier_copyData(ModifierData *md, ModifierData *target)
 | 
						|
{
 | 
						|
	LatticeModifierData *lmd = (LatticeModifierData*) md;
 | 
						|
	LatticeModifierData *tlmd = (LatticeModifierData*) target;
 | 
						|
 | 
						|
	tlmd->object = lmd->object;
 | 
						|
}
 | 
						|
 | 
						|
static int latticeModifier_isDisabled(ModifierData *md)
 | 
						|
{
 | 
						|
	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, 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);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void latticeModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	LatticeModifierData *lmd = (LatticeModifierData*) md;
 | 
						|
 | 
						|
	lattice_deform_verts(lmd->object, ob, vertexCos, numVerts, lmd->name);
 | 
						|
}
 | 
						|
 | 
						|
static void latticeModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	latticeModifier_deformVerts(md, ob, NULL, vertexCos, numVerts);
 | 
						|
}
 | 
						|
 | 
						|
/* 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 void *subsurfModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
 | 
						|
{
 | 
						|
	DerivedMesh *dm = derivedData;
 | 
						|
	SubsurfModifierData *smd = (SubsurfModifierData*) md;
 | 
						|
	Mesh *me = ob->data;
 | 
						|
 | 
						|
	if (dm) {
 | 
						|
		DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
 | 
						|
		int i;
 | 
						|
 | 
						|
		if (vertexCos) {
 | 
						|
			int numVerts = dm->getNumVerts(dm);
 | 
						|
 | 
						|
			for (i=0; i<numVerts; i++) {
 | 
						|
				VECCOPY(dlm->mvert[i].co, vertexCos[i]);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		dm = subsurf_make_derived_from_mesh(me, dlm, smd, useRenderParams, NULL, isFinalCalc);
 | 
						|
 | 
						|
		return dm;
 | 
						|
	} else {
 | 
						|
		return subsurf_make_derived_from_mesh(me, NULL, smd, useRenderParams, vertexCos, isFinalCalc);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void *subsurfModifier_applyModifierEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3])
 | 
						|
{
 | 
						|
	EditMesh *em = editData;
 | 
						|
	DerivedMesh *dm = derivedData;
 | 
						|
	SubsurfModifierData *smd = (SubsurfModifierData*) md;
 | 
						|
 | 
						|
	if (dm) {
 | 
						|
		DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
 | 
						|
 | 
						|
		dm = subsurf_make_derived_from_dlm_em(dlm, smd, vertexCos);
 | 
						|
 | 
						|
		return dm;
 | 
						|
	} else {
 | 
						|
		return subsurf_make_derived_from_editmesh(em, smd, vertexCos);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* 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 void *buildModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
 | 
						|
{
 | 
						|
	DerivedMesh *dm = derivedData;
 | 
						|
	BuildModifierData *bmd = (BuildModifierData*) md;
 | 
						|
	DispListMesh *dlm=NULL, *ndlm = MEM_callocN(sizeof(*ndlm), "build_dlm");
 | 
						|
	MVert *mvert;
 | 
						|
	MEdge *medge;
 | 
						|
	MFace *mface;
 | 
						|
	MCol *mcol;
 | 
						|
	TFace *tface;
 | 
						|
	int totvert, totedge, totface;
 | 
						|
	int i,j;
 | 
						|
	float frac;
 | 
						|
 | 
						|
	if (dm) {
 | 
						|
		dlm = dm->convertToDispListMesh(dm, 1);
 | 
						|
		mvert = dlm->mvert;
 | 
						|
		medge = dlm->medge;
 | 
						|
		mface = dlm->mface;
 | 
						|
		mcol = dlm->mcol;
 | 
						|
		tface = dlm->tface;
 | 
						|
		totvert = dlm->totvert;
 | 
						|
		totedge = dlm->totedge;
 | 
						|
		totface = dlm->totface;
 | 
						|
	} else {
 | 
						|
		Mesh *me = ob->data;
 | 
						|
		mvert = me->mvert;
 | 
						|
		medge = me->medge;
 | 
						|
		mface = me->mface;
 | 
						|
		mcol = me->mcol;
 | 
						|
		tface = me->tface;
 | 
						|
		totvert = me->totvert;
 | 
						|
		totedge = me->totedge;
 | 
						|
		totface = me->totface;
 | 
						|
	}
 | 
						|
 | 
						|
	if (ob) {
 | 
						|
		frac = bsystem_time(ob, 0, (float)G.scene->r.cfra, bmd->start-1.0f)/bmd->length;
 | 
						|
	} else {
 | 
						|
		frac = G.scene->r.cfra - bmd->start/bmd->length;
 | 
						|
	}
 | 
						|
	CLAMP(frac, 0.0, 1.0);
 | 
						|
 | 
						|
	ndlm->totface = totface*frac;
 | 
						|
	ndlm->totedge = totedge*frac;
 | 
						|
	if (ndlm->totface) {
 | 
						|
		ndlm->mvert = MEM_mallocN(sizeof(*ndlm->mvert)*totvert, "build_mvert");
 | 
						|
		memcpy(ndlm->mvert, mvert, sizeof(*mvert)*totvert);
 | 
						|
		for (i=0; i<totvert; i++) {
 | 
						|
			if (vertexCos)
 | 
						|
				VECCOPY(ndlm->mvert[i].co, vertexCos[i]);
 | 
						|
			ndlm->mvert[i].flag = 0;
 | 
						|
		}
 | 
						|
 | 
						|
		if (bmd->randomize) {
 | 
						|
			ndlm->mface = MEM_dupallocN(mface);
 | 
						|
			BLI_array_randomize(ndlm->mface, sizeof(*mface), totface, bmd->seed);
 | 
						|
 | 
						|
			if (tface) {
 | 
						|
				ndlm->tface = MEM_dupallocN(tface);
 | 
						|
				BLI_array_randomize(ndlm->tface, sizeof(*tface), totface, bmd->seed);
 | 
						|
			} else if (mcol) {
 | 
						|
				ndlm->mcol = MEM_dupallocN(mcol);
 | 
						|
				BLI_array_randomize(ndlm->mcol, sizeof(*mcol)*4, totface, bmd->seed);
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			ndlm->mface = MEM_mallocN(sizeof(*ndlm->mface)*ndlm->totface, "build_mf");
 | 
						|
			memcpy(ndlm->mface, mface, sizeof(*mface)*ndlm->totface);
 | 
						|
 | 
						|
			if (tface) {
 | 
						|
				ndlm->tface = MEM_mallocN(sizeof(*ndlm->tface)*ndlm->totface, "build_tf");
 | 
						|
				memcpy(ndlm->tface, tface, sizeof(*tface)*ndlm->totface);
 | 
						|
			} else if (mcol) {
 | 
						|
				ndlm->mcol = MEM_mallocN(sizeof(*ndlm->mcol)*4*ndlm->totface, "build_mcol");
 | 
						|
				memcpy(ndlm->mcol, mcol, sizeof(*mcol)*4*ndlm->totface);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		for (i=0; i<ndlm->totface; i++) {
 | 
						|
			MFace *mf = &ndlm->mface[i];
 | 
						|
 | 
						|
			ndlm->mvert[mf->v1].flag = 1;
 | 
						|
			ndlm->mvert[mf->v2].flag = 1;
 | 
						|
			ndlm->mvert[mf->v3].flag = 1;
 | 
						|
			if (mf->v4) ndlm->mvert[mf->v4].flag = 1;
 | 
						|
		}
 | 
						|
 | 
						|
			/* Store remapped indices in *((int*) mv->no) */
 | 
						|
		ndlm->totvert = 0;
 | 
						|
		for (i=0; i<totvert; i++) {
 | 
						|
			MVert *mv = &ndlm->mvert[i];
 | 
						|
 | 
						|
			if (mv->flag) 
 | 
						|
				*((int*) mv->no) = ndlm->totvert++;
 | 
						|
		}
 | 
						|
 | 
						|
			/* Remap face vertex indices */
 | 
						|
		for (i=0; i<ndlm->totface; i++) {
 | 
						|
			MFace *mf = &ndlm->mface[i];
 | 
						|
 | 
						|
			mf->v1 = *((int*) ndlm->mvert[mf->v1].no);
 | 
						|
			mf->v2 = *((int*) ndlm->mvert[mf->v2].no);
 | 
						|
			mf->v3 = *((int*) ndlm->mvert[mf->v3].no);
 | 
						|
			if (mf->v4) mf->v4 = *((int*) ndlm->mvert[mf->v4].no);
 | 
						|
		}
 | 
						|
			/* Copy in all edges that have both vertices (remap in process) */
 | 
						|
		if (totedge) {
 | 
						|
			ndlm->totedge = 0;
 | 
						|
			ndlm->medge = MEM_mallocN(sizeof(*ndlm->medge)*totedge, "build_med");
 | 
						|
 | 
						|
			for (i=0; i<totedge; i++) {
 | 
						|
				MEdge *med = &medge[i];
 | 
						|
 | 
						|
				if (ndlm->mvert[med->v1].flag && ndlm->mvert[med->v2].flag) {
 | 
						|
					MEdge *nmed = &ndlm->medge[ndlm->totedge++];
 | 
						|
 | 
						|
					memcpy(nmed, med, sizeof(*med));
 | 
						|
 | 
						|
					nmed->v1 = *((int*) ndlm->mvert[nmed->v1].no);
 | 
						|
					nmed->v2 = *((int*) ndlm->mvert[nmed->v2].no);
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
			/* Collapse vertex array to remove unused verts */
 | 
						|
		for(i=j=0; i<totvert; i++) {
 | 
						|
			MVert *mv = &ndlm->mvert[i];
 | 
						|
 | 
						|
			if (mv->flag) {
 | 
						|
				if (j!=i) 
 | 
						|
					memcpy(&ndlm->mvert[j], mv, sizeof(*mv));
 | 
						|
				j++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	} else if (ndlm->totedge) {
 | 
						|
		ndlm->mvert = MEM_mallocN(sizeof(*ndlm->mvert)*totvert, "build_mvert");
 | 
						|
		memcpy(ndlm->mvert, mvert, sizeof(*mvert)*totvert);
 | 
						|
		for (i=0; i<totvert; i++) {
 | 
						|
			if (vertexCos)
 | 
						|
				VECCOPY(ndlm->mvert[i].co, vertexCos[i]);
 | 
						|
			ndlm->mvert[i].flag = 0;
 | 
						|
		}
 | 
						|
 | 
						|
		if (bmd->randomize) {
 | 
						|
			ndlm->medge = MEM_dupallocN(medge);
 | 
						|
			BLI_array_randomize(ndlm->medge, sizeof(*medge), totedge, bmd->seed);
 | 
						|
		} else {
 | 
						|
			ndlm->medge = MEM_mallocN(sizeof(*ndlm->medge)*ndlm->totedge, "build_mf");
 | 
						|
			memcpy(ndlm->medge, medge, sizeof(*medge)*ndlm->totedge);
 | 
						|
		}
 | 
						|
 | 
						|
		for (i=0; i<ndlm->totedge; i++) {
 | 
						|
			MEdge *med = &ndlm->medge[i];
 | 
						|
 | 
						|
			ndlm->mvert[med->v1].flag = 1;
 | 
						|
			ndlm->mvert[med->v2].flag = 1;
 | 
						|
		}
 | 
						|
 | 
						|
			/* Store remapped indices in *((int*) mv->no) */
 | 
						|
		ndlm->totvert = 0;
 | 
						|
		for (i=0; i<totvert; i++) {
 | 
						|
			MVert *mv = &ndlm->mvert[i];
 | 
						|
 | 
						|
			if (mv->flag) 
 | 
						|
				*((int*) mv->no) = ndlm->totvert++;
 | 
						|
		}
 | 
						|
 | 
						|
			/* Remap edge vertex indices */
 | 
						|
		for (i=0; i<ndlm->totedge; i++) {
 | 
						|
			MEdge *med = &ndlm->medge[i];
 | 
						|
 | 
						|
			med->v1 = *((int*) ndlm->mvert[med->v1].no);
 | 
						|
			med->v2 = *((int*) ndlm->mvert[med->v2].no);
 | 
						|
		}
 | 
						|
 | 
						|
			/* Collapse vertex array to remove unused verts */
 | 
						|
		for(i=j=0; i<totvert; i++) {
 | 
						|
			MVert *mv = &ndlm->mvert[i];
 | 
						|
 | 
						|
			if (mv->flag) {
 | 
						|
				if (j!=i) 
 | 
						|
					memcpy(&ndlm->mvert[j], mv, sizeof(*mv));
 | 
						|
				j++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		ndlm->totvert = totvert*frac;
 | 
						|
 | 
						|
		if (bmd->randomize) {
 | 
						|
			ndlm->mvert = MEM_dupallocN(mvert);
 | 
						|
			BLI_array_randomize(ndlm->mvert, sizeof(*mvert), totvert, bmd->seed);
 | 
						|
		} else {
 | 
						|
			ndlm->mvert = MEM_mallocN(sizeof(*ndlm->mvert)*ndlm->totvert, "build_mvert");
 | 
						|
			memcpy(ndlm->mvert, mvert, sizeof(*mvert)*ndlm->totvert);
 | 
						|
		}
 | 
						|
 | 
						|
		if (vertexCos) {
 | 
						|
			for (i=0; i<ndlm->totvert; i++) {
 | 
						|
				VECCOPY(ndlm->mvert[i].co, vertexCos[i]);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (dlm) displistmesh_free(dlm);
 | 
						|
 | 
						|
	mesh_calc_normals(ndlm->mvert, ndlm->totvert, ndlm->mface, ndlm->totface, &ndlm->nors);
 | 
						|
	
 | 
						|
	return derivedmesh_from_displistmesh(ndlm, NULL);
 | 
						|
}
 | 
						|
 | 
						|
/* Mirror */
 | 
						|
 | 
						|
static void mirrorModifier_initData(ModifierData *md)
 | 
						|
{
 | 
						|
	MirrorModifierData *mmd = (MirrorModifierData*) md;
 | 
						|
 | 
						|
	mmd->tolerance = 0.001;
 | 
						|
}
 | 
						|
 | 
						|
static void mirrorModifier_copyData(ModifierData *md, ModifierData *target)
 | 
						|
{
 | 
						|
	MirrorModifierData *mmd = (MirrorModifierData*) md;
 | 
						|
	MirrorModifierData *tmmd = (MirrorModifierData*) target;
 | 
						|
 | 
						|
	tmmd->axis = mmd->axis;
 | 
						|
	tmmd->tolerance = mmd->tolerance;
 | 
						|
}
 | 
						|
 | 
						|
static DispListMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, DispListMesh *inDLM, float (*vertexCos)[3], int initFlags)
 | 
						|
{
 | 
						|
	int i, axis = mmd->axis;
 | 
						|
	float tolerance = mmd->tolerance;
 | 
						|
	DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "mirror_dlm");
 | 
						|
	int (*indexMap)[2];
 | 
						|
 | 
						|
	dlm->totvert = dlm->totedge = dlm->totface = 0;
 | 
						|
	indexMap = MEM_mallocN(sizeof(*indexMap)*inDLM->totvert, "indexmap");
 | 
						|
	dlm->mvert = MEM_callocN(sizeof(*dlm->mvert)*inDLM->totvert*2, "dlm_mvert");
 | 
						|
	dlm->mface = MEM_callocN(sizeof(*dlm->mface)*inDLM->totface*2, "dlm_mface");
 | 
						|
 | 
						|
	if (inDLM->medge) dlm->medge = MEM_callocN(sizeof(*dlm->medge)*inDLM->totedge*2, "dlm_medge");
 | 
						|
	if (inDLM->tface) dlm->tface = MEM_callocN(sizeof(*dlm->tface)*inDLM->totface*2, "dlm_tface");
 | 
						|
	if (inDLM->mcol) dlm->mcol = MEM_callocN(sizeof(*dlm->mcol)*inDLM->totface*4*2, "dlm_mcol");
 | 
						|
 | 
						|
	for (i=0; i<inDLM->totvert; i++) {
 | 
						|
		MVert *inMV = &inDLM->mvert[i];
 | 
						|
		MVert *mv = &dlm->mvert[dlm->totvert++];
 | 
						|
		int isShared = ABS(inMV->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.
 | 
						|
				 */
 | 
						|
		*mv = *inMV;
 | 
						|
		if (vertexCos) {
 | 
						|
			VECCOPY(mv->co, vertexCos[i]);
 | 
						|
		}
 | 
						|
		if (initFlags) mv->flag |= ME_VERT_STEPINDEX;
 | 
						|
 | 
						|
		indexMap[i][0] = dlm->totvert-1;
 | 
						|
		indexMap[i][1] = !isShared;
 | 
						|
 | 
						|
		if (isShared) {
 | 
						|
			mv->co[axis] = 0;
 | 
						|
			mv->flag |= ME_VERT_MERGED;
 | 
						|
		} else {
 | 
						|
			MVert *mv2 = &dlm->mvert[dlm->totvert++];
 | 
						|
 | 
						|
			*mv2 = *mv;
 | 
						|
			mv2->co[axis] = -mv2->co[axis];
 | 
						|
			mv2->flag &= ~ME_VERT_STEPINDEX;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	for (i=0; i<inDLM->totedge; i++) {
 | 
						|
		MEdge *inMED = &inDLM->medge[i];
 | 
						|
		MEdge *med = &dlm->medge[dlm->totedge++];
 | 
						|
 | 
						|
		*med = *inMED;
 | 
						|
		med->v1 = indexMap[inMED->v1][0];
 | 
						|
		med->v2 = indexMap[inMED->v2][0];
 | 
						|
		if (initFlags) med->flag |= ME_EDGEDRAW|ME_EDGERENDER|ME_EDGE_STEPINDEX;
 | 
						|
 | 
						|
		if (indexMap[inMED->v1][1] || indexMap[inMED->v2][1]) {
 | 
						|
			MEdge *med2 = &dlm->medge[dlm->totedge++];
 | 
						|
 | 
						|
			*med2 = *med;
 | 
						|
			med2->v1 += indexMap[inMED->v1][1];
 | 
						|
			med2->v2 += indexMap[inMED->v2][1];
 | 
						|
			med2->flag &= ~ME_EDGE_STEPINDEX;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	for (i=0; i<inDLM->totface; i++) {
 | 
						|
		MFace *inMF = &inDLM->mface[i];
 | 
						|
		MFace *mf = &dlm->mface[dlm->totface++];
 | 
						|
 | 
						|
		*mf = *inMF;
 | 
						|
		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 (initFlags) mf->flag |= ME_FACE_STEPINDEX;
 | 
						|
 | 
						|
		if (inDLM->tface) {
 | 
						|
			TFace *inTF = &inDLM->tface[i];
 | 
						|
			TFace *tf = &dlm->tface[dlm->totface-1];
 | 
						|
 | 
						|
			*tf = *inTF;
 | 
						|
		} else if (inDLM->mcol) {
 | 
						|
			MCol *inMC = &inDLM->mcol[i*4];
 | 
						|
			MCol *mc = &dlm->mcol[(dlm->totface-1)*4];
 | 
						|
 | 
						|
			mc[0] = inMC[0];
 | 
						|
			mc[1] = inMC[1];
 | 
						|
			mc[2] = inMC[2];
 | 
						|
			mc[3] = inMC[3];
 | 
						|
		}
 | 
						|
		
 | 
						|
		if (indexMap[inMF->v1][1] || indexMap[inMF->v2][1] || indexMap[inMF->v3][1] || (mf->v4 && indexMap[inMF->v4][1])) {
 | 
						|
			MFace *mf2 = &dlm->mface[dlm->totface++];
 | 
						|
			TFace *tf = NULL;
 | 
						|
			MCol *mc = NULL;
 | 
						|
 | 
						|
			*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];
 | 
						|
			mf2->flag &= ~ME_FACE_STEPINDEX;
 | 
						|
 | 
						|
			if (inDLM->tface) {
 | 
						|
				TFace *inTF = &inDLM->tface[i];
 | 
						|
				tf = &dlm->tface[dlm->totface-1];
 | 
						|
 | 
						|
				*tf = *inTF;
 | 
						|
			} else if (inDLM->mcol) {
 | 
						|
				MCol *inMC = &inDLM->mcol[i*4];
 | 
						|
				mc = &dlm->mcol[(dlm->totface-1)*4];
 | 
						|
 | 
						|
				mc[0] = inMC[0];
 | 
						|
				mc[1] = inMC[1];
 | 
						|
				mc[2] = inMC[2];
 | 
						|
				mc[3] = inMC[3];
 | 
						|
			}
 | 
						|
 | 
						|
				/* Flip face normal */
 | 
						|
			SWAP(int, mf2->v1, mf2->v3);
 | 
						|
			if (tf) {
 | 
						|
				SWAP(unsigned int, tf->col[0], tf->col[2]);
 | 
						|
				SWAP(float, tf->uv[0][0], tf->uv[2][0]);
 | 
						|
				SWAP(float, tf->uv[0][1], tf->uv[2][1]);
 | 
						|
			} else if (mc) {
 | 
						|
				SWAP(MCol, mc[0], mc[2]);
 | 
						|
			}
 | 
						|
 | 
						|
			test_index_face(mf2, mc, tf, inMF->v4?4:3);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	MEM_freeN(indexMap);
 | 
						|
 | 
						|
	return dlm;
 | 
						|
}
 | 
						|
 | 
						|
static void *mirrorModifier_applyModifier__internal(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
 | 
						|
{
 | 
						|
	DerivedMesh *dm = derivedData;
 | 
						|
	MirrorModifierData *mmd = (MirrorModifierData*) md;
 | 
						|
	DispListMesh *outDLM, *inDLM;
 | 
						|
 | 
						|
	if (dm) {
 | 
						|
		inDLM = dm->convertToDispListMesh(dm, 1);
 | 
						|
	} else {
 | 
						|
		Mesh *me = ob->data;
 | 
						|
 | 
						|
		inDLM = MEM_callocN(sizeof(*inDLM), "inDLM");
 | 
						|
		inDLM->dontFreeVerts = inDLM->dontFreeOther = 1;
 | 
						|
		inDLM->mvert = me->mvert;
 | 
						|
		inDLM->medge = me->medge;
 | 
						|
		inDLM->mface = me->mface;
 | 
						|
		inDLM->tface = me->tface;
 | 
						|
		inDLM->mcol = me->mcol;
 | 
						|
		inDLM->totvert = me->totvert;
 | 
						|
		inDLM->totedge = me->totedge;
 | 
						|
		inDLM->totface = me->totface;
 | 
						|
	}
 | 
						|
 | 
						|
	outDLM = mirrorModifier__doMirror(mmd, inDLM, vertexCos, dm?0:1);
 | 
						|
 | 
						|
	displistmesh_free(inDLM);
 | 
						|
	
 | 
						|
	mesh_calc_normals(outDLM->mvert, outDLM->totvert, outDLM->mface, outDLM->totface, &outDLM->nors);
 | 
						|
	
 | 
						|
	return derivedmesh_from_displistmesh(outDLM, NULL);
 | 
						|
}
 | 
						|
 | 
						|
static void *mirrorModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
 | 
						|
{
 | 
						|
	return mirrorModifier_applyModifier__internal(md, ob, derivedData, vertexCos, 0, 1);
 | 
						|
}
 | 
						|
 | 
						|
static void *mirrorModifier_applyModifierEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3])
 | 
						|
{
 | 
						|
	if (derivedData) {
 | 
						|
		return mirrorModifier_applyModifier__internal(md, ob, derivedData, vertexCos, 0, 1);
 | 
						|
	} else {
 | 
						|
		MirrorModifierData *mmd = (MirrorModifierData*) md;
 | 
						|
		DispListMesh *outDLM, *inDLM = MEM_callocN(sizeof(*inDLM), "mm_dlm");
 | 
						|
		EditMesh *em = editData;
 | 
						|
		EditVert *eve, *preveve;
 | 
						|
		EditEdge *eed;
 | 
						|
		EditFace *efa;
 | 
						|
		int i;
 | 
						|
 | 
						|
		for (i=0,eve=em->verts.first; eve; eve= eve->next)
 | 
						|
			eve->prev = (EditVert*) i++;
 | 
						|
 | 
						|
		inDLM->totvert = BLI_countlist(&em->verts);
 | 
						|
		inDLM->totedge = BLI_countlist(&em->edges);
 | 
						|
		inDLM->totface = BLI_countlist(&em->faces);
 | 
						|
 | 
						|
		inDLM->mvert = MEM_mallocN(sizeof(*inDLM->mvert)*inDLM->totvert*2, "mm_mv");
 | 
						|
		inDLM->medge = MEM_mallocN(sizeof(*inDLM->medge)*inDLM->totedge*2, "mm_med");
 | 
						|
		inDLM->mface = MEM_mallocN(sizeof(*inDLM->mface)*inDLM->totface*2, "mm_mf");
 | 
						|
 | 
						|
			/* Need to be able to mark loose edges */
 | 
						|
		for (eed=em->edges.first; eed; eed=eed->next) {
 | 
						|
			eed->f2 = 0;
 | 
						|
		}
 | 
						|
		for (efa=em->faces.first; efa; efa=efa->next) {
 | 
						|
			efa->e1->f2 = 1;
 | 
						|
			efa->e2->f2 = 1;
 | 
						|
			efa->e3->f2 = 1;
 | 
						|
			if (efa->e4) efa->e4->f2 = 1;
 | 
						|
		}
 | 
						|
 | 
						|
		for (i=0,eve=em->verts.first; i<inDLM->totvert; i++,eve=eve->next) {
 | 
						|
			MVert *mv = &inDLM->mvert[i];
 | 
						|
 | 
						|
			VECCOPY(mv->co, eve->co);
 | 
						|
			mv->mat_nr = 0;
 | 
						|
			mv->flag = ME_VERT_STEPINDEX;
 | 
						|
		}
 | 
						|
		for (i=0,eed=em->edges.first; i<inDLM->totedge; i++,eed=eed->next) {
 | 
						|
			MEdge *med = &inDLM->medge[i];
 | 
						|
 | 
						|
			med->v1 = (int) eed->v1->prev;
 | 
						|
			med->v2 = (int) eed->v2->prev;
 | 
						|
			med->crease = (unsigned char) (eed->crease*255.0f);
 | 
						|
			med->flag = ME_EDGEDRAW|ME_EDGERENDER|ME_EDGE_STEPINDEX;
 | 
						|
			
 | 
						|
			if (eed->seam) med->flag |= ME_SEAM;
 | 
						|
			if (!eed->f2) med->flag |= ME_LOOSEEDGE;
 | 
						|
		}
 | 
						|
		for (i=0,efa=em->faces.first; i<inDLM->totface; i++,efa=efa->next) {
 | 
						|
			MFace *mf = &inDLM->mface[i];
 | 
						|
			mf->v1 = (int) efa->v1->prev;
 | 
						|
			mf->v2 = (int) efa->v2->prev;
 | 
						|
			mf->v3 = (int) efa->v3->prev;
 | 
						|
			mf->v4 = efa->v4?(int) efa->v4->prev:0;
 | 
						|
			mf->mat_nr = efa->mat_nr;
 | 
						|
			mf->flag = efa->flag|ME_FACE_STEPINDEX;
 | 
						|
			test_index_face(mf, NULL, NULL, efa->v4?4:3);
 | 
						|
		}
 | 
						|
 | 
						|
		outDLM = mirrorModifier__doMirror(mmd, inDLM, vertexCos, 0);
 | 
						|
 | 
						|
		displistmesh_free(inDLM);
 | 
						|
 | 
						|
		for (preveve=NULL, eve=em->verts.first; eve; preveve=eve, eve= eve->next)
 | 
						|
			eve->prev = preveve;
 | 
						|
 | 
						|
		mesh_calc_normals(outDLM->mvert, outDLM->totvert, outDLM->mface, outDLM->totface, &outDLM->nors);
 | 
						|
 | 
						|
		return derivedmesh_from_displistmesh(outDLM, NULL);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* 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 void *decimateModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
 | 
						|
{
 | 
						|
	DecimateModifierData *dmd = (DecimateModifierData*) md;
 | 
						|
	DerivedMesh *dm = derivedData;
 | 
						|
	Mesh *me = ob->data;
 | 
						|
	MVert *mvert;
 | 
						|
	MFace *mface;
 | 
						|
	DispListMesh *ndlm=NULL, *dlm=NULL;
 | 
						|
	LOD_Decimation_Info lod;
 | 
						|
	int totvert, totface;
 | 
						|
	int a, numTris;
 | 
						|
 | 
						|
	if (dm) {
 | 
						|
		dlm = dm->convertToDispListMesh(dm, 1);
 | 
						|
		mvert = dlm->mvert;
 | 
						|
		mface = dlm->mface;
 | 
						|
		totvert = dlm->totvert;
 | 
						|
		totface = dlm->totface;
 | 
						|
	} else {
 | 
						|
		mvert = me->mvert;
 | 
						|
		mface = me->mface;
 | 
						|
		totvert = me->totvert;
 | 
						|
		totface = me->totface;
 | 
						|
	}
 | 
						|
 | 
						|
	numTris = 0;
 | 
						|
	for (a=0; a<totface; a++) {
 | 
						|
		MFace *mf = &mface[a];
 | 
						|
		numTris++;
 | 
						|
		if (mf->v4) numTris++;
 | 
						|
	}
 | 
						|
 | 
						|
	if(numTris<3) {
 | 
						|
		modifier_setError(md, "There must be 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];
 | 
						|
 | 
						|
		if (vertexCos) {
 | 
						|
			VECCOPY(vbCo, vertexCos[a]);
 | 
						|
		} else {
 | 
						|
			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;
 | 
						|
			}
 | 
						|
 | 
						|
			ndlm= MEM_callocN(sizeof(DispListMesh), "dispmesh");
 | 
						|
			ndlm->mvert= MEM_callocN(lod.vertex_num*sizeof(MVert), "mvert");
 | 
						|
			ndlm->totvert= lod.vertex_num;
 | 
						|
			if(lod.vertex_num>2) {
 | 
						|
				ndlm->mface= MEM_callocN(lod.face_num*sizeof(MFace), "mface");
 | 
						|
				ndlm->totface= dmd->faceCount = lod.face_num;
 | 
						|
			}
 | 
						|
			for(a=0; a<lod.vertex_num; a++) {
 | 
						|
				MVert *mv = &ndlm->mvert[a];
 | 
						|
				float *vbCo = &lod.vertex_buffer[a*3];
 | 
						|
				
 | 
						|
				VECCOPY(mv->co, vbCo);
 | 
						|
			}
 | 
						|
 | 
						|
			if(lod.vertex_num>2) {
 | 
						|
				for(a=0; a<lod.face_num; a++) {
 | 
						|
					MFace *mf = &ndlm->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, NULL, 3);
 | 
						|
				}
 | 
						|
				displistmesh_add_edges(ndlm);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		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:
 | 
						|
	if (dlm) displistmesh_free(dlm);
 | 
						|
 | 
						|
	if (ndlm) {
 | 
						|
		mesh_calc_normals(ndlm->mvert, ndlm->totvert, ndlm->mface, ndlm->totface, &ndlm->nors);
 | 
						|
 | 
						|
		return derivedmesh_from_displistmesh(ndlm, NULL);
 | 
						|
	} else {
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Wave */
 | 
						|
 | 
						|
static void waveModifier_initData(ModifierData *md) 
 | 
						|
{
 | 
						|
	WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
 | 
						|
		
 | 
						|
	wmd->flag |= (WAV_X+WAV_Y+WAV_CYCL);
 | 
						|
	
 | 
						|
	wmd->height= 0.5f;
 | 
						|
	wmd->width= 1.5f;
 | 
						|
	wmd->speed= 0.5f;
 | 
						|
	wmd->narrow= 1.5f;
 | 
						|
	wmd->lifetime= 0.0f;
 | 
						|
	wmd->damp= 10.0f;
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
static int waveModifier_dependsOnTime(ModifierData *md)
 | 
						|
{
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static void waveModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	WaveModifierData *wmd = (WaveModifierData*) md;
 | 
						|
	float ctime = bsystem_time(ob, 0, (float)G.scene->r.cfra, 0.0);
 | 
						|
	float minfac = (float)(1.0/exp(wmd->width*wmd->narrow*wmd->width*wmd->narrow));
 | 
						|
	float lifefac = wmd->height;
 | 
						|
 | 
						|
	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(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;
 | 
						|
 | 
						|
			if(wmd->flag & WAV_X) {
 | 
						|
				if(wmd->flag & WAV_Y) amplit= (float)sqrt( (x*x + y*y));
 | 
						|
				else amplit= x;
 | 
						|
			}
 | 
						|
			else amplit= y;
 | 
						|
			
 | 
						|
			/* this way it makes nice circles */
 | 
						|
			amplit-= (ctime-wmd->timeoffs)*wmd->speed;
 | 
						|
 | 
						|
			if(wmd->flag & WAV_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);
 | 
						|
 | 
						|
				co[2]+= lifefac*amplit;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void waveModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	waveModifier_deformVerts(md, ob, NULL, vertexCos, numVerts);
 | 
						|
}
 | 
						|
 | 
						|
/* 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;
 | 
						|
}
 | 
						|
 | 
						|
static int armatureModifier_isDisabled(ModifierData *md)
 | 
						|
{
 | 
						|
	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, 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);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void armatureModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	ArmatureModifierData *amd = (ArmatureModifierData*) md;
 | 
						|
 | 
						|
	armature_deform_verts(amd->object, ob, vertexCos, numVerts, amd->deformflag);
 | 
						|
}
 | 
						|
 | 
						|
static void armatureModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	ArmatureModifierData *amd = (ArmatureModifierData*) md;
 | 
						|
 | 
						|
	armature_deform_verts(amd->object, ob, vertexCos, numVerts, amd->deformflag);
 | 
						|
}
 | 
						|
 | 
						|
/* 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));
 | 
						|
}
 | 
						|
 | 
						|
static void hookModifier_freeData(ModifierData *md)
 | 
						|
{
 | 
						|
	HookModifierData *hmd = (HookModifierData*) md;
 | 
						|
 | 
						|
	if (hmd->indexar) MEM_freeN(hmd->indexar);
 | 
						|
}
 | 
						|
 | 
						|
static int hookModifier_isDisabled(ModifierData *md)
 | 
						|
{
 | 
						|
	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, Object *ob, DagNode *obNode)
 | 
						|
{
 | 
						|
	HookModifierData *hmd = (HookModifierData*) md;
 | 
						|
 | 
						|
	if (hmd->object) {
 | 
						|
		DagNode *curNode = dag_get_node(forest, hmd->object);
 | 
						|
 | 
						|
		dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void hookModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	HookModifierData *hmd = (HookModifierData*) md;
 | 
						|
	float vec[3], mat[4][4];
 | 
						|
	int i;
 | 
						|
 | 
						|
	Mat4Invert(ob->imat, ob->obmat);
 | 
						|
	Mat4MulSerie(mat, ob->imat, hmd->object->obmat, 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(hmd->falloff!=0.0) {
 | 
						|
					float len= VecLenf(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) {
 | 
						|
					VecMat4MulVecfl(vec, mat, co);
 | 
						|
					VecLerpf(co, co, vec, fac);
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else {	/* vertex group hook */
 | 
						|
		bDeformGroup *curdef;
 | 
						|
		Mesh *me= ob->data;
 | 
						|
		int index=0;
 | 
						|
		
 | 
						|
		/* find the group (weak loop-in-loop) */
 | 
						|
		for (curdef = ob->defbase.first; curdef; curdef=curdef->next, index++)
 | 
						|
			if (!strcmp(curdef->name, hmd->name))
 | 
						|
				break;
 | 
						|
		
 | 
						|
		if(curdef && me->dvert) {
 | 
						|
			MDeformVert *dvert= me->dvert;
 | 
						|
			int i, j;
 | 
						|
			
 | 
						|
			for (i=0; i < me->totvert; i++, dvert++) {
 | 
						|
				for(j=0; j<dvert->totweight; j++) {
 | 
						|
					if (dvert->dw[j].def_nr == index) {
 | 
						|
						float fac = hmd->force*dvert->dw[j].weight;
 | 
						|
						float *co = vertexCos[i];
 | 
						|
						
 | 
						|
						if(hmd->falloff!=0.0) {
 | 
						|
							float len= VecLenf(co, hmd->cent);
 | 
						|
							if(len > hmd->falloff) fac = 0.0;
 | 
						|
							else if(len>0.0) fac *= sqrt(1.0 - len/hmd->falloff);
 | 
						|
						}
 | 
						|
						
 | 
						|
						VecMat4MulVecfl(vec, mat, co);
 | 
						|
						VecLerpf(co, co, vec, fac);
 | 
						|
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void hookModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts);
 | 
						|
}
 | 
						|
 | 
						|
/* Softbody */
 | 
						|
 | 
						|
static void softbodyModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
 | 
						|
{
 | 
						|
	sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
 | 
						|
}
 | 
						|
 | 
						|
/* 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)
 | 
						|
{
 | 
						|
	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, 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);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void *booleanModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
 | 
						|
{	
 | 
						|
		// XXX doesn't handle derived data
 | 
						|
	BooleanModifierData *bmd = (BooleanModifierData*) md;
 | 
						|
	
 | 
						|
	/* we do a quick sanity check */
 | 
						|
	if( ((Mesh *)ob->data)->totface>3 && bmd->object && ((Mesh *)bmd->object->data)->totface>3) {
 | 
						|
		DispListMesh *dlm= NewBooleanMeshDLM(bmd->object, ob, 1+bmd->operation);
 | 
						|
		
 | 
						|
		/* if new mesh returned, get derived mesh; otherwise there was
 | 
						|
		 * an error, so delete the modifier object */
 | 
						|
 | 
						|
		if( dlm )
 | 
						|
			return derivedmesh_from_displistmesh(dlm, NULL);
 | 
						|
		else
 | 
						|
			bmd->object = NULL;
 | 
						|
	}
 | 
						|
	return derivedData;
 | 
						|
}
 | 
						|
 | 
						|
/***/
 | 
						|
 | 
						|
static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
 | 
						|
static int typeArrInit = 1;
 | 
						|
 | 
						|
ModifierTypeInfo *modifierType_getInfo(ModifierType type)
 | 
						|
{
 | 
						|
	if (typeArrInit) {
 | 
						|
		ModifierTypeInfo *mti;
 | 
						|
 | 
						|
		memset(typeArr, 0, sizeof(typeArr));
 | 
						|
 | 
						|
		/* 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 | eModifierTypeFlag_RequiresOriginalData;
 | 
						|
		mti->copyData = curveModifier_copyData;
 | 
						|
		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 | eModifierTypeFlag_RequiresOriginalData;
 | 
						|
		mti->copyData = latticeModifier_copyData;
 | 
						|
		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;
 | 
						|
		mti->initData = subsurfModifier_initData;
 | 
						|
		mti->copyData = subsurfModifier_copyData;
 | 
						|
		mti->freeData = subsurfModifier_freeData;
 | 
						|
		mti->applyModifier = subsurfModifier_applyModifier;
 | 
						|
		mti->applyModifierEM = subsurfModifier_applyModifierEM;
 | 
						|
 | 
						|
		mti = INIT_TYPE(Build);
 | 
						|
		mti->type = eModifierTypeType_Nonconstructive;
 | 
						|
		mti->flags = eModifierTypeFlag_AcceptsMesh;
 | 
						|
		mti->initData = buildModifier_initData;
 | 
						|
		mti->copyData = buildModifier_copyData;
 | 
						|
		mti->dependsOnTime = buildModifier_dependsOnTime;
 | 
						|
		mti->applyModifier = buildModifier_applyModifier;
 | 
						|
 | 
						|
		mti = INIT_TYPE(Mirror);
 | 
						|
		mti->type = eModifierTypeType_Constructive;
 | 
						|
		mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode;
 | 
						|
		mti->initData = mirrorModifier_initData;
 | 
						|
		mti->copyData = mirrorModifier_copyData;
 | 
						|
		mti->applyModifier = mirrorModifier_applyModifier;
 | 
						|
		mti->applyModifierEM = mirrorModifier_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(Wave);
 | 
						|
		mti->type = eModifierTypeType_OnlyDeform;
 | 
						|
		mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode;
 | 
						|
		mti->initData = waveModifier_initData;
 | 
						|
		mti->copyData = waveModifier_copyData;
 | 
						|
		mti->dependsOnTime = waveModifier_dependsOnTime;
 | 
						|
		mti->deformVerts = waveModifier_deformVerts;
 | 
						|
		mti->deformVertsEM = waveModifier_deformVertsEM;
 | 
						|
 | 
						|
		mti = INIT_TYPE(Armature);
 | 
						|
		mti->type = eModifierTypeType_OnlyDeform;
 | 
						|
		mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_RequiresOriginalData;
 | 
						|
		mti->initData = armatureModifier_initData;
 | 
						|
		mti->copyData = armatureModifier_copyData;
 | 
						|
		mti->isDisabled = armatureModifier_isDisabled;
 | 
						|
		mti->foreachObjectLink = armatureModifier_foreachObjectLink;
 | 
						|
		mti->updateDepgraph = armatureModifier_updateDepgraph;
 | 
						|
		mti->deformVerts = armatureModifier_deformVerts;
 | 
						|
		mti->deformVertsEM = armatureModifier_deformVertsEM;
 | 
						|
 | 
						|
		mti = INIT_TYPE(Hook);
 | 
						|
		mti->type = eModifierTypeType_OnlyDeform;
 | 
						|
		mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_RequiresOriginalData;
 | 
						|
		mti->initData = hookModifier_initData;
 | 
						|
		mti->copyData = hookModifier_copyData;
 | 
						|
		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;
 | 
						|
		mti->deformVerts = softbodyModifier_deformVerts;
 | 
						|
 | 
						|
		mti = INIT_TYPE(Boolean);
 | 
						|
		mti->type = eModifierTypeType_Nonconstructive;
 | 
						|
		mti->flags = eModifierTypeFlag_AcceptsMesh;
 | 
						|
		mti->copyData = booleanModifier_copyData;
 | 
						|
		mti->isDisabled = booleanModifier_isDisabled;
 | 
						|
		mti->applyModifier = booleanModifier_applyModifier;
 | 
						|
		mti->foreachObjectLink = booleanModifier_foreachObjectLink;
 | 
						|
		mti->updateDepgraph = booleanModifier_updateDepgraph;
 | 
						|
 | 
						|
		typeArrInit = 0;
 | 
						|
#undef INIT_TYPE
 | 
						|
	}
 | 
						|
 | 
						|
	if (type>=0 && type<NUM_MODIFIER_TYPES && typeArr[type].name[0]!='\0') {
 | 
						|
		return &typeArr[type];
 | 
						|
	} else {
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/***/
 | 
						|
 | 
						|
ModifierData *modifier_new(int type)
 | 
						|
{
 | 
						|
	ModifierTypeInfo *mti = modifierType_getInfo(type);
 | 
						|
	ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
 | 
						|
 | 
						|
	strcpy(md->name, mti->name);
 | 
						|
 | 
						|
	md->type = type;
 | 
						|
	md->mode = eModifierMode_Realtime|eModifierMode_Render|eModifierMode_Expanded;
 | 
						|
 | 
						|
	if (mti->flags&eModifierTypeFlag_EnableInEditmode)
 | 
						|
		md->mode |= eModifierMode_Editmode;
 | 
						|
 | 
						|
	if (mti->initData) mti->initData(md);
 | 
						|
 | 
						|
	return md;
 | 
						|
}
 | 
						|
 | 
						|
void modifier_free(ModifierData *md) 
 | 
						|
{
 | 
						|
	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 | 
						|
 | 
						|
	if (mti->freeData) mti->freeData(md);
 | 
						|
	if (md->error) MEM_freeN(md->error);
 | 
						|
 | 
						|
	MEM_freeN(md);
 | 
						|
}
 | 
						|
 | 
						|
int modifier_dependsOnTime(ModifierData *md) 
 | 
						|
{
 | 
						|
	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 | 
						|
 | 
						|
	return mti->dependsOnTime && mti->dependsOnTime(md);
 | 
						|
}
 | 
						|
 | 
						|
int modifier_supportsMapping(ModifierData *md)
 | 
						|
{
 | 
						|
	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 | 
						|
 | 
						|
	return (	(mti->flags&eModifierTypeFlag_SupportsEditmode) &&
 | 
						|
				(	(mti->type==eModifierTypeType_OnlyDeform ||
 | 
						|
					(mti->flags&eModifierTypeFlag_SupportsMapping))) );
 | 
						|
}
 | 
						|
 | 
						|
ModifierData *modifiers_findByType(Object *ob, ModifierType type)
 | 
						|
{
 | 
						|
	ModifierData *md = ob->modifiers.first;
 | 
						|
 | 
						|
	for (; md; md=md->next)
 | 
						|
		if (md->type==type)
 | 
						|
			break;
 | 
						|
 | 
						|
	return md;
 | 
						|
}
 | 
						|
 | 
						|
void modifiers_clearErrors(Object *ob)
 | 
						|
{
 | 
						|
	ModifierData *md = ob->modifiers.first;
 | 
						|
	int qRedraw = 0;
 | 
						|
 | 
						|
	for (; md; md=md->next) {
 | 
						|
		if (md->error) {
 | 
						|
			MEM_freeN(md->error);
 | 
						|
			md->error = NULL;
 | 
						|
 | 
						|
			qRedraw = 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (qRedraw) allqueue(REDRAWBUTSEDIT, 0);
 | 
						|
}
 | 
						|
 | 
						|
void modifiers_foreachObjectLink(Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
 | 
						|
{
 | 
						|
	ModifierData *md = ob->modifiers.first;
 | 
						|
 | 
						|
	for (; md; md=md->next) {
 | 
						|
		ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 | 
						|
 | 
						|
		if (mti->foreachObjectLink) mti->foreachObjectLink(md, ob, walk, userData);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void modifier_copyData(ModifierData *md, ModifierData *target)
 | 
						|
{
 | 
						|
	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 | 
						|
 | 
						|
	target->mode = md->mode;
 | 
						|
 | 
						|
	if (mti->copyData)
 | 
						|
		mti->copyData(md, target);
 | 
						|
}
 | 
						|
 | 
						|
int modifier_couldBeCage(ModifierData *md)
 | 
						|
{
 | 
						|
	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 | 
						|
 | 
						|
	return (	(md->mode&eModifierMode_Realtime) &&
 | 
						|
				(md->mode&eModifierMode_Editmode) &&
 | 
						|
				(!mti->isDisabled || !mti->isDisabled(md)) &&
 | 
						|
				modifier_supportsMapping(md));	
 | 
						|
}
 | 
						|
 | 
						|
void modifier_setError(ModifierData *md, char *format, ...)
 | 
						|
{
 | 
						|
	char buffer[2048];
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, format);
 | 
						|
	vsprintf(buffer, format, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	if (md->error)
 | 
						|
		MEM_freeN(md->error);
 | 
						|
 | 
						|
	md->error = BLI_strdup(buffer);
 | 
						|
 | 
						|
	allqueue(REDRAWBUTSEDIT, 0);
 | 
						|
}
 | 
						|
 | 
						|
/* used for buttons, to find out if the 'draw deformed in editmode' option is there */
 | 
						|
/* also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg then is NULL) */
 | 
						|
int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
 | 
						|
{
 | 
						|
	ModifierData *md = ob->modifiers.first;
 | 
						|
	int i, cageIndex = -1;
 | 
						|
 | 
						|
		/* Find the last modifier acting on the cage. */
 | 
						|
	for (i=0; md; i++,md=md->next) {
 | 
						|
		ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 | 
						|
 | 
						|
		if (!(md->mode&eModifierMode_Realtime)) continue;
 | 
						|
		if (!(md->mode&eModifierMode_Editmode)) continue;
 | 
						|
		if (mti->isDisabled && mti->isDisabled(md)) continue;
 | 
						|
		if (!(mti->flags&eModifierTypeFlag_SupportsEditmode)) continue;
 | 
						|
 | 
						|
		if (!modifier_supportsMapping(md))
 | 
						|
			break;
 | 
						|
 | 
						|
		if (lastPossibleCageIndex_r) *lastPossibleCageIndex_r = i;
 | 
						|
		if (md->mode&eModifierMode_OnCage)
 | 
						|
			cageIndex = i;
 | 
						|
	}
 | 
						|
 | 
						|
	return cageIndex;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int modifiers_isSoftbodyEnabled(Object *ob)
 | 
						|
{
 | 
						|
	ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
 | 
						|
 | 
						|
		/* Softbody not allowed in this situation, enforce! */
 | 
						|
	/* if (md && ob->pd && ob->pd->deflect) {	*/
 | 
						|
	/* no reason for that any more BM */
 | 
						|
	if (0) {
 | 
						|
		md->mode &= ~(eModifierMode_Realtime|eModifierMode_Render|eModifierMode_Editmode);
 | 
						|
		md = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	return (md && md->mode&(eModifierMode_Realtime|eModifierMode_Render));
 | 
						|
}
 | 
						|
 | 
						|
ModifierData *modifiers_getVirtualModifierList(Object *ob)
 | 
						|
{
 | 
						|
		/* Kinda hacky, but should be fine since we are never
 | 
						|
		 * reentrant and avoid free hassles.
 | 
						|
		 */
 | 
						|
	static ArmatureModifierData amd;
 | 
						|
	static CurveModifierData cmd;
 | 
						|
	static LatticeModifierData lmd;
 | 
						|
	static int init = 1;
 | 
						|
 | 
						|
	if (init) {
 | 
						|
		ModifierData *md;
 | 
						|
 | 
						|
		md = modifier_new(eModifierType_Armature);
 | 
						|
		amd = *((ArmatureModifierData*) md);
 | 
						|
		modifier_free(md);
 | 
						|
 | 
						|
		md = modifier_new(eModifierType_Curve);
 | 
						|
		cmd = *((CurveModifierData*) md);
 | 
						|
		modifier_free(md);
 | 
						|
 | 
						|
		md = modifier_new(eModifierType_Lattice);
 | 
						|
		lmd = *((LatticeModifierData*) md);
 | 
						|
		modifier_free(md);
 | 
						|
 | 
						|
		amd.modifier.mode |= eModifierMode_Virtual;
 | 
						|
		cmd.modifier.mode |= eModifierMode_Virtual;
 | 
						|
		lmd.modifier.mode |= eModifierMode_Virtual;
 | 
						|
 | 
						|
		init = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	if (ob->parent) {
 | 
						|
		if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) {
 | 
						|
			amd.object = ob->parent;
 | 
						|
			amd.modifier.next = ob->modifiers.first;
 | 
						|
			amd.deformflag= ((bArmature *)(ob->parent->data))->deformflag;
 | 
						|
			return &amd.modifier;
 | 
						|
		} else if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) {
 | 
						|
			cmd.object = ob->parent;
 | 
						|
			cmd.modifier.next = ob->modifiers.first;
 | 
						|
			return &cmd.modifier;
 | 
						|
		} else if(ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
 | 
						|
			lmd.object = ob->parent;
 | 
						|
			lmd.modifier.next = ob->modifiers.first;
 | 
						|
			return &lmd.modifier;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return ob->modifiers.first;
 | 
						|
}
 | 
						|
 | 
						|
Object *modifiers_isDeformedByArmature(Object *ob)
 | 
						|
{
 | 
						|
	ModifierData *md = modifiers_getVirtualModifierList(ob);
 | 
						|
 | 
						|
	for (; md; md=md->next) {
 | 
						|
		if (md->type==eModifierType_Armature) {
 | 
						|
			ArmatureModifierData *amd = (ArmatureModifierData*) md;
 | 
						|
			return amd->object;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
int modifiers_isDeformed(Object *ob)
 | 
						|
{
 | 
						|
	ModifierData *md = modifiers_getVirtualModifierList(ob);
 | 
						|
	
 | 
						|
	for (; md; md=md->next) {
 | 
						|
		if(ob==G.obedit && (md->mode & eModifierMode_Editmode)==0);
 | 
						|
		else {
 | 
						|
			if (md->type==eModifierType_Armature)
 | 
						|
				return 1;
 | 
						|
			if (md->type==eModifierType_Curve)
 | 
						|
				return 1;
 | 
						|
			if (md->type==eModifierType_Lattice)
 | 
						|
				return 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 |