2006-08-28 01:12:36 +00:00
|
|
|
/*
|
|
|
|
* $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) 2005 by the 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 *****
|
|
|
|
*
|
|
|
|
* Modifier stack implementation.
|
|
|
|
*
|
|
|
|
* BKE_modifier.h contains the function prototypes for this file.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2005-07-19 20:14:17 +00:00
|
|
|
#include "string.h"
|
2005-08-04 07:25:43 +00:00
|
|
|
#include "stdarg.h"
|
2005-07-26 02:44:59 +00:00
|
|
|
#include "math.h"
|
2006-08-30 11:10:04 +00:00
|
|
|
#include "float.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
#include "BLI_blenlib.h"
|
2005-07-20 04:14:21 +00:00
|
|
|
#include "BLI_rand.h"
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
#include "BLI_arithb.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "BLI_linklist.h"
|
2006-03-01 15:30:10 +00:00
|
|
|
#include "BLI_edgehash.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "BLI_ghash.h"
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2005-07-19 20:14:17 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2005-10-20 16:31:46 +00:00
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_effect_types.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "DNA_material_types.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
#include "DNA_modifier_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
2005-08-11 02:23:52 +00:00
|
|
|
#include "DNA_object_force.h"
|
2005-07-20 04:14:21 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "DNA_texture_types.h"
|
2006-03-01 15:30:10 +00:00
|
|
|
#include "DNA_curve_types.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "DNA_camera_types.h"
|
2005-10-20 16:31:46 +00:00
|
|
|
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
#include "BLI_editVert.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
|
2006-03-01 15:30:10 +00:00
|
|
|
#include "MTC_matrixops.h"
|
|
|
|
#include "MTC_vectorops.h"
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "BKE_main.h"
|
2006-03-01 15:30:10 +00:00
|
|
|
#include "BKE_anim.h"
|
2005-08-04 07:25:43 +00:00
|
|
|
#include "BKE_bad_level_calls.h"
|
2006-12-12 21:29:09 +00:00
|
|
|
#include "BKE_customdata.h"
|
2005-07-20 04:14:21 +00:00
|
|
|
#include "BKE_global.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
#include "BKE_utildefines.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "BKE_cdderivedmesh.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
#include "BKE_DerivedMesh.h"
|
2005-09-03 17:22:29 +00:00
|
|
|
#include "BKE_booleanops.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
#include "BKE_displist.h"
|
|
|
|
#include "BKE_modifier.h"
|
|
|
|
#include "BKE_lattice.h"
|
|
|
|
#include "BKE_subsurf.h"
|
2005-07-20 04:14:21 +00:00
|
|
|
#include "BKE_object.h"
|
|
|
|
#include "BKE_mesh.h"
|
2005-08-11 02:23:52 +00:00
|
|
|
#include "BKE_softbody.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "BKE_material.h"
|
2005-07-19 23:04:34 +00:00
|
|
|
#include "depsgraph_private.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
|
2005-07-26 02:44:59 +00:00
|
|
|
#include "LOD_DependKludge.h"
|
|
|
|
#include "LOD_decimation.h"
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
#include "CCGSubSurf.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "RE_shader_ext.h"
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
/***/
|
2005-07-19 20:14:17 +00:00
|
|
|
|
|
|
|
static int noneModifier_isDisabled(ModifierData *md)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Curve */
|
|
|
|
|
2006-10-28 16:48:56 +00:00
|
|
|
static void curveModifier_initData(ModifierData *md)
|
|
|
|
{
|
|
|
|
CurveModifierData *cmd = (CurveModifierData*) md;
|
|
|
|
|
|
|
|
cmd->defaxis = MOD_CURVE_POSX;
|
|
|
|
}
|
|
|
|
|
2005-07-27 20:16:41 +00:00
|
|
|
static void curveModifier_copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
|
|
|
CurveModifierData *cmd = (CurveModifierData*) md;
|
|
|
|
CurveModifierData *tcmd = (CurveModifierData*) target;
|
|
|
|
|
2006-10-28 16:48:56 +00:00
|
|
|
tcmd->defaxis = cmd->defaxis;
|
2005-07-27 20:16:41 +00:00
|
|
|
tcmd->object = cmd->object;
|
2006-09-08 01:05:57 +00:00
|
|
|
strncpy(tcmd->name, cmd->name, 32);
|
2005-07-27 20:16:41 +00:00
|
|
|
}
|
|
|
|
|
2006-12-05 17:42:03 +00:00
|
|
|
CustomDataMask curveModifier_requiredDataMask(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;
|
|
|
|
}
|
|
|
|
|
2005-07-19 20:14:17 +00:00
|
|
|
static int curveModifier_isDisabled(ModifierData *md)
|
|
|
|
{
|
|
|
|
CurveModifierData *cmd = (CurveModifierData*) md;
|
|
|
|
|
|
|
|
return !cmd->object;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void curveModifier_foreachObjectLink(
|
|
|
|
ModifierData *md, Object *ob,
|
|
|
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
|
|
|
void *userData)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
CurveModifierData *cmd = (CurveModifierData*) md;
|
|
|
|
|
|
|
|
walk(userData, ob, &cmd->object);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void curveModifier_updateDepgraph(
|
|
|
|
ModifierData *md, DagForest *forest,
|
|
|
|
Object *ob, DagNode *obNode)
|
2005-07-19 23:04:34 +00:00
|
|
|
{
|
|
|
|
CurveModifierData *cmd = (CurveModifierData*) md;
|
|
|
|
|
|
|
|
if (cmd->object) {
|
|
|
|
DagNode *curNode = dag_get_node(forest, cmd->object);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dag_add_relation(forest, curNode, obNode,
|
|
|
|
DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
|
2005-07-19 23:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void curveModifier_deformVerts(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
float (*vertexCos)[3], int numVerts)
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
{
|
|
|
|
CurveModifierData *cmd = (CurveModifierData*) md;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
curve_deform_verts(cmd->object, ob, derivedData, vertexCos, numVerts,
|
2006-10-28 16:48:56 +00:00
|
|
|
cmd->name, cmd->defaxis);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void curveModifier_deformVertsEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
2005-07-19 20:14:17 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *dm = derivedData;
|
|
|
|
|
|
|
|
if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
|
|
|
|
|
|
|
|
curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
|
|
|
|
|
|
|
|
if(!derivedData) dm->release(dm);
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Lattice */
|
|
|
|
|
2005-07-27 20:16:41 +00:00
|
|
|
static void latticeModifier_copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
|
|
|
LatticeModifierData *lmd = (LatticeModifierData*) md;
|
|
|
|
LatticeModifierData *tlmd = (LatticeModifierData*) target;
|
|
|
|
|
|
|
|
tlmd->object = lmd->object;
|
2006-09-08 01:05:57 +00:00
|
|
|
strncpy(tlmd->name, lmd->name, 32);
|
2005-07-27 20:16:41 +00:00
|
|
|
}
|
|
|
|
|
2006-12-05 17:42:03 +00:00
|
|
|
CustomDataMask latticeModifier_requiredDataMask(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;
|
|
|
|
}
|
|
|
|
|
2005-07-19 20:14:17 +00:00
|
|
|
static int latticeModifier_isDisabled(ModifierData *md)
|
|
|
|
{
|
|
|
|
LatticeModifierData *lmd = (LatticeModifierData*) md;
|
|
|
|
|
|
|
|
return !lmd->object;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void latticeModifier_foreachObjectLink(
|
|
|
|
ModifierData *md, Object *ob,
|
|
|
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
|
|
|
void *userData)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
LatticeModifierData *lmd = (LatticeModifierData*) md;
|
|
|
|
|
|
|
|
walk(userData, ob, &lmd->object);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest,
|
|
|
|
Object *ob, DagNode *obNode)
|
2005-07-19 23:04:34 +00:00
|
|
|
{
|
|
|
|
LatticeModifierData *lmd = (LatticeModifierData*) md;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(lmd->object) {
|
2005-07-19 23:04:34 +00:00
|
|
|
DagNode *latNode = dag_get_node(forest, lmd->object);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dag_add_relation(forest, latNode, obNode,
|
|
|
|
DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
|
2005-07-19 23:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void latticeModifier_deformVerts(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
float (*vertexCos)[3], int numVerts)
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
{
|
|
|
|
LatticeModifierData *lmd = (LatticeModifierData*) md;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
lattice_deform_verts(lmd->object, ob, derivedData,
|
|
|
|
vertexCos, numVerts, lmd->name);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void latticeModifier_deformVertsEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
2005-07-19 20:14:17 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *dm = derivedData;
|
|
|
|
|
|
|
|
if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
|
|
|
|
|
|
|
|
latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
|
|
|
|
|
|
|
|
if(!derivedData) dm->release(dm);
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Subsurf */
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
static void subsurfModifier_initData(ModifierData *md)
|
2005-07-19 20:14:17 +00:00
|
|
|
{
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
SubsurfModifierData *smd = (SubsurfModifierData*) md;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2005-07-19 20:14:17 +00:00
|
|
|
smd->levels = 1;
|
|
|
|
smd->renderLevels = 2;
|
2006-01-10 11:36:57 +00:00
|
|
|
smd->flags |= eSubsurfModifierFlag_SubsurfUv;
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
|
|
|
|
2005-07-27 20:16:41 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
static void subsurfModifier_freeData(ModifierData *md)
|
|
|
|
{
|
|
|
|
SubsurfModifierData *smd = (SubsurfModifierData*) md;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(smd->mCache) {
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ccgSubSurf_free(smd->mCache);
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
if(smd->emCache) {
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
ccgSubSurf_free(smd->emCache);
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *subsurfModifier_applyModifier(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
int useRenderParams, int isFinalCalc)
|
2005-07-19 20:14:17 +00:00
|
|
|
{
|
|
|
|
SubsurfModifierData *smd = (SubsurfModifierData*) md;
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *result;
|
2005-07-19 20:14:17 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
result = subsurf_make_derived_from_derived(derivedData, smd,
|
|
|
|
useRenderParams, NULL,
|
|
|
|
isFinalCalc, 0);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return result;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *subsurfModifier_applyModifierEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData)
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
{
|
|
|
|
SubsurfModifierData *smd = (SubsurfModifierData*) md;
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *result;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
result = subsurf_make_derived_from_derived(derivedData, smd, 0,
|
|
|
|
NULL, 0, 1);
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return result;
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
|
|
|
|
2005-07-20 04:14:21 +00:00
|
|
|
/* Build */
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
static void buildModifier_initData(ModifierData *md)
|
2005-07-20 04:14:21 +00:00
|
|
|
{
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
BuildModifierData *bmd = (BuildModifierData*) md;
|
2005-07-20 04:14:21 +00:00
|
|
|
|
|
|
|
bmd->start = 1.0;
|
|
|
|
bmd->length = 100.0;
|
|
|
|
}
|
|
|
|
|
2005-07-27 20:16:41 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-07-20 04:14:21 +00:00
|
|
|
static int buildModifier_dependsOnTime(ModifierData *md)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
|
|
|
|
DerivedMesh *derivedData,
|
|
|
|
int useRenderParams, int isFinalCalc)
|
2005-07-20 04:14:21 +00:00
|
|
|
{
|
2005-07-21 21:19:38 +00:00
|
|
|
DerivedMesh *dm = derivedData;
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *result;
|
2005-07-20 04:14:21 +00:00
|
|
|
BuildModifierData *bmd = (BuildModifierData*) md;
|
2006-08-28 01:12:36 +00:00
|
|
|
int i;
|
|
|
|
int numFaces, numEdges;
|
|
|
|
int maxVerts, maxEdges, maxFaces;
|
|
|
|
int *vertMap, *edgeMap, *faceMap;
|
2005-07-20 04:14:21 +00:00
|
|
|
float frac;
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
2005-07-20 04:14:21 +00:00
|
|
|
|
|
|
|
if (ob) {
|
2006-08-28 01:12:36 +00:00
|
|
|
frac = bsystem_time(ob, 0, (float)G.scene->r.cfra,
|
|
|
|
bmd->start - 1.0f) / bmd->length;
|
2005-07-20 04:14:21 +00:00
|
|
|
} else {
|
2006-08-28 01:12:36 +00:00
|
|
|
frac = G.scene->r.cfra - bmd->start / bmd->length;
|
2005-07-20 04:14:21 +00:00
|
|
|
}
|
|
|
|
CLAMP(frac, 0.0, 1.0);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
numFaces = dm->getNumFaces(dm) * frac;
|
|
|
|
numEdges = dm->getNumEdges(dm) * frac;
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* if there's at least one face, build based on faces */
|
|
|
|
if(numFaces) {
|
|
|
|
int maxEdges;
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(bmd->randomize)
|
|
|
|
BLI_array_randomize(faceMap, sizeof(*faceMap),
|
|
|
|
maxFaces, bmd->seed);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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, (void *)mf.v1))
|
|
|
|
BLI_ghash_insert(vertHash, (void *)mf.v1,
|
|
|
|
(void *)BLI_ghash_size(vertHash));
|
|
|
|
if(!BLI_ghash_haskey(vertHash, (void *)mf.v2))
|
|
|
|
BLI_ghash_insert(vertHash, (void *)mf.v2,
|
|
|
|
(void *)BLI_ghash_size(vertHash));
|
|
|
|
if(!BLI_ghash_haskey(vertHash, (void *)mf.v3))
|
|
|
|
BLI_ghash_insert(vertHash, (void *)mf.v3,
|
|
|
|
(void *)BLI_ghash_size(vertHash));
|
|
|
|
if(mf.v4 && !BLI_ghash_haskey(vertHash, (void *)mf.v4))
|
|
|
|
BLI_ghash_insert(vertHash, (void *)mf.v4,
|
|
|
|
(void *)BLI_ghash_size(vertHash));
|
2005-07-20 04:14:21 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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, (void *)me.v1)
|
|
|
|
&& BLI_ghash_haskey(vertHash, (void *)me.v2))
|
|
|
|
BLI_ghash_insert(edgeHash,
|
|
|
|
(void *)BLI_ghash_size(edgeHash), (void *)i);
|
2005-07-20 04:14:21 +00:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
} else if(numEdges) {
|
|
|
|
if(bmd->randomize)
|
|
|
|
BLI_array_randomize(edgeMap, sizeof(*edgeMap),
|
|
|
|
maxEdges, bmd->seed);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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, (void *)me.v1))
|
|
|
|
BLI_ghash_insert(vertHash, (void *)me.v1,
|
|
|
|
(void *)BLI_ghash_size(vertHash));
|
|
|
|
if(!BLI_ghash_haskey(vertHash, (void *)me.v2))
|
|
|
|
BLI_ghash_insert(vertHash, (void *)me.v2,
|
|
|
|
(void *)BLI_ghash_size(vertHash));
|
2005-07-20 04:14:21 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
BLI_ghash_insert(edgeHash, (void *)BLI_ghash_size(edgeHash),
|
|
|
|
(void *)edgeMap[i]);
|
2005-07-20 04:14:21 +00:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
} else {
|
|
|
|
int numVerts = dm->getNumVerts(dm) * frac;
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(bmd->randomize)
|
|
|
|
BLI_array_randomize(vertMap, sizeof(*vertMap),
|
|
|
|
maxVerts, bmd->seed);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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, (void *)vertMap[i], (void *)i);
|
|
|
|
}
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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 = (int)BLI_ghashIterator_getKey(hashIter);
|
|
|
|
int newIndex = (int)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);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* copy the edges across, remapping indices */
|
|
|
|
for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
|
|
|
|
MEdge source;
|
|
|
|
MEdge *dest;
|
|
|
|
int oldIndex = (int)BLI_ghash_lookup(edgeHash, (void *)i);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dm->getEdge(dm, oldIndex, &source);
|
|
|
|
dest = CDDM_get_edge(result, i);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1);
|
|
|
|
source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
DM_copy_edge_data(dm, result, oldIndex, i, 1);
|
|
|
|
*dest = source;
|
|
|
|
}
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* copy the faces across, remapping indices */
|
|
|
|
for(i = 0; i < numFaces; ++i) {
|
|
|
|
MFace source;
|
|
|
|
MFace *dest;
|
|
|
|
int orig_v4;
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dm->getFace(dm, faceMap[i], &source);
|
|
|
|
dest = CDDM_get_face(result, i);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
orig_v4 = source.v4;
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1);
|
|
|
|
source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2);
|
|
|
|
source.v3 = (int)BLI_ghash_lookup(vertHash, (void *)source.v3);
|
|
|
|
if(source.v4)
|
|
|
|
source.v4 = (int)BLI_ghash_lookup(vertHash, (void *)source.v4);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
DM_copy_face_data(dm, result, faceMap[i], i, 1);
|
|
|
|
*dest = source;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
|
2005-07-20 04:14:21 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
CDDM_calc_normals(result);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
BLI_ghash_free(vertHash, NULL, NULL);
|
|
|
|
BLI_ghash_free(edgeHash, NULL, NULL);
|
|
|
|
|
|
|
|
MEM_freeN(vertMap);
|
|
|
|
MEM_freeN(edgeMap);
|
|
|
|
MEM_freeN(faceMap);
|
|
|
|
|
|
|
|
return result;
|
2005-07-20 04:14:21 +00:00
|
|
|
}
|
|
|
|
|
2006-03-01 15:30:10 +00:00
|
|
|
/* 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
|
|
|
|
*/
|
2007-03-18 13:26:53 +00:00
|
|
|
amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
|
2006-03-01 15:30:10 +00:00
|
|
|
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;
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
tamd->start_cap = amd->start_cap;
|
|
|
|
tamd->end_cap = amd->end_cap;
|
2006-03-01 15:30:10 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void arrayModifier_foreachObjectLink(
|
|
|
|
ModifierData *md, Object *ob,
|
|
|
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
|
|
|
void *userData)
|
2006-03-01 15:30:10 +00:00
|
|
|
{
|
|
|
|
ArrayModifierData *amd = (ArrayModifierData*) md;
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
walk(userData, ob, &amd->start_cap);
|
|
|
|
walk(userData, ob, &amd->end_cap);
|
2006-03-01 15:30:10 +00:00
|
|
|
walk(userData, ob, &amd->curve_ob);
|
|
|
|
walk(userData, ob, &amd->offset_ob);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest,
|
|
|
|
Object *ob, DagNode *obNode)
|
2006-03-01 15:30:10 +00:00
|
|
|
{
|
|
|
|
ArrayModifierData *amd = (ArrayModifierData*) md;
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
if (amd->curve_ob) {
|
|
|
|
DagNode *curNode = dag_get_node(forest, amd->curve_ob);
|
|
|
|
|
|
|
|
dag_add_relation(forest, curNode, obNode,
|
2006-08-28 01:12:36 +00:00
|
|
|
DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
if (amd->offset_ob) {
|
|
|
|
DagNode *curNode = dag_get_node(forest, amd->offset_ob);
|
|
|
|
|
|
|
|
dag_add_relation(forest, curNode, obNode,
|
2006-08-28 01:12:36 +00:00
|
|
|
DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
float vertarray_size(MVert *mvert, int numVerts, int axis)
|
2006-03-01 15:30:10 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
float min_co, max_co;
|
|
|
|
|
|
|
|
/* if there are no vertices, width is 0 */
|
2006-08-28 01:12:36 +00:00
|
|
|
if(numVerts == 0) return 0;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
|
|
|
/* find the minimum and maximum coordinates on the desired axis */
|
2006-08-28 01:12:36 +00:00
|
|
|
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];
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
/* 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)
|
2006-03-01 15:30:10 +00:00
|
|
|
{
|
2007-03-18 13:26:53 +00:00
|
|
|
if(indexMap[oldIndex].merge < 0) {
|
2006-07-06 21:43:09 +00:00
|
|
|
/* vert wasn't merged, so use copy of this vert */
|
2007-03-18 13:26:53 +00:00
|
|
|
return indexMap[oldIndex].new + copyNum;
|
|
|
|
} else if(indexMap[oldIndex].merge == oldIndex) {
|
2006-07-06 21:43:09 +00:00
|
|
|
/* vert was merged with itself */
|
2007-03-18 13:26:53 +00:00
|
|
|
return indexMap[oldIndex].new;
|
2006-03-01 15:30:10 +00:00
|
|
|
} else {
|
2006-07-06 21:43:09 +00:00
|
|
|
/* vert was merged with another vert */
|
2006-08-30 07:35:19 +00:00
|
|
|
/* follow the chain of merges to the end, or until we've passed
|
|
|
|
* a number of vertices equal to the copy number
|
|
|
|
*/
|
2007-03-18 13:26:53 +00:00
|
|
|
if(copyNum <= 0)
|
|
|
|
return indexMap[oldIndex].new;
|
2006-07-06 21:43:09 +00:00
|
|
|
else
|
2007-03-18 13:26:53 +00:00
|
|
|
return calc_mapping(indexMap, indexMap[oldIndex].merge,
|
|
|
|
copyNum - 1);
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
|
|
|
|
Object *ob, DerivedMesh *dm,
|
|
|
|
int initFlags)
|
2006-03-01 15:30:10 +00:00
|
|
|
{
|
|
|
|
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;
|
2006-08-28 01:12:36 +00:00
|
|
|
int numVerts, numEdges, numFaces;
|
|
|
|
int maxVerts, maxEdges, maxFaces;
|
2007-03-18 13:26:53 +00:00
|
|
|
int finalVerts, finalEdges, finalFaces;
|
|
|
|
DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
|
2006-08-28 01:12:36 +00:00
|
|
|
MVert *mvert, *src_mvert;
|
|
|
|
MEdge *medge;
|
|
|
|
MFace *mface;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
|
|
|
IndexMapEntry *indexMap;
|
|
|
|
|
|
|
|
EdgeHash *edges;
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
/* need to avoid infinite recursion here */
|
|
|
|
if(amd->start_cap && amd->start_cap != ob)
|
|
|
|
start_cap = mesh_get_derived_final(amd->start_cap, CD_MASK_MESH);
|
|
|
|
if(amd->end_cap && amd->end_cap != ob)
|
|
|
|
end_cap = mesh_get_derived_final(amd->end_cap, CD_MASK_MESH);
|
|
|
|
|
2006-03-01 15:30:10 +00:00
|
|
|
MTC_Mat4One(offset);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
|
|
|
|
"indexmap");
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
src_mvert = dm->getVertArray(dm);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
maxVerts = dm->getNumVerts(dm);
|
|
|
|
|
2006-03-01 15:30:10 +00:00
|
|
|
if(amd->offset_type & MOD_ARR_OFF_CONST)
|
|
|
|
VecAddf(offset[3], offset[3], amd->offset);
|
|
|
|
if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
|
|
|
|
for(j = 0; j < 3; j++)
|
2006-08-28 01:12:36 +00:00
|
|
|
offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
|
|
|
|
maxVerts, j);
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
|
|
|
|
float obinv[4][4];
|
|
|
|
float result_mat[4][4];
|
|
|
|
|
|
|
|
if(ob)
|
|
|
|
MTC_Mat4Invert(obinv, ob->obmat);
|
|
|
|
else
|
|
|
|
MTC_Mat4One(obinv);
|
|
|
|
|
|
|
|
MTC_Mat4MulSerie(result_mat, offset,
|
|
|
|
obinv, amd->offset_ob->obmat,
|
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
MTC_Mat4CpyMat4(offset, result_mat);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
|
|
|
|
Curve *cu = amd->curve_ob->data;
|
|
|
|
if(cu) {
|
2006-11-26 14:04:25 +00:00
|
|
|
if(!cu->path) {
|
|
|
|
cu->flag |= CU_PATH; // needed for path & bevlist
|
|
|
|
makeDispListCurveTypes(amd->curve_ob, 0);
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
if(cu->path)
|
|
|
|
length = 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(MTC_dot3Float(offset[3], offset[3]));
|
|
|
|
|
2006-08-30 11:10:04 +00:00
|
|
|
if(dist > FLT_EPSILON)
|
2006-03-01 15:30:10 +00:00
|
|
|
/* this gives length = first copy start to last copy end
|
|
|
|
add a tiny offset for floating point rounding errors */
|
2006-08-30 11:10:04 +00:00
|
|
|
count = (length + FLT_EPSILON) / dist;
|
2006-03-01 15:30:10 +00:00
|
|
|
else
|
|
|
|
/* if the offset has no translation, just make one copy */
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(count < 1)
|
|
|
|
count = 1;
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
/* 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);
|
2006-03-01 15:30:10 +00:00
|
|
|
|
|
|
|
/* calculate the offset matrix of the final copy (for merging) */
|
|
|
|
MTC_Mat4One(final_offset);
|
|
|
|
|
|
|
|
for(j=0; j < count - 1; j++) {
|
|
|
|
MTC_Mat4MulMat4(tmp_mat, final_offset, offset);
|
|
|
|
MTC_Mat4CpyMat4(final_offset, tmp_mat);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
numVerts = numEdges = numFaces = 0;
|
|
|
|
mvert = CDDM_get_verts(result);
|
|
|
|
|
|
|
|
for (i = 0; i < maxVerts; i++) {
|
|
|
|
MVert *inMV;
|
|
|
|
MVert *mv = &mvert[numVerts];
|
2006-03-01 15:30:10 +00:00
|
|
|
MVert *mv2;
|
|
|
|
float co[3];
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
inMV = &src_mvert[i];
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
DM_copy_vert_data(dm, result, i, numVerts, 1);
|
|
|
|
*mv = *inMV;
|
|
|
|
numVerts++;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
indexMap[i].new = numVerts - 1;
|
2006-03-01 15:30:10 +00:00
|
|
|
indexMap[i].merge = -1; /* default to no merge */
|
|
|
|
indexMap[i].merge_final = 0; /* default to no merge */
|
|
|
|
|
|
|
|
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);
|
|
|
|
MTC_Mat4MulVecfl(offset, tmp_co);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
for(j = 0; j < maxVerts; j++) {
|
|
|
|
inMV = &src_mvert[j];
|
2006-03-01 15:30:10 +00:00
|
|
|
/* if this vert is within merge limit, merge */
|
|
|
|
if(VecLenCompare(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) {
|
2006-08-28 01:12:36 +00:00
|
|
|
VECCOPY(tmp_co, inMV->co);
|
|
|
|
inMV = &src_mvert[i];
|
2006-03-01 15:30:10 +00:00
|
|
|
MTC_Mat4MulVecfl(final_offset, tmp_co);
|
|
|
|
if(VecLenCompare(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++) {
|
2006-08-28 01:12:36 +00:00
|
|
|
mv2 = &mvert[numVerts];
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
|
2006-03-01 15:30:10 +00:00
|
|
|
*mv2 = *mv;
|
2006-08-28 01:12:36 +00:00
|
|
|
numVerts++;
|
|
|
|
|
2006-03-01 15:30:10 +00:00
|
|
|
MTC_Mat4MulVecfl(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
|
|
|
|
*/
|
2006-08-28 01:12:36 +00:00
|
|
|
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,
|
2007-03-18 13:26:53 +00:00
|
|
|
count - 1);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
if(indexMap[inMED.v2].merge_final) {
|
|
|
|
med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
|
2007-03-18 13:26:53 +00:00
|
|
|
count - 1);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
for(j = 1; j < count; j++)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
|
|
|
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)
|
2007-03-18 13:26:53 +00:00
|
|
|
mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
|
2006-08-28 01:12:36 +00:00
|
|
|
if(indexMap[inMF.v2].merge_final)
|
2007-03-18 13:26:53 +00:00
|
|
|
mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
|
2006-08-28 01:12:36 +00:00
|
|
|
if(indexMap[inMF.v3].merge_final)
|
2007-03-18 13:26:53 +00:00
|
|
|
mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
|
2006-08-28 01:12:36 +00:00
|
|
|
if(inMF.v4 && indexMap[inMF.v4].merge_final)
|
2007-03-18 13:26:53 +00:00
|
|
|
mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3);
|
|
|
|
numFaces++;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
/* if the face has fewer than 3 vertices, don't create it */
|
|
|
|
if(mf->v3 == 0) {
|
|
|
|
numFaces--;
|
|
|
|
DM_free_face_data(result, numFaces, 1);
|
|
|
|
}
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
for(j = 1; j < count; j++)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
|
|
|
|
numFaces++;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
/* if the face has fewer than 3 vertices, don't create it */
|
|
|
|
if(mf2->v3 == 0) {
|
|
|
|
numFaces--;
|
|
|
|
DM_free_face_data(result, numFaces, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-18 13:26:53 +00:00
|
|
|
/* 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);
|
|
|
|
|
|
|
|
Mat4Invert(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);
|
|
|
|
Mat4MulVecfl(startoffset, tmp_co);
|
|
|
|
|
|
|
|
for(j = 0; j < maxVerts; j++) {
|
|
|
|
in_mv = &src_mvert[j];
|
|
|
|
/* if this vert is within merge limit, merge */
|
|
|
|
if(VecLenCompare(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;
|
|
|
|
Mat4MulVecfl(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];
|
|
|
|
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);
|
|
|
|
|
|
|
|
Mat4MulMat4(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);
|
|
|
|
Mat4MulVecfl(offset, tmp_co);
|
|
|
|
|
|
|
|
for(j = 0; j < maxVerts; j++) {
|
|
|
|
in_mv = &src_mvert[j];
|
|
|
|
/* if this vert is within merge limit, merge */
|
|
|
|
if(VecLenCompare(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;
|
|
|
|
Mat4MulVecfl(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];
|
|
|
|
origindex[numFaces] = ORIGINDEX_NONE;
|
|
|
|
|
|
|
|
numFaces++;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(vert_map);
|
|
|
|
end_cap->release(end_cap);
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_edgehash_free(edges, NULL);
|
2006-08-28 01:12:36 +00:00
|
|
|
MEM_freeN(indexMap);
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
CDDM_lower_num_verts(result, numVerts);
|
|
|
|
CDDM_lower_num_edges(result, numEdges);
|
|
|
|
CDDM_lower_num_faces(result, numFaces);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
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, ob, derivedData, 0);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2007-04-30 06:51:24 +00:00
|
|
|
mmd->flag |= MOD_MIR_AXIS_X;
|
2006-08-28 01:12:36 +00:00
|
|
|
mmd->tolerance = 0.001;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mirrorModifier_copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
|
|
|
MirrorModifierData *mmd = (MirrorModifierData*) md;
|
|
|
|
MirrorModifierData *tmmd = (MirrorModifierData*) target;
|
|
|
|
|
|
|
|
tmmd->axis = mmd->axis;
|
2006-09-08 01:05:57 +00:00
|
|
|
tmmd->flag = mmd->flag;
|
2006-08-28 01:12:36 +00:00
|
|
|
tmmd->tolerance = mmd->tolerance;
|
|
|
|
}
|
|
|
|
|
2007-04-29 14:00:30 +00:00
|
|
|
static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|
|
|
|
DerivedMesh *dm,
|
|
|
|
int initFlags,
|
|
|
|
int axis)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2007-04-29 14:00:30 +00:00
|
|
|
int i;
|
2006-08-28 01:12:36 +00:00
|
|
|
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 (*indexMap)[2];
|
|
|
|
|
|
|
|
numVerts = numEdges = numFaces = 0;
|
|
|
|
|
|
|
|
indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
|
|
|
|
|
|
|
|
result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
|
|
|
|
|
|
|
|
for(i = 0; i < maxVerts; i++) {
|
|
|
|
MVert inMV;
|
|
|
|
MVert *mv = CDDM_get_vert(result, numVerts);
|
|
|
|
int isShared;
|
|
|
|
|
|
|
|
dm->getVert(dm, i, &inMV);
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
DM_copy_vert_data(dm, result, i, numVerts, 1);
|
|
|
|
*mv = inMV;
|
|
|
|
numVerts++;
|
|
|
|
|
|
|
|
indexMap[i][0] = numVerts - 1;
|
|
|
|
indexMap[i][1] = !isShared;
|
|
|
|
|
|
|
|
if(isShared) {
|
|
|
|
mv->co[axis] = 0;
|
|
|
|
mv->flag |= ME_VERT_MERGED;
|
|
|
|
} else {
|
|
|
|
MVert *mv2 = CDDM_get_vert(result, numVerts);
|
|
|
|
|
|
|
|
DM_copy_vert_data(dm, result, i, numVerts, 1);
|
|
|
|
*mv2 = *mv;
|
|
|
|
numVerts++;
|
|
|
|
|
|
|
|
mv2->co[axis] = -mv2->co[axis];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
static int corner_indices[4] = {2, 1, 0, 3};
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
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];
|
|
|
|
|
2007-03-18 13:46:26 +00:00
|
|
|
/* 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];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* Flip face normal */
|
|
|
|
SWAP(int, mf2->v1, mf2->v3);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
DM_swap_face_data(result, numFaces, corner_indices);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
|
|
|
|
numFaces++;
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
MEM_freeN(indexMap);
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
CDDM_lower_num_verts(result, numVerts);
|
|
|
|
CDDM_lower_num_edges(result, numEdges);
|
|
|
|
CDDM_lower_num_faces(result, numFaces);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-04-29 14:00:30 +00:00
|
|
|
static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
|
|
|
|
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, result, initFlags, 0);
|
|
|
|
}
|
|
|
|
if(mmd->flag & MOD_MIR_AXIS_Y) {
|
|
|
|
DerivedMesh *tmp = result;
|
|
|
|
result = doMirrorOnAxis(mmd, 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, result, initFlags, 2);
|
|
|
|
if(tmp != dm) tmp->release(tmp); /* free intermediate results */
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *mirrorModifier_applyModifier(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
int useRenderParams, int isFinalCalc)
|
|
|
|
{
|
|
|
|
DerivedMesh *result;
|
|
|
|
MirrorModifierData *mmd = (MirrorModifierData*) md;
|
|
|
|
|
|
|
|
result = mirrorModifier__doMirror(mmd, derivedData, 0);
|
|
|
|
|
|
|
|
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
|
2006-09-05 13:15:55 +00:00
|
|
|
#define EDGESPLIT_DEBUG_3
|
2006-08-28 01:12:36 +00:00
|
|
|
#define EDGESPLIT_DEBUG_2
|
2006-09-05 13:15:55 +00:00
|
|
|
#define EDGESPLIT_DEBUG_1
|
2006-08-28 01:12:36 +00:00
|
|
|
#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;
|
2006-09-08 01:05:57 +00:00
|
|
|
EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-08 01:05:57 +00:00
|
|
|
temd->split_angle = emd->split_angle;
|
|
|
|
temd->flags = emd->flags;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Mesh data for edgesplit operation */
|
|
|
|
typedef struct SmoothVert {
|
|
|
|
LinkNode *faces; /* all faces which use this vert */
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
int oldIndex; /* the index of the original DerivedMesh vert */
|
|
|
|
int newIndex; /* the index of the new DerivedMesh vert */
|
2006-08-28 01:12:36 +00:00
|
|
|
} 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 */
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
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 */
|
2006-08-28 01:12:36 +00:00
|
|
|
} SmoothEdge;
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
#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;
|
|
|
|
} SmoothMesh;
|
|
|
|
|
|
|
|
static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2007-03-18 14:20:24 +00:00
|
|
|
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;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2007-03-18 14:20:24 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
*copy = *edge;
|
2006-09-05 13:15:55 +00:00
|
|
|
copy->faces = NULL;
|
2007-03-18 14:20:24 +00:00
|
|
|
copy->newIndex = mesh->num_edges;
|
|
|
|
++mesh->num_edges;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_2
|
|
|
|
printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
|
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
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");
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
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;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
return mesh;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void smoothmesh_free(SmoothMesh *mesh)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2007-03-18 14:20:24 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
MEM_freeN(mesh->verts);
|
|
|
|
MEM_freeN(mesh->edges);
|
|
|
|
MEM_freeN(mesh->faces);
|
|
|
|
MEM_freeN(mesh);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2007-03-18 14:20:24 +00:00
|
|
|
int i;
|
|
|
|
SmoothVert *tmp;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
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;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2007-03-18 14:20:24 +00:00
|
|
|
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;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
2006-08-29 12:49:49 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_0
|
2006-08-28 01:12:36 +00:00
|
|
|
static void smoothmesh_print(SmoothMesh *mesh)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
DerivedMesh *dm = mesh->dm;
|
|
|
|
|
|
|
|
printf("--- SmoothMesh ---\n");
|
|
|
|
printf("--- Vertices ---\n");
|
2007-03-18 14:20:24 +00:00
|
|
|
for(i = 0; i < mesh->num_verts; i++) {
|
|
|
|
SmoothVert *vert = &mesh->verts[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
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");
|
2007-03-18 14:20:24 +00:00
|
|
|
for(i = 0; i < mesh->num_edges; i++) {
|
|
|
|
SmoothEdge *edge = &mesh->edges[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
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");
|
2007-03-18 14:20:24 +00:00
|
|
|
for(i = 0; i < mesh->num_faces; i++) {
|
|
|
|
SmoothFace *face = &mesh->faces[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
2006-08-29 12:49:49 +00:00
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
|
|
|
|
{
|
2007-03-18 14:20:24 +00:00
|
|
|
SmoothMesh *mesh;
|
2006-08-28 01:12:36 +00:00
|
|
|
EdgeHash *edges = BLI_edgehash_new();
|
|
|
|
int i;
|
|
|
|
int totvert, totedge, totface;
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
totvert = dm->getNumVerts(dm);
|
|
|
|
totedge = dm->getNumEdges(dm);
|
|
|
|
totface = dm->getNumFaces(dm);
|
|
|
|
|
|
|
|
mesh = smoothmesh_new(totvert, totedge, totface,
|
|
|
|
totvert, totedge, totface);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
mesh->dm = dm;
|
|
|
|
|
|
|
|
for(i = 0; i < totvert; i++) {
|
2007-03-18 14:20:24 +00:00
|
|
|
SmoothVert *vert = &mesh->verts[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
vert->oldIndex = vert->newIndex = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i = 0; i < totedge; i++) {
|
2007-03-18 14:20:24 +00:00
|
|
|
SmoothEdge *edge = &mesh->edges[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
MEdge med;
|
|
|
|
|
|
|
|
dm->getEdge(dm, i, &med);
|
2007-03-18 14:20:24 +00:00
|
|
|
edge->verts[0] = &mesh->verts[med.v1];
|
|
|
|
edge->verts[1] = &mesh->verts[med.v2];
|
2006-08-28 01:12:36 +00:00
|
|
|
edge->oldIndex = edge->newIndex = i;
|
|
|
|
edge->flag = med.flag;
|
2007-03-18 14:20:24 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
BLI_edgehash_insert(edges, med.v1, med.v2, edge);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i = 0; i < totface; i++) {
|
2007-03-18 14:20:24 +00:00
|
|
|
SmoothFace *face = &mesh->faces[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
|
|
|
CalcNormFloat4(v1.co, v2.co, v3.co, v4.co, face->normal);
|
|
|
|
} 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;
|
|
|
|
CalcNormFloat(v1.co, v2.co, v3.co, face->normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2007-03-18 14:20:24 +00:00
|
|
|
mesh->num_verts,
|
|
|
|
mesh->num_edges,
|
|
|
|
mesh->num_faces);
|
2006-08-28 01:12:36 +00:00
|
|
|
MVert *new_verts = CDDM_get_verts(result);
|
|
|
|
MEdge *new_edges = CDDM_get_edges(result);
|
|
|
|
MFace *new_faces = CDDM_get_faces(result);
|
2007-03-18 14:20:24 +00:00
|
|
|
int i;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
for(i = 0; i < mesh->num_verts; ++i) {
|
|
|
|
SmoothVert *vert = &mesh->verts[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
for(i = 0; i < mesh->num_edges; ++i) {
|
|
|
|
SmoothEdge *edge = &mesh->edges[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
for(i = 0; i < mesh->num_faces; ++i) {
|
|
|
|
SmoothFace *face = &mesh->faces[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* 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];
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* returns a face attached to the given edge which is not the given face.
|
|
|
|
* returns NULL if no other faces use this edge.
|
2006-08-28 01:12:36 +00:00
|
|
|
*/
|
2006-09-05 13:15:55 +00:00
|
|
|
static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
|
|
|
LinkNode *node;
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
for(node = edge->faces; node != NULL; node = node->next)
|
|
|
|
if(node->link != face) return node->link;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
return NULL;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
#if 0
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|
2006-09-05 13:15:55 +00:00
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2006-08-29 12:49:49 +00:00
|
|
|
#if 0 /* this is no longer used, it should possibly be removed */
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|
2006-08-29 12:49:49 +00:00
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* 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
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2006-09-05 13:15:55 +00:00
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2006-08-29 12:49:49 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_0
|
2006-08-28 01:12:36 +00:00
|
|
|
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);
|
|
|
|
}
|
2006-08-29 12:49:49 +00:00
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_3
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_3
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_3
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_3
|
2006-08-28 01:12:36 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
static int edge_is_loose(SmoothEdge *edge)
|
|
|
|
{
|
|
|
|
return !(edge->faces && edge->faces->next);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static int edge_is_sharp(SmoothEdge *edge, int flags,
|
|
|
|
float threshold)
|
|
|
|
{
|
2006-09-05 13:15:55 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_1
|
|
|
|
printf("edge %d: ", edge->newIndex);
|
|
|
|
#endif
|
2007-03-18 14:20:24 +00:00
|
|
|
if(edge->flag & ME_SHARP) {
|
|
|
|
/* edge can only be sharp if it has at least 2 faces */
|
|
|
|
if(!edge_is_loose(edge)) {
|
2006-09-05 13:15:55 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_1
|
|
|
|
printf("sharp\n");
|
|
|
|
#endif
|
|
|
|
return 1;
|
2007-03-18 14:20:24 +00:00
|
|
|
} else {
|
|
|
|
/* edge is loose, so it can't be sharp */
|
|
|
|
edge->flag &= ~ME_SHARP;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
#ifdef EDGESPLIT_DEBUG_1
|
|
|
|
printf("not sharp\n");
|
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* 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)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2006-09-05 13:15:55 +00:00
|
|
|
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);
|
2006-08-28 01:12:36 +00:00
|
|
|
#endif
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* get a face on which to start */
|
|
|
|
if(edge->faces) face = edge->faces->link;
|
|
|
|
else return NULL;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* record this edge as visited */
|
|
|
|
BLI_linklist_prepend(&visited_edges, edge);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* get the next edge */
|
|
|
|
edge2 = other_edge(face, vert, edge);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* record this face as visited */
|
|
|
|
if(visited_faces)
|
|
|
|
BLI_linklist_prepend(visited_faces, face);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* 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
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2006-09-05 13:15:55 +00:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* 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;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
BLI_linklist_free(visited_edges, NULL);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
#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);
|
2006-08-28 01:12:36 +00:00
|
|
|
#endif
|
2006-09-05 13:15:55 +00:00
|
|
|
return edge2;
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
static void split_single_vert(SmoothVert *vert, SmoothFace *face,
|
|
|
|
SmoothMesh *mesh)
|
|
|
|
{
|
|
|
|
SmoothVert *copy_vert;
|
|
|
|
ReplaceData repdata;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
copy_vert = smoothvert_copy(vert, mesh);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
repdata.find = vert;
|
|
|
|
repdata.replace = copy_vert;
|
2006-09-05 13:15:55 +00:00
|
|
|
face_replace_vert(face, &repdata);
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
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);
|
2006-08-28 01:12:36 +00:00
|
|
|
#endif
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
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);
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
BLI_linklist_free(visited_faces, NULL);
|
|
|
|
#ifdef EDGESPLIT_DEBUG_1
|
|
|
|
printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
|
|
|
|
edge->newIndex, vert->newIndex);
|
2006-08-28 01:12:36 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2006-09-05 13:15:55 +00:00
|
|
|
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
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
|
|
|
|
mesh->threshold, mesh->flags);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
if(!edge2) {
|
|
|
|
/* didn't find a sharp or loose edge, so try the other vert */
|
|
|
|
vert2 = other_vert(edge, vert);
|
|
|
|
propagate_split(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;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* 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)
|
2006-08-28 01:12:36 +00:00
|
|
|
*/
|
2006-09-05 13:15:55 +00:00
|
|
|
repdata.find = vert;
|
|
|
|
repdata.replace = vert2;
|
|
|
|
BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
/* all copying and replacing is done; the mesh should be consistent.
|
|
|
|
* now propagate the split to the vertices at either end
|
|
|
|
*/
|
|
|
|
propagate_split(copy_edge, other_vert(copy_edge, vert2), mesh);
|
|
|
|
propagate_split(copy_edge2, other_vert(copy_edge2, vert2), mesh);
|
|
|
|
|
|
|
|
if(smoothedge_has_vert(edge, vert))
|
|
|
|
propagate_split(edge, vert, mesh);
|
|
|
|
} else {
|
|
|
|
/* edge2 is loose */
|
|
|
|
SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
|
|
|
|
SmoothVert *vert2;
|
|
|
|
|
|
|
|
/* replace edge with its copy in visited_faces */
|
2006-08-28 01:12:36 +00:00
|
|
|
repdata.find = edge;
|
|
|
|
repdata.replace = copy_edge;
|
2006-09-05 13:15:55 +00:00
|
|
|
BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
propagate_split(copy_edge, other_vert(copy_edge, vert2), mesh);
|
|
|
|
|
|
|
|
if(smoothedge_has_vert(edge, vert))
|
|
|
|
propagate_split(edge, vert, mesh);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2006-09-05 13:15:55 +00:00
|
|
|
|
|
|
|
BLI_linklist_free(visited_faces, NULL);
|
|
|
|
#ifdef EDGESPLIT_DEBUG_1
|
|
|
|
printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
|
|
|
|
edge->newIndex, vert->newIndex);
|
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
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 = MTC_dot3Float(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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
|
|
|
|
{
|
|
|
|
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 */
|
2006-09-05 13:15:55 +00:00
|
|
|
mesh->threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
|
|
|
|
mesh->flags = flags;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
/* loop through edges, splitting sharp ones */
|
|
|
|
/* can't use an iterator here, because we'll be adding edges */
|
2007-03-18 14:20:24 +00:00
|
|
|
for(i = 0; i < mesh->num_edges; i++) {
|
|
|
|
SmoothEdge *edge = &mesh->edges[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
if(edge_is_sharp(edge, flags, mesh->threshold))
|
|
|
|
split_edge(edge, edge->verts[0], mesh);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void split_single_verts(SmoothMesh *mesh)
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
for(i = 0; i < mesh->num_faces; i++) {
|
|
|
|
SmoothFace *face = &mesh->faces[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
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;
|
2007-03-18 14:20:24 +00:00
|
|
|
int max_verts, max_edges;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-09-05 13:15:55 +00:00
|
|
|
if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
|
|
|
|
return dm;
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
/* 1. make smoothmesh with initial number of elements */
|
2006-08-28 01:12:36 +00:00
|
|
|
mesh = smoothmesh_from_derivedmesh(dm);
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
/* 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_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);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
#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
|
2006-09-05 13:15:55 +00:00
|
|
|
#if 1
|
2006-08-28 01:12:36 +00:00
|
|
|
split_single_verts(mesh);
|
2006-09-05 13:15:55 +00:00
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
#ifdef EDGESPLIT_DEBUG_1
|
|
|
|
printf("********** Post-vert-split **********\n");
|
|
|
|
smoothmesh_print(mesh);
|
|
|
|
#endif
|
|
|
|
|
2007-03-18 14:20:24 +00:00
|
|
|
#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
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
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);
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
CDDM_calc_normals(result);
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return result;
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *edgesplitModifier_applyModifierEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData)
|
|
|
|
{
|
|
|
|
return edgesplitModifier_applyModifier(md, ob, derivedData, 0, 1);
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* Displace */
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void displaceModifier_initData(ModifierData *md)
|
|
|
|
{
|
|
|
|
DisplaceModifierData *dmd = (DisplaceModifierData*) md;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dmd->texture = NULL;
|
|
|
|
dmd->strength = 1;
|
|
|
|
dmd->direction = MOD_DISP_DIR_NOR;
|
|
|
|
dmd->midlevel = 0.5;
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void displaceModifier_copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
|
|
|
DisplaceModifierData *dmd = (DisplaceModifierData*) md;
|
|
|
|
DisplaceModifierData *tdmd = (DisplaceModifierData*) target;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2007-06-20 05:23:31 +00:00
|
|
|
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);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-12-05 17:42:03 +00:00
|
|
|
CustomDataMask displaceModifier_requiredDataMask(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;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob,
|
|
|
|
ObjectWalkFunc walk, void *userData)
|
|
|
|
{
|
|
|
|
DisplaceModifierData *dmd = (DisplaceModifierData*) md;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
walk(userData, ob, &dmd->map_object);
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob,
|
|
|
|
IDWalkFunc walk, void *userData)
|
|
|
|
{
|
|
|
|
DisplaceModifierData *dmd = (DisplaceModifierData*) md;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
walk(userData, ob, (ID **)&dmd->texture);
|
2006-08-13 14:59:05 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc) walk, userData);
|
|
|
|
}
|
2006-08-13 14:59:05 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static int displaceModifier_isDisabled(ModifierData *md)
|
|
|
|
{
|
|
|
|
DisplaceModifierData *dmd = (DisplaceModifierData*) md;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return !dmd->texture;
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void displaceModifier_updateDepgraph(
|
|
|
|
ModifierData *md, DagForest *forest,
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2007-01-29 15:10:55 +00:00
|
|
|
static void validate_layer_name(const CustomData *data, int type, char *name)
|
|
|
|
{
|
|
|
|
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(name, data->layers[index].name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(texmapping == MOD_DISP_MAP_OBJECT) {
|
|
|
|
if(dmd->map_object)
|
|
|
|
Mat4Invert(dmd->map_object->imat, dmd->map_object->obmat);
|
|
|
|
else /* if there is no map object, default to local */
|
|
|
|
texmapping = MOD_DISP_MAP_LOCAL;
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* UVs need special handling, since they come from faces */
|
|
|
|
if(texmapping == MOD_DISP_MAP_UV) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
if(dm->getFaceDataArray(dm, CD_MTFACE)) {
|
|
|
|
MFace *mface = dm->getFaceArray(dm);
|
2006-08-28 01:12:36 +00:00
|
|
|
MFace *mf;
|
|
|
|
char *done = MEM_callocN(sizeof(*done) * numVerts,
|
|
|
|
"get_texture_coords done");
|
2007-01-29 15:10:55 +00:00
|
|
|
int numFaces = dm->getNumFaces(dm);
|
|
|
|
MTFace *tf;
|
|
|
|
|
|
|
|
validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name);
|
|
|
|
|
|
|
|
tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
|
|
|
|
dmd->uvlayer_name);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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;
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
MEM_freeN(done);
|
|
|
|
return;
|
|
|
|
} else /* if there are no UVs, default to local */
|
|
|
|
texmapping = MOD_DISP_MAP_LOCAL;
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
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);
|
|
|
|
Mat4MulVecfl(ob->obmat, *texco);
|
|
|
|
break;
|
|
|
|
case MOD_DISP_MAP_OBJECT:
|
|
|
|
VECCOPY(*texco, *co);
|
|
|
|
Mat4MulVecfl(ob->obmat, *texco);
|
|
|
|
Mat4MulVecfl(dmd->map_object->imat, *texco);
|
|
|
|
break;
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-29 00:50:00 +00:00
|
|
|
static void get_texture_value(Tex *texture, float *tex_co, TexResult *texres)
|
|
|
|
{
|
|
|
|
int result_type;
|
|
|
|
|
|
|
|
result_type = multitex_ext(texture, tex_co, NULL,
|
|
|
|
NULL, 1, texres);
|
|
|
|
|
|
|
|
/* if the texture gave an RGB value, we assume it didn't give a valid
|
2006-11-20 14:23:41 +00:00
|
|
|
* intensity, so calculate one (formula from do_material_tex).
|
|
|
|
* if the texture didn't give an RGB value, copy the intensity across
|
2006-08-29 00:50:00 +00:00
|
|
|
*/
|
|
|
|
if(result_type & TEX_RGB)
|
|
|
|
texres->tin = (0.35 * texres->tr + 0.45 * texres->tg
|
|
|
|
+ 0.2 * texres->tb);
|
2006-11-20 14:23:41 +00:00
|
|
|
else
|
|
|
|
texres->tr = texres->tg = texres->tb = texres->tin;
|
2006-08-29 00:50:00 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* dm must be a CDDerivedMesh */
|
|
|
|
static void displaceModifier_do(
|
|
|
|
DisplaceModifierData *dmd, Object *ob,
|
|
|
|
DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
|
2006-03-01 15:30:10 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
int i;
|
|
|
|
MVert *mvert;
|
|
|
|
MDeformVert *dvert = NULL;
|
|
|
|
int defgrp_index;
|
|
|
|
float (*tex_co)[3];
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(!dmd->texture) return;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
defgrp_index = -1;
|
|
|
|
|
|
|
|
if(dmd->defgrp_name[0]) {
|
|
|
|
bDeformGroup *def;
|
|
|
|
for(i = 0, def = ob->defbase.first; def; def = def->next, i++) {
|
|
|
|
if(!strcmp(def->name, dmd->defgrp_name)) {
|
|
|
|
defgrp_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
mvert = CDDM_get_verts(dm);
|
|
|
|
if(defgrp_index >= 0)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
2006-11-20 14:23:41 +00:00
|
|
|
float delta = 0, strength = dmd->strength;
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
2006-08-29 00:50:00 +00:00
|
|
|
get_texture_value(dmd->texture, tex_co[i], &texres);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
delta = texres.tin - dmd->midlevel;
|
|
|
|
|
2006-11-20 14:23:41 +00:00
|
|
|
if(def_weight) strength *= def_weight->weight;
|
|
|
|
|
|
|
|
delta *= strength;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
switch(dmd->direction) {
|
|
|
|
case MOD_DISP_DIR_X:
|
2006-11-20 14:23:41 +00:00
|
|
|
vertexCos[i][0] += delta;
|
2006-08-28 01:12:36 +00:00
|
|
|
break;
|
|
|
|
case MOD_DISP_DIR_Y:
|
2006-11-20 14:23:41 +00:00
|
|
|
vertexCos[i][1] += delta;
|
2006-08-28 01:12:36 +00:00
|
|
|
break;
|
|
|
|
case MOD_DISP_DIR_Z:
|
2006-11-20 14:23:41 +00:00
|
|
|
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;
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
MEM_freeN(tex_co);
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void displaceModifier_deformVerts(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
float (*vertexCos)[3], int numVerts)
|
2006-03-01 15:30:10 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *dm;
|
|
|
|
|
|
|
|
if(derivedData) dm = CDDM_copy(derivedData);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
|
2006-11-04 14:22:58 +00:00
|
|
|
else return;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
CDDM_apply_vert_coords(dm, vertexCos);
|
|
|
|
CDDM_calc_normals(dm);
|
|
|
|
|
|
|
|
displaceModifier_do((DisplaceModifierData *)md, ob, dm,
|
|
|
|
vertexCos, numVerts);
|
|
|
|
|
|
|
|
dm->release(dm);
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void displaceModifier_deformVertsEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
2006-03-01 15:30:10 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *dm;
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(derivedData) dm = CDDM_copy(derivedData);
|
|
|
|
else dm = CDDM_from_editmesh(editData, ob->data);
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
CDDM_apply_vert_coords(dm, vertexCos);
|
|
|
|
CDDM_calc_normals(dm);
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
displaceModifier_do((DisplaceModifierData *)md, ob, dm,
|
|
|
|
vertexCos, numVerts);
|
2006-03-01 15:30:10 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dm->release(dm);
|
2006-03-01 15:30:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* UVProject */
|
|
|
|
/* UV Project modifier: Generates UVs projected from an object
|
|
|
|
*/
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void uvprojectModifier_initData(ModifierData *md)
|
2005-07-20 07:11:26 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
UVProjectModifierData *umd = (UVProjectModifierData*) md;
|
|
|
|
int i;
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
|
|
|
|
umd->projectors[i] = NULL;
|
|
|
|
umd->image = NULL;
|
2007-01-29 15:10:55 +00:00
|
|
|
umd->flags = 0;
|
2006-08-28 01:12:36 +00:00
|
|
|
umd->num_projectors = 1;
|
2006-11-22 15:09:41 +00:00
|
|
|
umd->aspectx = umd->aspecty = 1.0f;
|
2005-07-20 07:11:26 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target)
|
2005-07-27 20:16:41 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
UVProjectModifierData *umd = (UVProjectModifierData*) md;
|
|
|
|
UVProjectModifierData *tumd = (UVProjectModifierData*) target;
|
|
|
|
int i;
|
2005-07-27 20:16:41 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
2006-11-22 15:09:41 +00:00
|
|
|
tumd->aspectx = umd->aspectx;
|
|
|
|
tumd->aspecty = umd->aspecty;
|
2005-07-27 20:16:41 +00:00
|
|
|
}
|
|
|
|
|
2006-12-05 17:42:03 +00:00
|
|
|
CustomDataMask uvprojectModifier_requiredDataMask(ModifierData *md)
|
|
|
|
{
|
|
|
|
CustomDataMask dataMask = 0;
|
|
|
|
|
|
|
|
/* ask for UV coordinates */
|
|
|
|
dataMask |= (1 << CD_MTFACE);
|
|
|
|
|
|
|
|
return dataMask;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob,
|
|
|
|
ObjectWalkFunc walk, void *userData)
|
2005-07-20 07:11:26 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
UVProjectModifierData *umd = (UVProjectModifierData*) md;
|
|
|
|
int i;
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
|
|
|
|
walk(userData, ob, &umd->projectors[i]);
|
|
|
|
}
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void uvprojectModifier_foreachIDLink(ModifierData *md, Object *ob,
|
|
|
|
IDWalkFunc walk, void *userData)
|
|
|
|
{
|
|
|
|
UVProjectModifierData *umd = (UVProjectModifierData*) md;
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
walk(userData, ob, (ID **)&umd->image);
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
uvprojectModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk,
|
|
|
|
userData);
|
|
|
|
}
|
2005-07-26 06:39:58 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void uvprojectModifier_updateDepgraph(ModifierData *md,
|
|
|
|
DagForest *forest, Object *ob, DagNode *obNode)
|
|
|
|
{
|
|
|
|
UVProjectModifierData *umd = (UVProjectModifierData*) md;
|
|
|
|
int i;
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
for(i = 0; i < umd->num_projectors; ++i) {
|
|
|
|
if(umd->projectors[i]) {
|
|
|
|
DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dag_add_relation(forest, curNode, obNode,
|
|
|
|
DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
|
2005-07-20 07:11:26 +00:00
|
|
|
}
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct Projector {
|
|
|
|
Object *ob; /* object this projector is derived from */
|
2006-11-22 15:09:41 +00:00
|
|
|
float projmat[4][4]; /* projection matrix */
|
2006-08-28 01:12:36 +00:00
|
|
|
float normal[3]; /* projector normal in world space */
|
|
|
|
} Projector;
|
|
|
|
|
|
|
|
static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
|
|
|
|
Object *ob, DerivedMesh *dm)
|
|
|
|
{
|
|
|
|
float (*coords)[3], (*co)[3];
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
MTFace *tface;
|
2006-08-28 01:12:36 +00:00
|
|
|
int i, numVerts, numFaces;
|
|
|
|
Image *image = umd->image;
|
|
|
|
MFace *mface, *mf;
|
2007-01-29 16:28:11 +00:00
|
|
|
int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
|
2006-08-28 01:12:36 +00:00
|
|
|
Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
|
|
|
|
int num_projectors = 0;
|
2006-11-22 15:09:41 +00:00
|
|
|
float aspect;
|
|
|
|
|
|
|
|
if(umd->aspecty != 0) aspect = umd->aspectx / umd->aspecty;
|
|
|
|
else aspect = 1.0f;
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
for(i = 0; i < umd->num_projectors; ++i)
|
|
|
|
if(umd->projectors[i])
|
|
|
|
projectors[num_projectors++].ob = umd->projectors[i];
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(num_projectors == 0) return dm;
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2007-01-29 15:10:55 +00:00
|
|
|
/* make sure there are UV layers available */
|
|
|
|
if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2007-01-29 15:10:55 +00:00
|
|
|
/* make sure we're using an existing layer */
|
|
|
|
validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name);
|
|
|
|
|
|
|
|
/* make sure we are not modifying the original UV layer */
|
|
|
|
tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
|
|
|
|
CD_MTFACE,
|
|
|
|
umd->uvlayer_name);
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
numVerts = dm->getNumVerts(dm);
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
coords = MEM_callocN(sizeof(*coords) * numVerts,
|
|
|
|
"uvprojectModifier_do coords");
|
|
|
|
dm->getVertCos(dm, coords);
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* convert coords to world space */
|
|
|
|
for(i = 0, co = coords; i < numVerts; ++i, ++co)
|
|
|
|
Mat4MulVecfl(ob->obmat, *co);
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-11-22 15:09:41 +00:00
|
|
|
/* calculate a projection matrix and normal for each projector */
|
|
|
|
for(i = 0; i < num_projectors; ++i) {
|
|
|
|
float tmpmat[4][4];
|
|
|
|
float offsetmat[4][4];
|
|
|
|
|
|
|
|
/* calculate projection matrix */
|
|
|
|
Mat4Invert(projectors[i].projmat, projectors[i].ob->obmat);
|
|
|
|
|
|
|
|
if(projectors[i].ob->type == OB_CAMERA) {
|
|
|
|
Camera *cam = (Camera *)projectors[i].ob->data;
|
|
|
|
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) {
|
2007-01-26 21:06:49 +00:00
|
|
|
xmax = 0.5f * pixsize;
|
2006-11-22 15:09:41 +00:00
|
|
|
ymax = xmax / aspect;
|
|
|
|
} else {
|
|
|
|
ymax = 0.5f * pixsize;
|
|
|
|
xmax = ymax * aspect;
|
|
|
|
}
|
|
|
|
xmin = -xmax;
|
|
|
|
ymin = -ymax;
|
|
|
|
|
|
|
|
i_window(xmin, xmax, ymin, ymax,
|
|
|
|
cam->clipsta, cam->clipend, perspmat);
|
|
|
|
Mat4MulMat4(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;
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-11-22 15:09:41 +00:00
|
|
|
i_ortho(xmin, xmax, ymin, ymax,
|
|
|
|
cam->clipsta, cam->clipend, orthomat);
|
|
|
|
Mat4MulMat4(tmpmat, projectors[i].projmat, orthomat);
|
2005-07-20 07:11:26 +00:00
|
|
|
}
|
2006-11-22 15:09:41 +00:00
|
|
|
} else {
|
|
|
|
Mat4CpyMat4(tmpmat, projectors[i].projmat);
|
2005-07-20 07:11:26 +00:00
|
|
|
}
|
2006-11-22 15:09:41 +00:00
|
|
|
|
|
|
|
Mat4One(offsetmat);
|
|
|
|
Mat4MulFloat3(offsetmat[0], 0.5);
|
|
|
|
offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5;
|
|
|
|
Mat4MulMat4(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;
|
|
|
|
Mat4Mul3Vecfl(projectors[i].ob->obmat, projectors[i].normal);
|
2005-07-20 07:11:26 +00:00
|
|
|
}
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
|
2006-11-22 15:09:41 +00:00
|
|
|
/* if only one projector, project coords to UVs */
|
|
|
|
if(num_projectors == 1)
|
|
|
|
for(i = 0, co = coords; i < numVerts; ++i, ++co)
|
|
|
|
Mat4MulVec3Project(projectors[0].projmat, *co);
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
mface = dm->getFaceArray(dm);
|
2006-08-28 01:12:36 +00:00
|
|
|
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) {
|
2007-01-29 16:28:11 +00:00
|
|
|
if(override_image || !image || tface->tpage == image) {
|
2006-08-28 01:12:36 +00:00
|
|
|
if(num_projectors == 1) {
|
|
|
|
/* 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]);
|
|
|
|
CalcNormFloat4(co1, co2, co3, co4, face_no);
|
|
|
|
} else {
|
|
|
|
CalcNormFloat(co1, co2, co3, face_no);
|
|
|
|
}
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* find the projector which the face points at most directly
|
|
|
|
* (projector normal with largest dot product is best)
|
|
|
|
*/
|
|
|
|
best_dot = MTC_dot3Float(projectors[0].normal, face_no);
|
|
|
|
best_projector = &projectors[0];
|
|
|
|
|
|
|
|
for(j = 1; j < num_projectors; ++j) {
|
|
|
|
float tmp_dot = MTC_dot3Float(projectors[j].normal,
|
|
|
|
face_no);
|
|
|
|
if(tmp_dot > best_dot) {
|
|
|
|
best_dot = tmp_dot;
|
|
|
|
best_projector = &projectors[j];
|
|
|
|
}
|
|
|
|
}
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2006-11-22 15:09:41 +00:00
|
|
|
Mat4MulVec3Project(best_projector->projmat, co1);
|
|
|
|
Mat4MulVec3Project(best_projector->projmat, co2);
|
|
|
|
Mat4MulVec3Project(best_projector->projmat, co3);
|
2006-08-28 01:12:36 +00:00
|
|
|
if(mf->v4)
|
2006-11-22 15:09:41 +00:00
|
|
|
Mat4MulVec3Project(best_projector->projmat, co4);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
/* 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];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2007-01-29 16:28:11 +00:00
|
|
|
if(override_image) {
|
2006-08-28 01:12:36 +00:00
|
|
|
tface->mode = TF_TEX;
|
2007-01-29 16:28:11 +00:00
|
|
|
tface->tpage = image;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
MEM_freeN(coords);
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return dm;
|
2005-08-07 05:42:03 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *uvprojectModifier_applyModifier(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
int useRenderParams, int isFinalCalc)
|
2005-08-07 05:42:03 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *result;
|
|
|
|
UVProjectModifierData *umd = (UVProjectModifierData*) md;
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
result = uvprojectModifier_do(umd, ob, derivedData);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return result;
|
|
|
|
}
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *uvprojectModifier_applyModifierEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData)
|
|
|
|
{
|
|
|
|
return uvprojectModifier_applyModifier(md, ob, derivedData, 0, 1);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
2005-07-26 02:44:59 +00:00
|
|
|
/* Decimate */
|
|
|
|
|
|
|
|
static void decimateModifier_initData(ModifierData *md)
|
|
|
|
{
|
|
|
|
DecimateModifierData *dmd = (DecimateModifierData*) md;
|
|
|
|
|
|
|
|
dmd->percent = 1.0;
|
|
|
|
}
|
|
|
|
|
2005-09-24 16:02:56 +00:00
|
|
|
static void decimateModifier_copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
|
|
|
DecimateModifierData *dmd = (DecimateModifierData*) md;
|
|
|
|
DecimateModifierData *tdmd = (DecimateModifierData*) target;
|
|
|
|
|
|
|
|
tdmd->percent = dmd->percent;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *decimateModifier_applyModifier(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
int useRenderParams, int isFinalCalc)
|
2005-07-26 02:44:59 +00:00
|
|
|
{
|
|
|
|
DecimateModifierData *dmd = (DecimateModifierData*) md;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
DerivedMesh *dm = derivedData, *result = NULL;
|
2005-07-26 02:44:59 +00:00
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
LOD_Decimation_Info lod;
|
|
|
|
int totvert, totface;
|
|
|
|
int a, numTris;
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
mvert = dm->getVertArray(dm);
|
|
|
|
mface = dm->getFaceArray(dm);
|
|
|
|
totvert = dm->getNumVerts(dm);
|
|
|
|
totface = dm->getNumFaces(dm);
|
2005-07-26 02:44:59 +00:00
|
|
|
|
|
|
|
numTris = 0;
|
|
|
|
for (a=0; a<totface; a++) {
|
|
|
|
MFace *mf = &mface[a];
|
- added mesh_strip_loose_faces, works in conjunction with make_edges
to get rid of faces with MFace.v3==0
- change all Mesh's to have ->medge now. This is forced by make_edges
on readfile, and in the various exotic important routines, and on
conversion back in python.
- make python NMesh structure always have medges now (needs testing)
- with above two changes it is guarenteed that mf->v3 is never ==0
in main blender code (i.e., all MFace's are actually triangles
or quads) and so I went through and removed all the historic tests
to deal with MFace.v3==0. Equals lots of deleting, I am in heaven!
- removed MEdge edcode flag, no longer needed
- added experimental replacement for edge flag system
Still are some inconsistencies in FACESELECT mode edge drawing to
be ironed out.
NOTE: This commit adds an experimental edge flag calc system, based
on 10-seconds-of-thought algorithm by yours truly. Would appreciate
feedback on how this system works, esp compared to old one and esp
on complex or interesting models.
To Use: New system is enabled by setting G.rt to a value between
1 and 1000 (Value of 0 uses old system). Value 1000 is reserved for
"auto" edge, which is more or less identical to old system but also
makes sure that at least 10% of edges are drawn (solves errors for
super subdivided meshes). Values between 1 and 999 act as percent
(out of 1000) of edges that should be drawn, starting with "most
interesting" edges first. Please try it and comment!
2005-08-21 07:19:20 +00:00
|
|
|
numTris++;
|
|
|
|
if (mf->v4) numTris++;
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(numTris<3) {
|
2006-08-28 01:12:36 +00:00
|
|
|
modifier_setError(md,
|
|
|
|
"There must be more than 3 input faces (triangles).");
|
2005-08-04 07:25:43 +00:00
|
|
|
goto exit;
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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");
|
2005-07-26 23:38:26 +00:00
|
|
|
lod.vertex_num= totvert;
|
2005-07-26 02:44:59 +00:00
|
|
|
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];
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
VECCOPY(vbCo, mv->co);
|
2005-07-26 02:44:59 +00:00
|
|
|
|
|
|
|
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];
|
- added mesh_strip_loose_faces, works in conjunction with make_edges
to get rid of faces with MFace.v3==0
- change all Mesh's to have ->medge now. This is forced by make_edges
on readfile, and in the various exotic important routines, and on
conversion back in python.
- make python NMesh structure always have medges now (needs testing)
- with above two changes it is guarenteed that mf->v3 is never ==0
in main blender code (i.e., all MFace's are actually triangles
or quads) and so I went through and removed all the historic tests
to deal with MFace.v3==0. Equals lots of deleting, I am in heaven!
- removed MEdge edcode flag, no longer needed
- added experimental replacement for edge flag system
Still are some inconsistencies in FACESELECT mode edge drawing to
be ironed out.
NOTE: This commit adds an experimental edge flag calc system, based
on 10-seconds-of-thought algorithm by yours truly. Would appreciate
feedback on how this system works, esp compared to old one and esp
on complex or interesting models.
To Use: New system is enabled by setting G.rt to a value between
1 and 1000 (Value of 0 uses old system). Value 1000 is reserved for
"auto" edge, which is more or less identical to old system but also
makes sure that at least 10% of edges are drawn (solves errors for
super subdivided meshes). Values between 1 and 999 act as percent
(out of 1000) of edges that should be drawn, starting with "most
interesting" edges first. Please try it and comment!
2005-08-21 07:19:20 +00:00
|
|
|
int *tri = &lod.triangle_index_buffer[3*numTris++];
|
|
|
|
tri[0]= mf->v1;
|
|
|
|
tri[1]= mf->v2;
|
|
|
|
tri[2]= mf->v3;
|
2005-07-26 02:44:59 +00:00
|
|
|
|
- added mesh_strip_loose_faces, works in conjunction with make_edges
to get rid of faces with MFace.v3==0
- change all Mesh's to have ->medge now. This is forced by make_edges
on readfile, and in the various exotic important routines, and on
conversion back in python.
- make python NMesh structure always have medges now (needs testing)
- with above two changes it is guarenteed that mf->v3 is never ==0
in main blender code (i.e., all MFace's are actually triangles
or quads) and so I went through and removed all the historic tests
to deal with MFace.v3==0. Equals lots of deleting, I am in heaven!
- removed MEdge edcode flag, no longer needed
- added experimental replacement for edge flag system
Still are some inconsistencies in FACESELECT mode edge drawing to
be ironed out.
NOTE: This commit adds an experimental edge flag calc system, based
on 10-seconds-of-thought algorithm by yours truly. Would appreciate
feedback on how this system works, esp compared to old one and esp
on complex or interesting models.
To Use: New system is enabled by setting G.rt to a value between
1 and 1000 (Value of 0 uses old system). Value 1000 is reserved for
"auto" edge, which is more or less identical to old system but also
makes sure that at least 10% of edges are drawn (solves errors for
super subdivided meshes). Values between 1 and 999 act as percent
(out of 1000) of edges that should be drawn, starting with "most
interesting" edges first. Please try it and comment!
2005-08-21 07:19:20 +00:00
|
|
|
if(mf->v4) {
|
|
|
|
tri = &lod.triangle_index_buffer[3*numTris++];
|
2005-07-26 02:44:59 +00:00
|
|
|
tri[0]= mf->v1;
|
- added mesh_strip_loose_faces, works in conjunction with make_edges
to get rid of faces with MFace.v3==0
- change all Mesh's to have ->medge now. This is forced by make_edges
on readfile, and in the various exotic important routines, and on
conversion back in python.
- make python NMesh structure always have medges now (needs testing)
- with above two changes it is guarenteed that mf->v3 is never ==0
in main blender code (i.e., all MFace's are actually triangles
or quads) and so I went through and removed all the historic tests
to deal with MFace.v3==0. Equals lots of deleting, I am in heaven!
- removed MEdge edcode flag, no longer needed
- added experimental replacement for edge flag system
Still are some inconsistencies in FACESELECT mode edge drawing to
be ironed out.
NOTE: This commit adds an experimental edge flag calc system, based
on 10-seconds-of-thought algorithm by yours truly. Would appreciate
feedback on how this system works, esp compared to old one and esp
on complex or interesting models.
To Use: New system is enabled by setting G.rt to a value between
1 and 1000 (Value of 0 uses old system). Value 1000 is reserved for
"auto" edge, which is more or less identical to old system but also
makes sure that at least 10% of edges are drawn (solves errors for
super subdivided meshes). Values between 1 and 999 act as percent
(out of 1000) of edges that should be drawn, starting with "most
interesting" edges first. Please try it and comment!
2005-08-21 07:19:20 +00:00
|
|
|
tri[1]= mf->v3;
|
|
|
|
tri[2]= mf->v4;
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-11-21 16:21:03 +00:00
|
|
|
if(lod.vertex_num>2) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
result = CDDM_new(lod.vertex_num, 0, lod.face_num);
|
|
|
|
dmd->faceCount = lod.face_num;
|
2005-11-21 16:21:03 +00:00
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
else
|
|
|
|
result = CDDM_new(lod.vertex_num, 0, 0);
|
|
|
|
|
|
|
|
mvert = CDDM_get_verts(result);
|
2005-07-26 02:44:59 +00:00
|
|
|
for(a=0; a<lod.vertex_num; a++) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
MVert *mv = &mvert[a];
|
2005-07-26 02:44:59 +00:00
|
|
|
float *vbCo = &lod.vertex_buffer[a*3];
|
|
|
|
|
|
|
|
VECCOPY(mv->co, vbCo);
|
|
|
|
}
|
|
|
|
|
2005-11-21 16:21:03 +00:00
|
|
|
if(lod.vertex_num>2) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
mface = CDDM_get_faces(result);
|
2005-11-21 16:21:03 +00:00
|
|
|
for(a=0; a<lod.face_num; a++) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
MFace *mf = &mface[a];
|
2005-11-21 16:21:03 +00:00
|
|
|
int *tri = &lod.triangle_index_buffer[a*3];
|
|
|
|
mf->v1 = tri[0];
|
|
|
|
mf->v2 = tri[1];
|
|
|
|
mf->v3 = tri[2];
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
test_index_face(mf, NULL, 0, 3);
|
2005-11-21 16:21:03 +00:00
|
|
|
}
|
2005-08-23 02:29:22 +00:00
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
|
|
|
CDDM_calc_edges(result);
|
|
|
|
CDDM_calc_normals(result);
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
else
|
2005-08-04 07:25:43 +00:00
|
|
|
modifier_setError(md, "Out of memory.");
|
2005-07-26 02:44:59 +00:00
|
|
|
|
|
|
|
LOD_FreeDecimationData(&lod);
|
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
else
|
2005-08-04 07:25:43 +00:00
|
|
|
modifier_setError(md, "Non-manifold mesh as input.");
|
2005-07-26 02:44:59 +00:00
|
|
|
|
|
|
|
MEM_freeN(lod.vertex_buffer);
|
|
|
|
MEM_freeN(lod.vertex_normal_buffer);
|
|
|
|
MEM_freeN(lod.triangle_index_buffer);
|
|
|
|
|
2005-08-04 07:25:43 +00:00
|
|
|
exit:
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
return result;
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
|
2007-04-29 18:13:55 +00:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
int smoothModifier_isDisabled(ModifierData *md)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomDataMask smoothModifier_requiredDataMask(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 = CDDM_get_edges(dm);
|
|
|
|
numDMEdges = dm->getNumEdges(dm);
|
|
|
|
|
|
|
|
defgrp_index = -1;
|
|
|
|
|
|
|
|
if (smd->defgrp_name[0]) {
|
|
|
|
bDeformGroup *def;
|
|
|
|
|
|
|
|
for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
|
|
|
|
if (!strcmp(def->name, smd->defgrp_name)) {
|
|
|
|
defgrp_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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]++;
|
|
|
|
VecAddf(v1, v1, fvec);
|
|
|
|
}
|
|
|
|
if (uctmp[idx2] < 255) {
|
|
|
|
uctmp[idx2]++;
|
|
|
|
VecAddf(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)
|
|
|
|
{
|
|
|
|
DerivedMesh *dm;
|
|
|
|
|
|
|
|
if(derivedData) dm = CDDM_copy(derivedData);
|
|
|
|
else dm = CDDM_from_mesh(ob->data, ob);
|
|
|
|
|
|
|
|
CDDM_apply_vert_coords(dm, vertexCos);
|
|
|
|
CDDM_calc_normals(dm);
|
|
|
|
|
|
|
|
smoothModifier_do((SmoothModifierData *)md, ob, dm,
|
|
|
|
vertexCos, numVerts);
|
|
|
|
|
|
|
|
dm->release(dm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void smoothModifier_deformVertsEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
|
|
|
{
|
|
|
|
DerivedMesh *dm;
|
|
|
|
|
|
|
|
if(derivedData) dm = CDDM_copy(derivedData);
|
|
|
|
else dm = CDDM_from_editmesh(editData, ob->data);
|
|
|
|
|
|
|
|
CDDM_apply_vert_coords(dm, vertexCos);
|
|
|
|
CDDM_calc_normals(dm);
|
|
|
|
|
|
|
|
smoothModifier_do((SmoothModifierData *)md, ob, dm,
|
|
|
|
vertexCos, numVerts);
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
int castModifier_isDisabled(ModifierData *md)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomDataMask castModifier_requiredDataMask(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, 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 = -1;
|
|
|
|
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 */
|
|
|
|
|
2007-04-30 19:20:43 +00:00
|
|
|
if (type == MOD_CAST_TYPE_CYLINDER)
|
|
|
|
flag &= ~MOD_CAST_Z;
|
|
|
|
|
2007-04-29 18:13:55 +00:00
|
|
|
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) {
|
|
|
|
Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
|
|
|
|
Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
|
|
|
|
Mat4Invert(imat, mat);
|
|
|
|
}
|
|
|
|
|
|
|
|
Mat4Invert(ob->imat, ob->obmat);
|
|
|
|
VECCOPY(center, ctrl_ob->obmat[3]);
|
|
|
|
Mat4MulVecfl(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 */
|
|
|
|
if (cmd->defgrp_name[0]) {
|
|
|
|
bDeformGroup *def;
|
|
|
|
|
|
|
|
for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
|
|
|
|
if (!strcmp(def->name, cmd->defgrp_name)) {
|
|
|
|
defgrp_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
|
|
|
|
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
|
|
|
|
|
2007-04-30 19:20:43 +00:00
|
|
|
if(flag & MOD_CAST_SIZE_FROM_RADIUS) {
|
2007-04-29 18:13:55 +00:00
|
|
|
len = cmd->radius;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
len = cmd->size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(len <= 0) {
|
|
|
|
for (i = 0; i < numVerts; i++) {
|
|
|
|
len += VecLenf(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) {
|
|
|
|
Mat4MulVecfl(mat, tmp_co);
|
|
|
|
} else {
|
|
|
|
VecSubf(tmp_co, tmp_co, center);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VECCOPY(vec, tmp_co);
|
|
|
|
|
|
|
|
if (type == MOD_CAST_TYPE_CYLINDER)
|
|
|
|
vec[2] = 0.0f;
|
|
|
|
|
|
|
|
if (has_radius) {
|
|
|
|
if (VecLength(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(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];
|
2007-04-30 19:20:43 +00:00
|
|
|
if (flag & MOD_CAST_Z)
|
2007-04-29 18:13:55 +00:00
|
|
|
tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
|
|
|
|
|
|
|
|
if(ctrl_ob) {
|
|
|
|
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
|
|
|
|
Mat4MulVecfl(imat, tmp_co);
|
|
|
|
} else {
|
|
|
|
VecAddf(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) {
|
|
|
|
Mat4MulVecfl(mat, tmp_co);
|
|
|
|
} else {
|
|
|
|
VecSubf(tmp_co, tmp_co, center);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VECCOPY(vec, tmp_co);
|
|
|
|
|
|
|
|
if (type == MOD_CAST_TYPE_CYLINDER)
|
|
|
|
vec[2] = 0.0f;
|
|
|
|
|
|
|
|
if (has_radius) {
|
|
|
|
if (VecLength(vec) > cmd->radius) continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Normalize(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];
|
2007-04-30 19:20:43 +00:00
|
|
|
if (flag & MOD_CAST_Z)
|
2007-04-29 18:13:55 +00:00
|
|
|
tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
|
|
|
|
|
|
|
|
if(ctrl_ob) {
|
|
|
|
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
|
|
|
|
Mat4MulVecfl(imat, tmp_co);
|
|
|
|
} else {
|
|
|
|
VecAddf(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 = -1;
|
|
|
|
int has_radius = 0;
|
2007-04-30 19:20:43 +00:00
|
|
|
short flag;
|
2007-04-29 18:13:55 +00:00
|
|
|
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 */
|
|
|
|
if (cmd->defgrp_name[0]) {
|
|
|
|
bDeformGroup *def;
|
|
|
|
|
|
|
|
for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
|
|
|
|
if (!strcmp(def->name, cmd->defgrp_name)) {
|
|
|
|
defgrp_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
|
|
|
|
Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
|
|
|
|
Mat4Invert(imat, mat);
|
|
|
|
}
|
|
|
|
|
|
|
|
Mat4Invert(ob->imat, ob->obmat);
|
|
|
|
VECCOPY(center, ctrl_ob->obmat[3]);
|
|
|
|
Mat4MulVecfl(ob->imat, center);
|
|
|
|
}
|
|
|
|
|
2007-04-30 19:20:43 +00:00
|
|
|
if((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
|
2007-04-29 18:13:55 +00:00
|
|
|
for(i = 0; i < 3; i++) {
|
|
|
|
min[i] = -cmd->radius;
|
|
|
|
max[i] = cmd->radius;
|
|
|
|
}
|
2007-04-30 19:20:43 +00:00
|
|
|
} else if(!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
|
2007-04-29 18:13:55 +00:00
|
|
|
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);
|
|
|
|
|
2007-04-30 19:20:43 +00:00
|
|
|
/* 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. */
|
2007-04-29 18:13:55 +00:00
|
|
|
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++) {
|
|
|
|
VecSubf(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) {
|
|
|
|
Mat4MulVecfl(mat, tmp_co);
|
|
|
|
} else {
|
|
|
|
VecSubf(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 */
|
|
|
|
VecCopyf(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) {
|
|
|
|
Mat4MulVecfl(imat, tmp_co);
|
|
|
|
} else {
|
|
|
|
VecAddf(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) {
|
|
|
|
Mat4MulVecfl(mat, tmp_co);
|
|
|
|
} else {
|
|
|
|
VecSubf(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;
|
|
|
|
|
|
|
|
VecCopyf(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) {
|
|
|
|
Mat4MulVecfl(imat, tmp_co);
|
|
|
|
} else {
|
|
|
|
VecAddf(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)
|
|
|
|
{
|
|
|
|
DerivedMesh *dm = derivedData;
|
|
|
|
CastModifierData *cmd = (CastModifierData *)md;
|
|
|
|
|
|
|
|
if (!dm && ob->type == OB_MESH)
|
|
|
|
dm = CDDM_from_mesh(ob->data, ob);
|
|
|
|
|
|
|
|
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 (!derivedData && dm) dm->release(dm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void castModifier_deformVertsEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
|
|
|
{
|
|
|
|
DerivedMesh *dm = derivedData;
|
|
|
|
CastModifierData *cmd = (CastModifierData *)md;
|
|
|
|
|
|
|
|
if (!dm && ob->type == OB_MESH)
|
|
|
|
dm = CDDM_from_editmesh(editData, ob->data);
|
|
|
|
|
|
|
|
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 (!derivedData && dm) dm->release(dm);
|
|
|
|
}
|
|
|
|
|
2005-07-26 02:44:59 +00:00
|
|
|
/* Wave */
|
|
|
|
|
|
|
|
static void waveModifier_initData(ModifierData *md)
|
|
|
|
{
|
|
|
|
WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
|
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
|
|
|
|
| MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2006-11-20 11:58:48 +00:00
|
|
|
wmd->objectcenter = NULL;
|
2007-04-29 16:15:50 +00:00
|
|
|
wmd->texture = NULL;
|
|
|
|
wmd->map_object = NULL;
|
2005-07-26 02:44:59 +00:00
|
|
|
wmd->height= 0.5f;
|
|
|
|
wmd->width= 1.5f;
|
|
|
|
wmd->speed= 0.5f;
|
|
|
|
wmd->narrow= 1.5f;
|
|
|
|
wmd->lifetime= 0.0f;
|
|
|
|
wmd->damp= 10.0f;
|
2007-04-29 16:15:50 +00:00
|
|
|
wmd->texmapping = MOD_WAV_MAP_LOCAL;
|
2007-04-30 15:20:05 +00:00
|
|
|
wmd->defgrp_name[0] = 0;
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
|
2005-07-27 20:16:41 +00:00
|
|
|
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;
|
2006-11-20 11:58:48 +00:00
|
|
|
twmd->objectcenter = wmd->objectcenter;
|
2007-04-29 16:15:50 +00:00
|
|
|
twmd->texture = wmd->texture;
|
|
|
|
twmd->map_object = wmd->map_object;
|
|
|
|
twmd->texmapping = wmd->texmapping;
|
2007-04-30 15:20:05 +00:00
|
|
|
strncpy(twmd->defgrp_name, wmd->defgrp_name, 32);
|
2005-07-27 20:16:41 +00:00
|
|
|
}
|
|
|
|
|
2005-07-26 02:44:59 +00:00
|
|
|
static int waveModifier_dependsOnTime(ModifierData *md)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2006-11-20 11:58:48 +00:00
|
|
|
static void waveModifier_foreachObjectLink(
|
2007-04-29 16:15:50 +00:00
|
|
|
ModifierData *md, Object *ob,
|
|
|
|
ObjectWalkFunc walk, void *userData)
|
2006-11-20 11:58:48 +00:00
|
|
|
{
|
|
|
|
WaveModifierData *wmd = (WaveModifierData*) md;
|
|
|
|
|
|
|
|
walk(userData, ob, &wmd->objectcenter);
|
2007-04-29 16:15:50 +00:00
|
|
|
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);
|
2006-11-20 11:58:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void waveModifier_updateDepgraph(
|
|
|
|
ModifierData *md, DagForest *forest, 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);
|
|
|
|
}
|
2007-04-29 16:15:50 +00:00
|
|
|
|
|
|
|
if(wmd->map_object) {
|
|
|
|
DagNode *curNode = dag_get_node(forest, wmd->map_object);
|
|
|
|
|
|
|
|
dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
|
|
|
|
}
|
2006-11-20 11:58:48 +00:00
|
|
|
}
|
|
|
|
|
2007-04-29 16:15:50 +00:00
|
|
|
CustomDataMask waveModifier_requiredDataMask(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);
|
|
|
|
|
2007-04-30 15:20:05 +00:00
|
|
|
/* ask for vertexgroups if we need them */
|
|
|
|
if(wmd->defgrp_name[0])
|
|
|
|
dataMask |= (1 << CD_MDEFORMVERT);
|
|
|
|
|
2007-04-29 16:15:50 +00:00
|
|
|
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)
|
|
|
|
Mat4Invert(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(dm->getFaceDataArray(dm, 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);
|
|
|
|
MTFace *tf;
|
|
|
|
|
|
|
|
validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name);
|
|
|
|
|
|
|
|
tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
|
|
|
|
wmd->uvlayer_name);
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
Mat4MulVecfl(ob->obmat, *texco);
|
|
|
|
break;
|
|
|
|
case MOD_WAV_MAP_OBJECT:
|
|
|
|
VECCOPY(*texco, *co);
|
|
|
|
Mat4MulVecfl(ob->obmat, *texco);
|
|
|
|
Mat4MulVecfl(wmd->map_object->imat, *texco);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void waveModifier_do(
|
|
|
|
WaveModifierData *md, Object *ob, DerivedMesh *dm,
|
2006-08-28 01:12:36 +00:00
|
|
|
float (*vertexCos)[3], int numVerts)
|
2005-07-26 02:44:59 +00:00
|
|
|
{
|
|
|
|
WaveModifierData *wmd = (WaveModifierData*) md;
|
2007-04-30 16:49:12 +00:00
|
|
|
MVert *mvert = NULL;
|
2007-04-30 15:20:05 +00:00
|
|
|
MDeformVert *dvert = NULL;
|
|
|
|
int defgrp_index;
|
2005-07-26 02:44:59 +00:00
|
|
|
float ctime = bsystem_time(ob, 0, (float)G.scene->r.cfra, 0.0);
|
2006-08-28 01:12:36 +00:00
|
|
|
float minfac =
|
|
|
|
(float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
|
2005-07-26 02:44:59 +00:00
|
|
|
float lifefac = wmd->height;
|
2007-06-21 11:24:42 +00:00
|
|
|
float (*tex_co)[3] = NULL;
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH)
|
|
|
|
mvert = dm->getVertArray(dm);
|
|
|
|
|
2006-11-20 11:58:48 +00:00
|
|
|
if(wmd->objectcenter){
|
|
|
|
float mat[4][4];
|
|
|
|
/* get the control object's location in local coordinates */
|
|
|
|
Mat4Invert(ob->imat, ob->obmat);
|
|
|
|
Mat4MulMat4(mat, wmd->objectcenter->obmat, ob->imat);
|
|
|
|
|
|
|
|
wmd->startx = mat[3][0];
|
|
|
|
wmd->starty = mat[3][1];
|
|
|
|
}
|
|
|
|
|
2007-04-30 15:20:05 +00:00
|
|
|
/* get the index of the deform group */
|
|
|
|
defgrp_index = -1;
|
|
|
|
|
|
|
|
if(wmd->defgrp_name[0]) {
|
|
|
|
int i;
|
|
|
|
bDeformGroup *def;
|
|
|
|
for(i = 0, def = ob->defbase.first; def; def = def->next, i++) {
|
|
|
|
if(!strcmp(def->name, wmd->defgrp_name)) {
|
|
|
|
defgrp_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(defgrp_index >= 0){
|
|
|
|
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(wmd->damp == 0) wmd->damp = 10.0f;
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(wmd->lifetime != 0.0) {
|
|
|
|
float x = ctime - wmd->timeoffs;
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(x > wmd->lifetime) {
|
|
|
|
lifefac = x - wmd->lifetime;
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(lifefac > wmd->damp) lifefac = 0.0;
|
|
|
|
else lifefac =
|
|
|
|
(float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp)));
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-29 16:15:50 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(lifefac != 0.0) {
|
2005-07-26 02:44:59 +00:00
|
|
|
int i;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
for(i = 0; i < numVerts; i++) {
|
2005-07-26 02:44:59 +00:00
|
|
|
float *co = vertexCos[i];
|
2006-08-28 01:12:36 +00:00
|
|
|
float x = co[0] - wmd->startx;
|
|
|
|
float y = co[1] - wmd->starty;
|
2006-07-02 10:36:26 +00:00
|
|
|
float amplit= 0.0f;
|
2007-04-29 16:15:50 +00:00
|
|
|
TexResult texres;
|
2007-04-30 15:20:05 +00:00
|
|
|
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;
|
|
|
|
}
|
2007-04-29 16:15:50 +00:00
|
|
|
|
|
|
|
if(wmd->texture) {
|
|
|
|
texres.nor = NULL;
|
|
|
|
get_texture_value(wmd->texture, tex_co[i], &texres);
|
|
|
|
}
|
|
|
|
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
if(wmd->flag & MOD_WAVE_X) {
|
|
|
|
if(wmd->flag & MOD_WAVE_Y) amplit = (float)sqrt(x*x + y*y);
|
2006-08-28 01:12:36 +00:00
|
|
|
else amplit = x;
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
2007-04-30 16:49:12 +00:00
|
|
|
else if(wmd->flag & MOD_WAVE_Y)
|
2006-07-02 10:36:26 +00:00
|
|
|
amplit= y;
|
2005-07-26 02:44:59 +00:00
|
|
|
|
|
|
|
/* this way it makes nice circles */
|
2006-08-28 01:12:36 +00:00
|
|
|
amplit -= (ctime - wmd->timeoffs) * wmd->speed;
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
if(wmd->flag & MOD_WAVE_CYCL) {
|
2006-08-28 01:12:36 +00:00
|
|
|
amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width)
|
|
|
|
+ wmd->width;
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* GAUSSIAN */
|
|
|
|
if(amplit > -wmd->width && amplit < wmd->width) {
|
|
|
|
amplit = amplit * wmd->narrow;
|
|
|
|
amplit = (float)(1.0 / exp(amplit * amplit) - minfac);
|
2007-04-29 16:15:50 +00:00
|
|
|
if(wmd->texture)
|
|
|
|
amplit = amplit * texres.tin;
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2007-04-30 15:20:05 +00:00
|
|
|
if(def_weight)
|
|
|
|
amplit = amplit * def_weight->weight;
|
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
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;
|
|
|
|
}
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-04-29 16:15:50 +00:00
|
|
|
|
|
|
|
if(wmd->texture) MEM_freeN(tex_co);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void waveModifier_deformVerts(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
float (*vertexCos)[3], int numVerts)
|
|
|
|
{
|
|
|
|
DerivedMesh *dm;
|
|
|
|
WaveModifierData *wmd = (WaveModifierData *)md;
|
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM))
|
|
|
|
dm = derivedData;
|
2007-04-30 15:20:05 +00:00
|
|
|
else if(derivedData) dm = derivedData;
|
2007-04-29 16:15:50 +00:00
|
|
|
else if(ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
|
|
|
|
else return;
|
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
if(wmd->flag & MOD_WAVE_NORM) {
|
|
|
|
CDDM_apply_vert_coords(dm, vertexCos);
|
|
|
|
CDDM_calc_normals(dm);
|
|
|
|
}
|
|
|
|
|
2007-04-29 16:15:50 +00:00
|
|
|
waveModifier_do(wmd, ob, dm, vertexCos, numVerts);
|
|
|
|
|
|
|
|
if(dm != derivedData) dm->release(dm);
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void waveModifier_deformVertsEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
2005-07-26 02:44:59 +00:00
|
|
|
{
|
2007-04-29 16:15:50 +00:00
|
|
|
DerivedMesh *dm;
|
|
|
|
WaveModifierData *wmd = (WaveModifierData *)md;
|
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM))
|
|
|
|
dm = derivedData;
|
2007-04-30 15:20:05 +00:00
|
|
|
else if(derivedData) dm = derivedData;
|
2007-04-29 16:15:50 +00:00
|
|
|
else dm = CDDM_from_editmesh(editData, ob->data);
|
|
|
|
|
2007-04-30 16:49:12 +00:00
|
|
|
if(wmd->flag & MOD_WAVE_NORM) {
|
|
|
|
CDDM_apply_vert_coords(dm, vertexCos);
|
|
|
|
CDDM_calc_normals(dm);
|
|
|
|
}
|
|
|
|
|
2007-04-29 16:15:50 +00:00
|
|
|
waveModifier_do(wmd, ob, dm, vertexCos, numVerts);
|
|
|
|
|
|
|
|
if(dm != derivedData) dm->release(dm);
|
2005-07-26 02:44:59 +00:00
|
|
|
}
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
/* Armature */
|
|
|
|
|
2005-11-05 21:51:12 +00:00
|
|
|
static void armatureModifier_initData(ModifierData *md)
|
|
|
|
{
|
|
|
|
ArmatureModifierData *amd = (ArmatureModifierData*) md;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP;
|
2005-11-05 21:51:12 +00:00
|
|
|
}
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
static void armatureModifier_copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
|
|
|
ArmatureModifierData *amd = (ArmatureModifierData*) md;
|
|
|
|
ArmatureModifierData *tamd = (ArmatureModifierData*) target;
|
|
|
|
|
|
|
|
tamd->object = amd->object;
|
2005-10-20 16:31:46 +00:00
|
|
|
tamd->deformflag = amd->deformflag;
|
2006-09-08 01:05:57 +00:00
|
|
|
strncpy(tamd->defgrp_name, amd->defgrp_name, 32);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
|
|
|
|
2006-12-05 17:42:03 +00:00
|
|
|
CustomDataMask armatureModifier_requiredDataMask(ModifierData *md)
|
|
|
|
{
|
|
|
|
CustomDataMask dataMask = 0;
|
|
|
|
|
|
|
|
/* ask for vertexgroups */
|
|
|
|
dataMask |= (1 << CD_MDEFORMVERT);
|
|
|
|
|
|
|
|
return dataMask;
|
|
|
|
}
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
static int armatureModifier_isDisabled(ModifierData *md)
|
|
|
|
{
|
|
|
|
ArmatureModifierData *amd = (ArmatureModifierData*) md;
|
|
|
|
|
|
|
|
return !amd->object;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void armatureModifier_foreachObjectLink(
|
|
|
|
ModifierData *md, Object *ob,
|
|
|
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
|
|
|
void *userData)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
ArmatureModifierData *amd = (ArmatureModifierData*) md;
|
|
|
|
|
|
|
|
walk(userData, ob, &amd->object);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void armatureModifier_updateDepgraph(
|
|
|
|
ModifierData *md, DagForest *forest, Object *ob,
|
|
|
|
DagNode *obNode)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
ArmatureModifierData *amd = (ArmatureModifierData*) md;
|
|
|
|
|
|
|
|
if (amd->object) {
|
|
|
|
DagNode *curNode = dag_get_node(forest, amd->object);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dag_add_relation(forest, curNode, obNode,
|
|
|
|
DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void armatureModifier_deformVerts(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
float (*vertexCos)[3], int numVerts)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
ArmatureModifierData *amd = (ArmatureModifierData*) md;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
armature_deform_verts(amd->object, ob, derivedData, vertexCos, numVerts,
|
2006-08-28 21:56:58 +00:00
|
|
|
amd->deformflag, amd->defgrp_name);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void armatureModifier_deformVertsEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
ArmatureModifierData *amd = (ArmatureModifierData*) md;
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *dm = derivedData;
|
|
|
|
|
|
|
|
if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
armature_deform_verts(amd->object, ob, dm, vertexCos, numVerts,
|
2006-08-28 21:56:58 +00:00
|
|
|
amd->deformflag, amd->defgrp_name);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
if(!derivedData) dm->release(dm);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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));
|
2006-09-08 01:05:57 +00:00
|
|
|
strncpy(thmd->name, hmd->name, 32);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
|
|
|
|
2006-12-05 17:42:03 +00:00
|
|
|
CustomDataMask hookModifier_requiredDataMask(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;
|
|
|
|
}
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void hookModifier_foreachObjectLink(
|
|
|
|
ModifierData *md, Object *ob,
|
|
|
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
|
|
|
void *userData)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
|
|
|
|
walk(userData, ob, &hmd->object);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest,
|
|
|
|
Object *ob, DagNode *obNode)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void hookModifier_deformVerts(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
float (*vertexCos)[3], int numVerts)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
float vec[3], mat[4][4];
|
|
|
|
int i;
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *dm = derivedData;
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
|
|
|
|
Mat4Invert(ob->imat, ob->obmat);
|
2006-08-28 01:12:36 +00:00
|
|
|
Mat4MulSerie(mat, ob->imat, hmd->object->obmat, hmd->parentinv,
|
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
|
2005-09-24 20:17:48 +00:00
|
|
|
/* vertex indices? */
|
|
|
|
if(hmd->indexar) {
|
2006-08-28 01:12:36 +00:00
|
|
|
for(i = 0; i < hmd->totindex; i++) {
|
2005-09-24 20:17:48 +00:00
|
|
|
int index = hmd->indexar[i];
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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) {
|
2005-09-24 20:17:48 +00:00
|
|
|
float *co = vertexCos[index];
|
|
|
|
float fac = hmd->force;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* if DerivedMesh is present and has original index data,
|
|
|
|
* use it
|
|
|
|
*/
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
if(dm && dm->getVertData(dm, 0, CD_ORIGINDEX)) {
|
2006-08-28 01:12:36 +00:00
|
|
|
int j;
|
|
|
|
int orig_index;
|
|
|
|
for(j = 0; j < numVerts; ++j) {
|
|
|
|
fac = hmd->force;
|
|
|
|
orig_index = *(int *)dm->getVertData(dm, j,
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
CD_ORIGINDEX);
|
2006-08-28 01:12:36 +00:00
|
|
|
if(orig_index == index) {
|
|
|
|
co = vertexCos[j];
|
|
|
|
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 {
|
|
|
|
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);
|
|
|
|
}
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(fac != 0.0) {
|
|
|
|
VecMat4MulVecfl(vec, mat, co);
|
|
|
|
VecLerpf(co, co, vec, fac);
|
|
|
|
}
|
2005-09-24 20:17:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
} else { /* vertex group hook */
|
2005-09-24 20:17:48 +00:00
|
|
|
bDeformGroup *curdef;
|
2006-08-28 01:12:36 +00:00
|
|
|
Mesh *me = ob->data;
|
|
|
|
int index = 0;
|
|
|
|
int use_dverts;
|
2006-10-26 23:34:44 +00:00
|
|
|
int maxVerts = 0;
|
2005-09-24 20:17:48 +00:00
|
|
|
|
|
|
|
/* find the group (weak loop-in-loop) */
|
2006-08-28 01:12:36 +00:00
|
|
|
for(curdef = ob->defbase.first; curdef; curdef = curdef->next, index++)
|
|
|
|
if(!strcmp(curdef->name, hmd->name)) break;
|
|
|
|
|
|
|
|
if(dm)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) {
|
2006-08-28 01:12:36 +00:00
|
|
|
use_dverts = 1;
|
|
|
|
maxVerts = dm->getNumVerts(dm);
|
|
|
|
} else use_dverts = 0;
|
|
|
|
else if(me->dvert) {
|
|
|
|
use_dverts = 1;
|
|
|
|
maxVerts = me->totvert;
|
|
|
|
} else use_dverts = 0;
|
2005-09-24 20:17:48 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(curdef && use_dverts) {
|
|
|
|
MDeformVert *dvert = me->dvert;
|
2005-09-24 20:17:48 +00:00
|
|
|
int i, j;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
for(i = 0; i < maxVerts; i++, dvert++) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT);
|
2006-08-28 01:12:36 +00:00
|
|
|
for(j = 0; j < dvert->totweight; j++) {
|
|
|
|
if(dvert->dw[j].def_nr == index) {
|
2005-09-24 20:17:48 +00:00
|
|
|
float fac = hmd->force*dvert->dw[j].weight;
|
|
|
|
float *co = vertexCos[i];
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(hmd->falloff != 0.0) {
|
|
|
|
float len = VecLenf(co, hmd->cent);
|
2005-09-24 20:17:48 +00:00
|
|
|
if(len > hmd->falloff) fac = 0.0;
|
2006-08-28 01:12:36 +00:00
|
|
|
else if(len > 0.0)
|
|
|
|
fac *= sqrt(1.0 - len / hmd->falloff);
|
2005-09-24 20:17:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VecMat4MulVecfl(vec, mat, co);
|
|
|
|
VecLerpf(co, co, vec, fac);
|
|
|
|
}
|
|
|
|
}
|
2005-08-10 22:25:32 +00:00
|
|
|
}
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void hookModifier_deformVertsEM(
|
|
|
|
ModifierData *md, Object *ob, EditMesh *editData,
|
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
DerivedMesh *dm = derivedData;
|
|
|
|
|
|
|
|
if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
if(!derivedData) dm->release(dm);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Softbody */
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void softbodyModifier_deformVerts(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
float (*vertexCos)[3], int numVerts)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
2005-08-15 10:30:53 +00:00
|
|
|
sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
2005-07-26 02:44:59 +00:00
|
|
|
|
2005-09-03 17:22:29 +00:00
|
|
|
/* Boolean */
|
|
|
|
|
2005-09-24 16:02:56 +00:00
|
|
|
static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
|
|
|
BooleanModifierData *bmd = (BooleanModifierData*) md;
|
|
|
|
BooleanModifierData *tbmd = (BooleanModifierData*) target;
|
|
|
|
|
|
|
|
tbmd->object = bmd->object;
|
2005-11-23 19:19:44 +00:00
|
|
|
tbmd->operation = bmd->operation;
|
2005-09-24 16:02:56 +00:00
|
|
|
}
|
|
|
|
|
2005-09-03 17:22:29 +00:00
|
|
|
static int booleanModifier_isDisabled(ModifierData *md)
|
|
|
|
{
|
|
|
|
BooleanModifierData *bmd = (BooleanModifierData*) md;
|
|
|
|
|
|
|
|
return !bmd->object;
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void booleanModifier_foreachObjectLink(
|
|
|
|
ModifierData *md, Object *ob,
|
|
|
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
|
|
|
void *userData)
|
2005-09-03 17:22:29 +00:00
|
|
|
{
|
|
|
|
BooleanModifierData *bmd = (BooleanModifierData*) md;
|
|
|
|
|
|
|
|
walk(userData, ob, &bmd->object);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void booleanModifier_updateDepgraph(
|
|
|
|
ModifierData *md, DagForest *forest, Object *ob,
|
|
|
|
DagNode *obNode)
|
2005-09-03 17:22:29 +00:00
|
|
|
{
|
|
|
|
BooleanModifierData *bmd = (BooleanModifierData*) md;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(bmd->object) {
|
2005-09-03 17:22:29 +00:00
|
|
|
DagNode *curNode = dag_get_node(forest, bmd->object);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
dag_add_relation(forest, curNode, obNode,
|
|
|
|
DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
|
2005-09-03 17:22:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static DerivedMesh *booleanModifier_applyModifier(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
int useRenderParams, int isFinalCalc)
|
|
|
|
{
|
|
|
|
// XXX doesn't handle derived data
|
2005-09-03 17:22:29 +00:00
|
|
|
BooleanModifierData *bmd = (BooleanModifierData*) md;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2005-12-19 17:21:55 +00:00
|
|
|
/* we do a quick sanity check */
|
2006-08-28 01:12:36 +00:00
|
|
|
if(((Mesh *)ob->data)->totface > 3
|
|
|
|
&& bmd->object && ((Mesh *)bmd->object->data)->totface > 3) {
|
2006-11-08 20:14:04 +00:00
|
|
|
DerivedMesh *result = NewBooleanDerivedMesh(ob, bmd->object,
|
2006-08-28 01:12:36 +00:00
|
|
|
1 + bmd->operation);
|
2006-01-01 15:41:20 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* if new mesh returned, return it; otherwise there was
|
|
|
|
* an error, so delete the modifier object */
|
|
|
|
if(result)
|
|
|
|
return result;
|
2006-01-01 15:41:20 +00:00
|
|
|
else
|
|
|
|
bmd->object = NULL;
|
2005-12-19 17:21:55 +00:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2006-01-01 15:41:20 +00:00
|
|
|
return derivedData;
|
2005-09-03 17:22:29 +00:00
|
|
|
}
|
|
|
|
|
2005-07-19 20:14:17 +00:00
|
|
|
/***/
|
|
|
|
|
|
|
|
static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
|
|
|
|
static int typeArrInit = 1;
|
|
|
|
|
2005-08-03 04:04:05 +00:00
|
|
|
ModifierTypeInfo *modifierType_getInfo(ModifierType type)
|
2005-07-19 20:14:17 +00:00
|
|
|
{
|
|
|
|
if (typeArrInit) {
|
|
|
|
ModifierTypeInfo *mti;
|
|
|
|
|
|
|
|
memset(typeArr, 0, sizeof(typeArr));
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
/* Initialize and return the appropriate type info structure,
|
|
|
|
* assumes that modifier has:
|
|
|
|
* name == typeName,
|
|
|
|
* structName == typeName + 'ModifierData'
|
|
|
|
*/
|
|
|
|
#define INIT_TYPE(typeName) \
|
2006-08-28 01:12:36 +00:00
|
|
|
(strcpy(typeArr[eModifierType_##typeName].name, #typeName), \
|
|
|
|
strcpy(typeArr[eModifierType_##typeName].structName, \
|
|
|
|
#typeName "ModifierData"), \
|
|
|
|
typeArr[eModifierType_##typeName].structSize = \
|
|
|
|
sizeof(typeName##ModifierData), \
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
&typeArr[eModifierType_##typeName])
|
|
|
|
|
2005-07-19 20:14:17 +00:00
|
|
|
mti = &typeArr[eModifierType_None];
|
|
|
|
strcpy(mti->name, "None");
|
|
|
|
strcpy(mti->structName, "ModifierData");
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti->structSize = sizeof(ModifierData);
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->type = eModifierType_None;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh
|
|
|
|
| eModifierTypeFlag_AcceptsCVs;
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->isDisabled = noneModifier_isDisabled;
|
2007-01-26 21:06:49 +00:00
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti = INIT_TYPE(Curve);
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->type = eModifierTypeType_OnlyDeform;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsCVs
|
|
|
|
| eModifierTypeFlag_SupportsEditmode;
|
2006-10-28 16:48:56 +00:00
|
|
|
mti->initData = curveModifier_initData;
|
2005-07-27 20:16:41 +00:00
|
|
|
mti->copyData = curveModifier_copyData;
|
2006-12-05 17:42:03 +00:00
|
|
|
mti->requiredDataMask = curveModifier_requiredDataMask;
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->isDisabled = curveModifier_isDisabled;
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
mti->foreachObjectLink = curveModifier_foreachObjectLink;
|
2005-07-19 23:04:34 +00:00
|
|
|
mti->updateDepgraph = curveModifier_updateDepgraph;
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->deformVerts = curveModifier_deformVerts;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
mti->deformVertsEM = curveModifier_deformVertsEM;
|
2005-07-19 20:14:17 +00:00
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti = INIT_TYPE(Lattice);
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->type = eModifierTypeType_OnlyDeform;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsCVs
|
|
|
|
| eModifierTypeFlag_SupportsEditmode;
|
2005-07-27 20:16:41 +00:00
|
|
|
mti->copyData = latticeModifier_copyData;
|
2006-12-05 17:42:03 +00:00
|
|
|
mti->requiredDataMask = latticeModifier_requiredDataMask;
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->isDisabled = latticeModifier_isDisabled;
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
mti->foreachObjectLink = latticeModifier_foreachObjectLink;
|
2005-07-19 23:04:34 +00:00
|
|
|
mti->updateDepgraph = latticeModifier_updateDepgraph;
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->deformVerts = latticeModifier_deformVerts;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
mti->deformVertsEM = latticeModifier_deformVertsEM;
|
2005-07-19 20:14:17 +00:00
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti = INIT_TYPE(Subsurf);
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->type = eModifierTypeType_Constructive;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh
|
|
|
|
| eModifierTypeFlag_SupportsMapping
|
|
|
|
| eModifierTypeFlag_SupportsEditmode
|
|
|
|
| eModifierTypeFlag_EnableInEditmode;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti->initData = subsurfModifier_initData;
|
2005-07-27 20:16:41 +00:00
|
|
|
mti->copyData = subsurfModifier_copyData;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti->freeData = subsurfModifier_freeData;
|
2005-07-19 20:14:17 +00:00
|
|
|
mti->applyModifier = subsurfModifier_applyModifier;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
mti->applyModifierEM = subsurfModifier_applyModifierEM;
|
2005-07-19 20:14:17 +00:00
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti = INIT_TYPE(Build);
|
2005-07-20 04:14:21 +00:00
|
|
|
mti->type = eModifierTypeType_Nonconstructive;
|
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti->initData = buildModifier_initData;
|
2005-07-27 20:16:41 +00:00
|
|
|
mti->copyData = buildModifier_copyData;
|
2005-07-20 04:14:21 +00:00
|
|
|
mti->dependsOnTime = buildModifier_dependsOnTime;
|
|
|
|
mti->applyModifier = buildModifier_applyModifier;
|
|
|
|
|
2006-03-01 15:30:10 +00:00
|
|
|
mti = INIT_TYPE(Array);
|
|
|
|
mti->type = eModifierTypeType_Constructive;
|
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh
|
|
|
|
| eModifierTypeFlag_SupportsMapping
|
|
|
|
| eModifierTypeFlag_SupportsEditmode
|
|
|
|
| eModifierTypeFlag_EnableInEditmode;
|
|
|
|
mti->initData = arrayModifier_initData;
|
|
|
|
mti->copyData = arrayModifier_copyData;
|
|
|
|
mti->foreachObjectLink = arrayModifier_foreachObjectLink;
|
|
|
|
mti->updateDepgraph = arrayModifier_updateDepgraph;
|
|
|
|
mti->applyModifier = arrayModifier_applyModifier;
|
|
|
|
mti->applyModifierEM = arrayModifier_applyModifierEM;
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti = INIT_TYPE(Mirror);
|
2005-07-20 07:11:26 +00:00
|
|
|
mti->type = eModifierTypeType_Constructive;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh
|
|
|
|
| eModifierTypeFlag_SupportsMapping
|
|
|
|
| eModifierTypeFlag_SupportsEditmode
|
|
|
|
| eModifierTypeFlag_EnableInEditmode;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
mti->initData = mirrorModifier_initData;
|
2005-07-27 20:16:41 +00:00
|
|
|
mti->copyData = mirrorModifier_copyData;
|
2005-07-20 07:11:26 +00:00
|
|
|
mti->applyModifier = mirrorModifier_applyModifier;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
mti->applyModifierEM = mirrorModifier_applyModifierEM;
|
2005-07-20 07:11:26 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
mti = INIT_TYPE(EdgeSplit);
|
|
|
|
mti->type = eModifierTypeType_Constructive;
|
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh
|
|
|
|
| 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(Displace);
|
2006-11-09 10:12:26 +00:00
|
|
|
mti->type = eModifierTypeType_OnlyDeform;
|
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsEditmode;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->initData = displaceModifier_initData;
|
|
|
|
mti->copyData = displaceModifier_copyData;
|
2006-12-05 17:42:03 +00:00
|
|
|
mti->requiredDataMask = displaceModifier_requiredDataMask;
|
2006-08-28 01:12:36 +00:00
|
|
|
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;
|
2006-12-05 17:42:03 +00:00
|
|
|
mti->requiredDataMask = uvprojectModifier_requiredDataMask;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->foreachObjectLink = uvprojectModifier_foreachObjectLink;
|
|
|
|
mti->foreachIDLink = uvprojectModifier_foreachIDLink;
|
|
|
|
mti->updateDepgraph = uvprojectModifier_updateDepgraph;
|
|
|
|
mti->applyModifier = uvprojectModifier_applyModifier;
|
|
|
|
mti->applyModifierEM = uvprojectModifier_applyModifierEM;
|
|
|
|
|
2005-07-26 02:44:59 +00:00
|
|
|
mti = INIT_TYPE(Decimate);
|
|
|
|
mti->type = eModifierTypeType_Nonconstructive;
|
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh;
|
|
|
|
mti->initData = decimateModifier_initData;
|
2005-09-24 16:02:56 +00:00
|
|
|
mti->copyData = decimateModifier_copyData;
|
2005-07-26 02:44:59 +00:00
|
|
|
mti->applyModifier = decimateModifier_applyModifier;
|
|
|
|
|
2007-04-29 18:13:55 +00:00
|
|
|
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->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->foreachObjectLink = castModifier_foreachObjectLink;
|
|
|
|
mti->updateDepgraph = castModifier_updateDepgraph;
|
|
|
|
mti->deformVerts = castModifier_deformVerts;
|
|
|
|
mti->deformVertsEM = castModifier_deformVertsEM;
|
|
|
|
|
2005-07-26 02:44:59 +00:00
|
|
|
mti = INIT_TYPE(Wave);
|
|
|
|
mti->type = eModifierTypeType_OnlyDeform;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsCVs
|
|
|
|
| eModifierTypeFlag_SupportsEditmode;
|
2005-07-26 02:44:59 +00:00
|
|
|
mti->initData = waveModifier_initData;
|
2005-07-27 20:16:41 +00:00
|
|
|
mti->copyData = waveModifier_copyData;
|
2005-07-26 02:44:59 +00:00
|
|
|
mti->dependsOnTime = waveModifier_dependsOnTime;
|
2007-04-29 16:15:50 +00:00
|
|
|
mti->requiredDataMask = waveModifier_requiredDataMask;
|
2006-11-20 11:58:48 +00:00
|
|
|
mti->foreachObjectLink = waveModifier_foreachObjectLink;
|
2007-04-29 16:15:50 +00:00
|
|
|
mti->foreachIDLink = waveModifier_foreachIDLink;
|
2006-11-20 11:58:48 +00:00
|
|
|
mti->updateDepgraph = waveModifier_updateDepgraph;
|
2005-07-26 02:44:59 +00:00
|
|
|
mti->deformVerts = waveModifier_deformVerts;
|
|
|
|
mti->deformVertsEM = waveModifier_deformVertsEM;
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
mti = INIT_TYPE(Armature);
|
|
|
|
mti->type = eModifierTypeType_OnlyDeform;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsCVs
|
|
|
|
| eModifierTypeFlag_SupportsEditmode;
|
2005-11-05 21:51:12 +00:00
|
|
|
mti->initData = armatureModifier_initData;
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
mti->copyData = armatureModifier_copyData;
|
2006-12-05 17:42:03 +00:00
|
|
|
mti->requiredDataMask = armatureModifier_requiredDataMask;
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
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;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsCVs
|
|
|
|
| eModifierTypeFlag_SupportsEditmode;
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
mti->initData = hookModifier_initData;
|
|
|
|
mti->copyData = hookModifier_copyData;
|
2006-12-05 17:42:03 +00:00
|
|
|
mti->requiredDataMask = hookModifier_requiredDataMask;
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
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;
|
2006-08-28 01:12:36 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsCVs
|
|
|
|
| eModifierTypeFlag_RequiresOriginalData;
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
mti->deformVerts = softbodyModifier_deformVerts;
|
|
|
|
|
2005-09-03 17:22:29 +00:00
|
|
|
mti = INIT_TYPE(Boolean);
|
|
|
|
mti->type = eModifierTypeType_Nonconstructive;
|
2006-06-28 14:02:11 +00:00
|
|
|
mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData;
|
2005-09-24 16:02:56 +00:00
|
|
|
mti->copyData = booleanModifier_copyData;
|
2005-09-03 17:22:29 +00:00
|
|
|
mti->isDisabled = booleanModifier_isDisabled;
|
|
|
|
mti->applyModifier = booleanModifier_applyModifier;
|
|
|
|
mti->foreachObjectLink = booleanModifier_foreachObjectLink;
|
|
|
|
mti->updateDepgraph = booleanModifier_updateDepgraph;
|
|
|
|
|
2005-07-19 20:14:17 +00:00
|
|
|
typeArrInit = 0;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
#undef INIT_TYPE
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (type>=0 && type<NUM_MODIFIER_TYPES && typeArr[type].name[0]!='\0') {
|
|
|
|
return &typeArr[type];
|
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
/***/
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ModifierData *modifier_new(int type)
|
|
|
|
{
|
2005-08-03 04:04:05 +00:00
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(type);
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
strcpy(md->name, mti->name);
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
md->type = type;
|
2006-08-28 01:12:36 +00:00
|
|
|
md->mode = eModifierMode_Realtime
|
|
|
|
| eModifierMode_Render | eModifierMode_Expanded;
|
2005-07-23 19:15:08 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if (mti->flags & eModifierTypeFlag_EnableInEditmode)
|
2005-07-23 19:15:08 +00:00
|
|
|
md->mode |= eModifierMode_Editmode;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
|
|
|
|
if (mti->initData) mti->initData(md);
|
|
|
|
|
|
|
|
return md;
|
|
|
|
}
|
|
|
|
|
|
|
|
void modifier_free(ModifierData *md)
|
|
|
|
{
|
2005-08-03 04:04:05 +00:00
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
|
|
|
|
if (mti->freeData) mti->freeData(md);
|
2005-08-04 07:25:43 +00:00
|
|
|
if (md->error) MEM_freeN(md->error);
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
|
|
|
|
MEM_freeN(md);
|
|
|
|
}
|
|
|
|
|
2005-07-20 04:14:21 +00:00
|
|
|
int modifier_dependsOnTime(ModifierData *md)
|
|
|
|
{
|
2005-08-03 04:04:05 +00:00
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
2005-07-20 04:14:21 +00:00
|
|
|
|
|
|
|
return mti->dependsOnTime && mti->dependsOnTime(md);
|
|
|
|
}
|
2005-07-27 20:16:41 +00:00
|
|
|
|
2005-08-03 04:04:05 +00:00
|
|
|
int modifier_supportsMapping(ModifierData *md)
|
|
|
|
{
|
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return ( (mti->flags & eModifierTypeFlag_SupportsEditmode) &&
|
2005-08-03 04:04:05 +00:00
|
|
|
( (mti->type==eModifierTypeType_OnlyDeform ||
|
2006-08-28 01:12:36 +00:00
|
|
|
(mti->flags & eModifierTypeFlag_SupportsMapping))) );
|
2005-08-03 04:04:05 +00:00
|
|
|
}
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
ModifierData *modifiers_findByType(Object *ob, ModifierType type)
|
2005-07-27 20:16:41 +00:00
|
|
|
{
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
ModifierData *md = ob->modifiers.first;
|
2005-07-27 20:16:41 +00:00
|
|
|
|
|
|
|
for (; md; md=md->next)
|
|
|
|
if (md->type==type)
|
|
|
|
break;
|
|
|
|
|
|
|
|
return md;
|
|
|
|
}
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
void modifiers_clearErrors(Object *ob)
|
2005-08-04 07:25:43 +00:00
|
|
|
{
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
ModifierData *md = ob->modifiers.first;
|
|
|
|
int qRedraw = 0;
|
2005-08-04 07:25:43 +00:00
|
|
|
|
|
|
|
for (; md; md=md->next) {
|
|
|
|
if (md->error) {
|
|
|
|
MEM_freeN(md->error);
|
|
|
|
md->error = NULL;
|
|
|
|
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
qRedraw = 1;
|
2005-08-04 07:25:43 +00:00
|
|
|
}
|
|
|
|
}
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
|
|
|
|
if (qRedraw) allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk,
|
|
|
|
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 modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData)
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
{
|
|
|
|
ModifierData *md = ob->modifiers.first;
|
|
|
|
|
|
|
|
for (; md; md=md->next) {
|
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if(mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData);
|
|
|
|
else if(mti->foreachObjectLink) {
|
|
|
|
/* each Object can masquerade as an ID, so this should be OK */
|
|
|
|
ObjectWalkFunc fp = (ObjectWalkFunc)walk;
|
|
|
|
mti->foreachObjectLink(md, ob, fp, userData);
|
|
|
|
}
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
}
|
2005-08-04 07:25:43 +00:00
|
|
|
}
|
|
|
|
|
2005-07-27 20:16:41 +00:00
|
|
|
void modifier_copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
2005-08-03 04:04:05 +00:00
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
2005-07-27 20:16:41 +00:00
|
|
|
|
|
|
|
target->mode = md->mode;
|
|
|
|
|
|
|
|
if (mti->copyData)
|
|
|
|
mti->copyData(md, target);
|
|
|
|
}
|
2005-08-04 07:25:43 +00:00
|
|
|
|
|
|
|
int modifier_couldBeCage(ModifierData *md)
|
|
|
|
{
|
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return ( (md->mode & eModifierMode_Realtime) &&
|
|
|
|
(md->mode & eModifierMode_Editmode) &&
|
2005-08-04 07:25:43 +00:00
|
|
|
(!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);
|
|
|
|
}
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* 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)
|
|
|
|
*/
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
|
2005-08-04 07:25:43 +00:00
|
|
|
{
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
ModifierData *md = ob->modifiers.first;
|
2005-08-04 07:25:43 +00:00
|
|
|
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);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
if (!(md->mode & eModifierMode_Realtime)) continue;
|
|
|
|
if (!(md->mode & eModifierMode_Editmode)) continue;
|
2005-08-04 07:25:43 +00:00
|
|
|
if (mti->isDisabled && mti->isDisabled(md)) continue;
|
2006-08-28 01:12:36 +00:00
|
|
|
if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
|
2005-08-04 07:25:43 +00:00
|
|
|
|
|
|
|
if (!modifier_supportsMapping(md))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (lastPossibleCageIndex_r) *lastPossibleCageIndex_r = i;
|
2006-08-28 01:12:36 +00:00
|
|
|
if (md->mode & eModifierMode_OnCage)
|
2005-08-04 07:25:43 +00:00
|
|
|
cageIndex = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cageIndex;
|
|
|
|
}
|
2005-08-11 02:23:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
int modifiers_isSoftbodyEnabled(Object *ob)
|
|
|
|
{
|
|
|
|
ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
|
2005-08-11 02:23:52 +00:00
|
|
|
}
|
2005-08-11 03:31:33 +00:00
|
|
|
|
2006-12-05 17:42:03 +00:00
|
|
|
LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask)
|
|
|
|
{
|
|
|
|
LinkNode *dataMasks = NULL;
|
|
|
|
LinkNode *curr, *prev;
|
|
|
|
|
|
|
|
/* build a list of modifier data requirements in reverse order */
|
|
|
|
for(; md; md = md->next) {
|
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
|
|
|
CustomDataMask mask = 0;
|
|
|
|
|
|
|
|
if(mti->requiredDataMask) mask = mti->requiredDataMask(md);
|
|
|
|
|
|
|
|
BLI_linklist_prepend(&dataMasks, (void *)mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* build the list of required data masks - each mask in the list must
|
|
|
|
* include all elements of the masks that follow it
|
|
|
|
*
|
|
|
|
* note the list is currently in reverse order, so "masks that follow it"
|
|
|
|
* actually means "masks that precede it" at the moment
|
|
|
|
*/
|
|
|
|
for(curr = dataMasks, prev = NULL; curr; prev = curr, curr = curr->next) {
|
|
|
|
if(prev) {
|
|
|
|
CustomDataMask prev_mask = (CustomDataMask)prev->link;
|
|
|
|
CustomDataMask curr_mask = (CustomDataMask)curr->link;
|
|
|
|
|
|
|
|
curr->link = (void *)(curr_mask | prev_mask);
|
|
|
|
} else {
|
|
|
|
CustomDataMask curr_mask = (CustomDataMask)curr->link;
|
|
|
|
|
|
|
|
curr->link = (void *)(curr_mask | dataMask);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reverse the list so it's in the correct order */
|
|
|
|
BLI_linklist_reverse(&dataMasks);
|
|
|
|
|
|
|
|
return dataMasks;
|
|
|
|
}
|
|
|
|
|
2005-08-11 03:31:33 +00:00
|
|
|
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;
|
2005-10-20 16:31:46 +00:00
|
|
|
amd.deformflag= ((bArmature *)(ob->parent->data))->deformflag;
|
2005-08-11 03:31:33 +00:00
|
|
|
return &amd.modifier;
|
|
|
|
} else if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) {
|
|
|
|
cmd.object = ob->parent;
|
2006-11-29 13:52:59 +00:00
|
|
|
cmd.defaxis = ob->trackflag + 1;
|
2005-08-11 03:31:33 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
/* Takes an object and returns its first selected armature, else just its
|
|
|
|
* armature
|
|
|
|
* This should work for multiple armatures per object
|
|
|
|
*/
|
2005-09-07 18:07:24 +00:00
|
|
|
Object *modifiers_isDeformedByArmature(Object *ob)
|
2005-08-22 20:24:59 +00:00
|
|
|
{
|
2005-08-22 20:25:54 +00:00
|
|
|
ModifierData *md = modifiers_getVirtualModifierList(ob);
|
2006-05-14 12:45:13 +00:00
|
|
|
ArmatureModifierData *amd= NULL;
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* return the first selected armature, this lets us use multiple armatures
|
|
|
|
*/
|
2005-08-22 20:25:54 +00:00
|
|
|
for (; md; md=md->next) {
|
2005-08-22 20:24:59 +00:00
|
|
|
if (md->type==eModifierType_Armature) {
|
2006-05-14 12:45:13 +00:00
|
|
|
amd = (ArmatureModifierData*) md;
|
2006-05-29 13:59:18 +00:00
|
|
|
if (amd->object && (amd->object->flag & SELECT))
|
2006-05-14 12:45:13 +00:00
|
|
|
return amd->object;
|
2005-08-22 20:24:59 +00:00
|
|
|
}
|
|
|
|
}
|
2006-05-14 12:45:13 +00:00
|
|
|
|
|
|
|
if (amd) /* if were still here then return the last armature */
|
|
|
|
return amd->object;
|
|
|
|
|
2005-09-07 18:07:24 +00:00
|
|
|
return NULL;
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
}
|
|
|
|
|
2006-12-23 11:56:22 +00:00
|
|
|
/* Takes an object and returns its first selected lattice, else just its
|
|
|
|
* armature
|
|
|
|
* This should work for multiple armatures per object
|
|
|
|
*/
|
|
|
|
Object *modifiers_isDeformedByLattice(Object *ob)
|
|
|
|
{
|
|
|
|
ModifierData *md = modifiers_getVirtualModifierList(ob);
|
|
|
|
LatticeModifierData *lmd= NULL;
|
|
|
|
|
|
|
|
/* return the first selected armature, this lets us use multiple armatures
|
|
|
|
*/
|
|
|
|
for (; md; md=md->next) {
|
|
|
|
if (md->type==eModifierType_Lattice) {
|
|
|
|
lmd = (LatticeModifierData*) md;
|
|
|
|
if (lmd->object && (lmd->object->flag & SELECT))
|
|
|
|
return lmd->object;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lmd) /* if were still here then return the last lattice */
|
|
|
|
return lmd->object;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-05-04 00:59:02 +00:00
|
|
|
int modifiers_usesArmature(Object *ob, bArmature *arm)
|
|
|
|
{
|
|
|
|
ModifierData *md = modifiers_getVirtualModifierList(ob);
|
|
|
|
|
|
|
|
for (; md; md=md->next) {
|
|
|
|
if (md->type==eModifierType_Armature) {
|
|
|
|
ArmatureModifierData *amd = (ArmatureModifierData*) md;
|
2006-07-05 15:59:26 +00:00
|
|
|
if (amd->object && amd->object->data==arm)
|
2006-05-04 00:59:02 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-14 14:14:32 +00:00
|
|
|
return 0;
|
2006-05-04 00:59:02 +00:00
|
|
|
}
|
|
|
|
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
int modifiers_isDeformed(Object *ob)
|
|
|
|
{
|
|
|
|
ModifierData *md = modifiers_getVirtualModifierList(ob);
|
|
|
|
|
|
|
|
for (; md; md=md->next) {
|
2005-11-30 20:22:27 +00:00
|
|
|
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;
|
|
|
|
}
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|