利用者:Apinzonf/Dev:Doc/Tutorial Modifier

提供: wiki
移動先: 案内検索

Tutorial Adding a New Modifier

In this tutorial you will learn the steps to create a new modifier in Blender.

This tutorial is focused to people with a medium level of programming in (C, C++, python), and do not know the Blender source code.

The development was done with CMake, vs2010 and windows, but should be similar to other systems like SCons and Unix.

You can read an introduction of the topic in Dev:Source/Modifiers/Adding

Directory Structure

You can read wiki document about file structure Dev:2.5/Doc/Blender_Source/Files_structure

To build blender need to select a directory we name as ANY FOLDER where you'll make the following folders.

ANY FOLDER/blender

ANY FOLDER/lib/windows

ANY FOLDER/build

Download source code from svn repository

You can read wiki documentation about set up your local repository in Dev:2.5/Doc/Building_Blender/Windows/msvc/CMake

For get Blender source code you need a svn client like svn command line or svn graphical client


Manual CMake Setup

You can download and install CMake from www.cmake.org

You can find CMake in windows Menu: CMake 2.8 -> Cmake (cmake gui)

Your CMake application should look like the picture below

CMake gui
  • In the field Where is the source code: put the direction of ANY FOLDER/blender
  • In the field Where is to build the binaries: put the direction of ANY FOLDER/build
  • Click in Configure button, in the first time appear this dialog, and you choose Visual Studio 2010
CMake gui
  • Click in Generate button

Build Blender using visual C++ 2010

After generating project files with Cmake, should appear the file ANY FOLDER/build/Bender.sln, open that file, and set Solution Configuration to Release.

Blender - Microsoft Visual Studio

In the Solution Explorer locate the project INSTALL, then right click on the project INSTALL and select the option Generate.

After completion of the compilation, you will find your own version of Blender in ANY FOLDER/build/bin/Release/blender.exe

Adding a New Modifier

In the previous steps was obtained and compiled the source code, we now need to begin to add the modifier.

This modifier will be very simple but contains all the elements to build something more complex.

In this tutorial we will create a modifier for the scaling of the mesh.

To create a new modifier in Blender, you need to modify a set of files and create several files to place our modifier algorithm.

Design the new modifier

To create a modifier "Scaling" we needs to interact with the GUI (rna_modifier.c, properties_data_modifier.py) and be able to call a modifier over a method (MOD_scaling.c) that receive the parameters of the modifier in some kind of structure (RNA_access.h, DNA_modifier_types.h, MOD_util.c).

This is the list of files to be modified and created

properties_data_modifier.py

ANY FOLDER/blender/release/scripts/startup/bl_ui/properties_data_modifier.py

You must add a new function SCALING in the class DATA_PT_modifiers. This function sets the layout of the buttons and controls in the GUI.

class DATA_PT_modifiers(ModifierButtonsPanel, Panel): 
    ...
    def SCALING(self, layout, ob, md):
        split = layout.split(percentage=0.25)
        col = split.column()
        col.prop(md, "scaleui")
    ...

DNA_modifier_types.h

ANY FOLDER/blender/source/blender/makesdna/DNA_modifier_types.h

Add a new modifier name to the ModifierType list, eModifierType_Scaling. Make sure the new entry comes before NUM_MODIFIER_TYPES, but does not modify the ordinal for any other modifier.

typedef enum ModifierType {
	eModifierType_None = 0,
	...
	...
	eModifierType_Scaling,
	NUM_MODIFIER_TYPES
} ModifierType;

Add a new structure of your new modifier, at end of file of DNA_modifier_types.h, and check that the structure meets the alignment requirements Dev:Source/Data_Structures/DNAStructs

typedef struct ScalingModifierData {
	ModifierData modifier;
	float scale;
	int pad; /* Variable needed to meet the alignment requirements */
} ScalingModifierData;

RNA_access.h

ANY FOLDER/blender/source/blender/makesrna/RNA_access.h

Add a new StructRNA declaration.

extern StructRNA RNA_ScalingModifier;

rna_modifier.c

ANY FOLDER/blender/source/blender/makesrna/intern/rna_modifier.c

Add the new modifier to the modifier_type_items array. There are currently four categories it can go under: Modify, Generate, Deform, and Simulate. Entries within a category should be in alphabetical order. Add this modifier under {0, "", 0, N_("Deform"), ""} block.

EnumPropertyItem modifier_type_items[] = {
	...
	{0, "", 0, N_("Deform"), ""},
	...
	{eModifierType_Scaling, "SCALING", ICON_MAN_SCALE, "Scaling the mesh", ""},
	...
};

In function rna_Modifier_refine, add a new case for the modifier struct:

static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
{
	...
	switch (md->type) {
		...
		case eModifierType_Scaling:
			return &RNA_ScalingModifier;
	...
}

Add properties to the blender user interface with base on Dev:2.5/Source/Architecture/RNA

Add new function rna_def_modifier_scaling

static void rna_def_modifier_scaling(BlenderRNA *brna)
{
	StructRNA *srna;
	PropertyRNA *prop;

	srna = RNA_def_struct(brna, "ScalingModifier", "Modifier");
	RNA_def_struct_ui_text(srna, "Scaling Modifier", "Scaling effect modifier");
	RNA_def_struct_sdna(srna, "ScalingModifierData");
	RNA_def_struct_ui_icon(srna, ICON_MAN_SCALE);

	/* scaleui: name for "properties_data_modifier.py"*/
	prop = RNA_def_property(srna, "scaleui", PROP_FLOAT, PROP_NONE); 

	/*scale: name for "DNA_modifier_types.h"*/
	RNA_def_property_float_sdna(prop, NULL, "scale");

	RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
	RNA_def_property_ui_range(prop, -100, 100, 1, 3);
	RNA_def_property_ui_text(prop, "Scale", "Scale factor");
	RNA_def_property_update(prop, 0, "rna_Modifier_update");

}

Add line to defines new RNA function, invoke the previous function

void RNA_def_modifier(BlenderRNA *brna)
{
	...
	rna_def_modifier_remesh(brna);
	rna_def_modifier_skin(brna);
	rna_def_modifier_scaling(brna);
}

CMakeLists.txt

ANY FOLDER/blender/source/blender/modifiers/CMakeLists.txt

Add a file name MOD_scaling.c to bf_modifiers project

set(SRC
	...
	intern/MOD_scaling.c
	...
)

MOD_modifiertypes.h

ANY FOLDER/blender/source/blender/modifiers/MOD_modifiertypes.h

Add a new ModifierTypeInfo declaration.

extern ModifierTypeInfo modifierType_Scaling;

MOD_util.c

ANY FOLDER/blender/source/blender/modifiers/intern/MOD_util.c

Add a new INIT_TYPE line.

#define INIT_TYPE(typeName) (types[eModifierType_##typeName] = &modifierType_##typeName)
...
	INIT_TYPE(Scaling);
#undef INIT_TYPE

MOD_scaling.c

ANY FOLDER/blender/source/blender/modifiers/intern/MOD_scaling.c

Create a new file name as MOD_scaling.c in the folder ANY FOLDER/blender/source/blender/modifiers/intern/.

/*
 * ***** BEGIN GPL LICENSE BLOCK *****
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software  Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
 * All rights reserved.
 *
 * Contributor(s): Your name
 *
 * ***** END GPL LICENSE BLOCK *****
 *
 */

/** \file blender/modifiers/intern/MOD_scaling.c
 *  \ingroup modifiers
 */


#include "DNA_meshdata_types.h"

#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"

#include "MEM_guardedalloc.h"

#include "BKE_cdderivedmesh.h"
#include "BKE_particle.h"
#include "BKE_deform.h"

#include "MOD_modifiertypes.h"
#include "MOD_util.h"


static void initData(ModifierData *md)
{
	ScalingModifierData *smd = (ScalingModifierData *) md;
	smd->scale = 1.0f;
}

static void copyData(ModifierData *md, ModifierData *target)
{
	ScalingModifierData *smd = (ScalingModifierData *) md;
	ScalingModifierData *tsmd = (ScalingModifierData *) target;
	tsmd->scale = smd->scale;
}

static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
{
	ScalingModifierData *smd = (ScalingModifierData *) md;
	/* disable if modifier is 1.0 for scale*/
	if (smd->scale == 1.0f) return 1;
	return 0;
}

static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
	ScalingModifierData *smd = (ScalingModifierData *)md;
	CustomDataMask dataMask = 0;
	return dataMask;
}

static void ScalingModifier_do(
        ScalingModifierData *smd, Object *ob, DerivedMesh *dm,
        float (*vertexCos)[3], int numVerts)
{
	int i;
	float scale;
	scale = smd->scale;

	for (i = 0; i < numVerts; i++) {
		vertexCos[i][0] = vertexCos[i][0] * scale;
		vertexCos[i][1] = vertexCos[i][1] * scale;
		vertexCos[i][2] = vertexCos[i][2] * scale;
	}
}

static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
                        float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag))
{
	DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, 0);

	ScalingModifier_do((ScalingModifierData *)md, ob, dm,
	                  vertexCos, numVerts);

	if (dm != derivedData)
		dm->release(dm);
}

static void deformVertsEM(
        ModifierData *md, Object *ob, struct BMEditMesh *editData,
        DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
	DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, 0);

	ScalingModifier_do((ScalingModifierData *)md, ob, dm,
	                  vertexCos, numVerts);

	if (dm != derivedData)
		dm->release(dm);
}


ModifierTypeInfo modifierType_Scaling = {
	/* name */              "Scaling",
	/* structName */        "ScalingModifierData",
	/* structSize */        sizeof(ScalingModifierData),
	/* type */              eModifierTypeType_OnlyDeform,
	/* flags */             eModifierTypeFlag_AcceptsMesh |
	                        eModifierTypeFlag_SupportsEditmode,

	/* copyData */          copyData,
	/* deformVerts */       deformVerts,
	/* deformMatrices */    NULL,
	/* deformVertsEM */     deformVertsEM,
	/* deformMatricesEM */  NULL,
	/* applyModifier */     NULL,
	/* applyModifierEM */   NULL,
	/* initData */          initData,
	/* requiredDataMask */  requiredDataMask,
	/* freeData */          NULL,
	/* isDisabled */        isDisabled,
	/* updateDepgraph */    NULL,
	/* dependsOnTime */     NULL,
	/* dependsOnNormals */	NULL,
	/* foreachObjectLink */ NULL,
	/* foreachIDLink */     NULL,
	/* foreachTexLink */    NULL,
};

The most important funcion in the file MOD_scaling.c is

static void ScalingModifier_do(
        ScalingModifierData *smd, Object *ob, DerivedMesh *dm,
        float (*vertexCos)[3], int numVerts)
{
	int i;
	float scale;
	scale = smd->scale;
 
	for (i = 0; i < numVerts; i++) {
		vertexCos[i][0] = vertexCos[i][0] * scale;
		vertexCos[i][1] = vertexCos[i][1] * scale;
		vertexCos[i][2] = vertexCos[i][2] * scale;
	}
}

In that function you scale every vertex in the mesh by the factor scale;

Configurate and Compile

For changes in the CMakeLists.txt file to take effect, you must rerun CMake (cmake-gui) and click on Configure and Generate.

Then you must reopen the file Blender.sln, and Generate the project INSTALL.