Paste Code
Paste Blends
Paste Images
Index: release/scripts/startup/bl_ui/properties_data_modifier.py
===================================================================
--- release/scripts/startup/bl_ui/properties_data_modifier.py (revisione 39737)
+++ release/scripts/startup/bl_ui/properties_data_modifier.py (copia locale)
@@ -81,10 +81,10 @@
layout.prop(md, "curve")

layout.separator()
-
split = layout.split()

col = split.column()
+ col.prop(md,"rays")
col.prop(md, "use_constant_offset")
sub = col.column()
sub.active = md.use_constant_offset
@@ -99,6 +99,7 @@
sub.prop(md, "merge_threshold", text="Distance")

col = split.column()
+ col.prop(md,"rays_dir")
col.prop(md, "use_relative_offset")
sub = col.column()
sub.active = md.use_relative_offset
@@ -110,12 +111,90 @@
sub = col.column()
sub.active = md.use_object_offset
sub.prop(md, "offset_object", text="")
-
+ sub.prop(md, "use_between_offset")
layout.separator()

layout.prop(md, "start_cap")
layout.prop(md, "end_cap")
+ layout.prop(md, "mid_cap")
+ act_mid = layout.row()
+ if md.mid_cap is None :
+ act_mid.active = False
+ else:
+ act_mid.active = True
+ act_mid.prop(md, "cont_mid_cap")
+ layout.separator()

+ if md.fit_type == 'FIT_CURVE':
+ col = layout.column()
+ row = col.box().row()
+ if md.use_advanced_curve:
+ row.prop(md, "use_advanced_curve",
+ icon="DOWNARROW_HLT", text="", emboss=False)
+ else:
+ row.prop(md, "use_advanced_curve",
+ icon="RIGHTARROW", text="", emboss=False)
+ row.label("Advanced Curve")
+ if (md.use_advanced_curve):
+ col = col.box().column()
+ sub_split = col.split()
+ col = sub_split.column()
+ col.prop(md, "all_curve")
+ col = sub_split.column()
+ col.prop(md, "for_segment")
+
+ col = layout.column()
+ row = col.box().row()
+ if md.use_advanced_material:
+ row.prop(md, "use_advanced_material",
+ icon="DOWNARROW_HLT", text="", emboss=False)
+ else:
+ row.prop(md, "use_advanced_material",
+ icon="RIGHTARROW", text="", emboss=False)
+ row.label("Advanced Material", icon="MATERIAL")
+ if (md.use_advanced_material):
+ col = col.box().column()
+ row = col.row()
+ row.prop(md, "material", expand=True)
+ act = col.row()
+ if md.material == 'SEQUENCE' :
+ act.active = True
+ else:
+ act.active = False
+ act.prop(md, "cont_mat")
+
+ col = layout.column()
+ row = col.box().row()
+ row.prop(md, "use_advanced", text="")
+ row.label("Advanced Noise")
+ if (md.use_advanced):
+ col = col.box().column()
+ row = col.row()
+ row.label(text="Sign Offset:")
+ row.prop(md, "sign_p")
+ row.prop(md, "sign_l")
+ off_box = col.row()
+ off_box.column().prop(md, "location_offset", text="Location")
+ off_box.column().prop(md, "rotation_offset", text="Rotation")
+ off_box2 = off_box.split().column()
+ off_box2.column().prop(md, "proportion", text="Scale")
+ if (md.proportion):
+ off_box2.column().prop(md, "scale", text="")
+ else:
+ off_box2.column().prop(md, "scale_offset", text="")
+ col.separator()
+ row = col.row()
+ row.prop(md, "array_group")
+ act = row.row()
+ if md.array_group is None :
+ act.active = False
+ else:
+ act.active = True
+ act.prop(md, "rand_group")
+ col = col.column()
+ col.separator()
+ layout.operator("object.array_rand", text="Refresh Ad. Offset")
+
def BEVEL(self, layout, ob, md):
split = layout.split()

Index: source/blender/blenkernel/BKE_ama.h
===================================================================
--- source/blender/blenkernel/BKE_ama.h (revisione 0)
+++ source/blender/blenkernel/BKE_ama.h (revisione 0)
@@ -0,0 +1,84 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef BKE_AMA_H
+#define BKE_AMA_H
+
+/** \file BKE_ama.h
+ * \ingroup bke
+ */
+
+struct ArrayModifierData;
+struct Object;
+struct Scene;
+struct MVert;
+struct MFace;
+struct DerivedMesh;
+struct CustomData;
+struct EdgeHash;
+
+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;
+
+
+/* calculations is in local space of deformed object
+ so we store in latmat transform from path coord inside object
+ */
+typedef struct {
+ float dmin[3], dmax[3], dsize, dloc[3];
+ float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
+ int no_rot_axis;
+} CurveDeform;
+
+
+float vertarray_size(struct MVert *mvert, int numVerts, int axis);
+int test_index_face_maxvert(struct MFace *mface, struct CustomData *fdata, int mfindex, int nr, int maxvert);
+int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum);
+
+float length_fitcurve(struct ArrayModifierData *amd, struct Scene *scene);
+int length_to_count(float length, const float offset[3]);
+float count_to_length(int count, const float offset[3]);
+float f_rand_max(float max);
+void array_scale_offset(const float max_off[3], float rit[3],int prop);
+void array_offset(const float max_off[3], float rit[3],int sign);
+void init_offset(const int start, const int end, struct ArrayModifierData *ar);
+void create_offset(const int n, const int totmat, struct ArrayModifierData *ar, struct Object *ob);
+void array_to_curve(struct Scene *scene, struct Object *cuOb, struct Object *target, float (*vertexCos)[3], int numVerts);
+/*struct DerivedMesh *insert_start_cap(struct ArrayModifierData *amd, struct DerivedMesh *dm, struct DerivedMesh *result, struct DerivedMesh *start_cap, IndexMapEntry *indexMap,
+ struct EdgeHash *edges, int numVerts, int numEdges, int numFaces, float offset[4][4]);*/
+
+#endif
+
Index: source/blender/blenkernel/CMakeLists.txt
===================================================================
--- source/blender/blenkernel/CMakeLists.txt (revisione 39737)
+++ source/blender/blenkernel/CMakeLists.txt (copia locale)
@@ -73,6 +73,7 @@
intern/CCGSubSurf.c
intern/DerivedMesh.c
intern/action.c
+ intern/ama.c
intern/anim.c
intern/anim_sys.c
intern/armature.c
@@ -152,6 +153,7 @@

BKE_DerivedMesh.h
BKE_action.h
+ BKE_ama.h
BKE_anim.h
BKE_animsys.h
BKE_armature.h
Index: source/blender/blenkernel/intern/ama.c
===================================================================
--- source/blender/blenkernel/intern/ama.c (revisione 0)
+++ source/blender/blenkernel/intern/ama.c (revisione 0)
@@ -0,0 +1,625 @@
+/*
+ * $Id: ama.c 36773 2011-08-13 13:46:00Z ruesp83 $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Fabio Russo
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/ama.c
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_rand.h"
+#include "BLI_listbase.h"
+#include "BLI_edgehash.h"
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "BKE_object.h"
+#include "BKE_displist.h"
+#include "BKE_ama.h"
+#include "BKE_anim.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_mesh.h"
+
+
+float vertarray_size(MVert *mvert, int numVerts, int axis)
+{
+ int i;
+ float min_co, max_co;
+
+ /* if there are no vertices, width is 0 */
+ if(numVerts == 0) return 0;
+
+ /* find the minimum and maximum coordinates on the desired axis */
+ min_co = max_co = mvert->co[axis];
+ ++mvert;
+ for(i = 1; i < numVerts; ++i, ++mvert) {
+ if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
+ if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
+ }
+
+ return max_co - min_co;
+}
+
+
+/* XXX This function fixes bad merging code, in some cases removing vertices creates indices > maxvert */
+int test_index_face_maxvert(MFace *mface, CustomData *fdata, int mfindex, int nr, int maxvert)
+{
+ if(mface->v1 >= maxvert) {
+ // printf("bad index in array\n");
+ mface->v1= maxvert - 1;
+ }
+ if(mface->v2 >= maxvert) {
+ // printf("bad index in array\n");
+ mface->v2= maxvert - 1;
+ }
+ if(mface->v3 >= maxvert) {
+ // printf("bad index in array\n");
+ mface->v3= maxvert - 1;
+ }
+ if(mface->v4 >= maxvert) {
+ // printf("bad index in array\n");
+ mface->v4= maxvert - 1;
+ }
+
+ return test_index_face(mface, fdata, mfindex, nr);
+}
+
+
+/* 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.)
+ */
+int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
+{
+ if(indexMap[oldIndex].merge < 0) {
+ /* vert wasn't merged, so use copy of this vert */
+ return indexMap[oldIndex].new + copyNum;
+ } else if(indexMap[oldIndex].merge == oldIndex) {
+ /* vert was merged with itself */
+ return indexMap[oldIndex].new;
+ } else {
+ /* vert was merged with another vert */
+ /* follow the chain of merges to the end, or until we've passed
+ * a number of vertices equal to the copy number
+ */
+ if(copyNum <= 0)
+ return indexMap[oldIndex].new;
+ else
+ return calc_mapping(indexMap, indexMap[oldIndex].merge,
+ copyNum - 1);
+ }
+}
+
+
+float length_fitcurve(ArrayModifierData *amd, struct Scene *scene)
+{
+ float length = 0;
+
+ Curve *cu = amd->curve_ob->data;
+ if(cu) {
+ float tmp_mat[3][3];
+ float scale;
+
+ object_to_mat3(amd->curve_ob, tmp_mat);
+ scale = mat3_to_scale(tmp_mat);
+
+ if(!cu->path) {
+ cu->flag |= CU_PATH; // needed for path & bevlist
+ makeDispListCurveTypes(scene, amd->curve_ob, 0);
+ }
+ if(cu->path)
+ length = scale*cu->path->totdist;
+ }
+ return length;
+}
+
+
+int length_to_count(float length, const float offset[3])
+{
+ int count = 0;
+
+ float dist = sqrt(dot_v3v3(offset, offset));
+
+ if(dist > 1e-6f)
+ /* this gives length = first copy start to last copy end
+ add a tiny offset for floating point rounding errors */
+ count = (length + 1e-6f) / dist;
+ else
+ /* if the offset has no translation, just make one copy */
+ count = 1;
+ return count;
+}
+
+
+float count_to_length(int count, const float offset[3])
+{
+ float length = 0;
+ float dist = sqrt(dot_v3v3(offset, offset));
+
+ if(dist > 1e-6f)
+ /* this gives length = first copy start to last copy end
+ add a tiny offset for floating point rounding errors */
+ //count = (length + 1e-6f) / dist;
+ length = count * dist - 1e-6f;
+ else
+ /* if the offset has no translation, just make one copy */
+ length = 1;
+ return length;
+}
+
+
+//generates a psuedo-random float between 0.0 and max
+float f_rand_max(float max)
+{
+ return BLI_frand()*max;
+}
+
+
+void array_scale_offset(const float max_off[3], float rit[3],int prop)
+{
+ //TODO:far valere anche valori meno di uno,
+ //così si possono ottenere oggetti anche più piccoli dell'originale
+
+ rit[0] = f_rand_max(max_off[0]);
+ rit[0] = 1+rit[0];
+
+ if (!prop)
+ {
+ rit[1] = f_rand_max(max_off[1]);
+ rit[1] = 1+rit[1];
+
+ rit[2] = f_rand_max(max_off[2]);
+ rit[2] = 1+rit[2];
+ }
+ else
+ {
+ rit[1] = rit[0];
+ rit[2] = rit[0];
+ }
+}
+
+
+void array_offset(const float max_off[3], float rit[3],int sign)
+{
+ int j;
+
+ rit[0] = f_rand_max(max_off[0]);
+ if (sign & MOD_ARR_SIGN_L)
+ {
+ if (sign & MOD_ARR_SIGN_P)
+ {
+ j = BLI_rand() % 2;
+ if (j == 0)
+ rit[0] = rit[0]*(-1);
+ }
+ else
+ rit[0] = rit[0]*(-1);
+ }
+
+ rit[1] = f_rand_max(max_off[1]);
+ if (sign & MOD_ARR_SIGN_L)
+ {
+ if (sign & MOD_ARR_SIGN_P)
+ {
+ j = BLI_rand() % 2;
+ if (j == 0)
+ rit[1] = rit[1]*(-1);
+ }
+ else
+ rit[1] = rit[1]*(-1);
+ }
+
+ rit[2] = f_rand_max(max_off[2]);
+ if (sign & MOD_ARR_SIGN_L)
+ {
+ if (sign & MOD_ARR_SIGN_P)
+ {
+ j = BLI_rand() % 2;
+ if (j == 0)
+ rit[2] = rit[2]*(-1);
+ }
+ else
+ rit[2] = rit[2]*(-1);
+ }
+}
+
+
+void init_offset(const int start, const int end, ArrayModifierData *ar)
+{
+ int i;
+
+ for (i=start; i< end; i++)
+ {
+ unit_m4(ar->Mem_Ob[i].location);
+ ar->Mem_Ob[i].id_mat = 0;
+ ar->Mem_Ob[i].transform = 0;
+ ar->Mem_Ob[i].rand_group_obj = 0;
+ }
+}
+
+
+void create_offset(const int n, const int totmat, ArrayModifierData *ar, Object *ob)
+{
+ float loc[3];
+ float rot[3];
+ float rotAxis[3];
+ float scale[3];
+ int i, act_mat = 0;
+ int cont_mat = ar->cont_mat-1;
+ Group *group;
+
+ if(ob->dup_group!=NULL)
+ group= ob->dup_group;
+
+ scale[0]=scale[1]=scale[2]=1;
+
+ for (i=0; i < n-1; i++)
+ {
+ if (ar->mode & MOD_ARR_MOD_ADV)
+ {
+ if ((ar->rot_offset[0]!=0) || (ar->rot_offset[1]!=0) || (ar->rot_offset[2]!=0))
+ {
+ array_offset(ar->rot_offset, rot, ar->sign);
+ ar->Mem_Ob[i].transform=1;
+ }
+ if ((ar->scale_offset[0]!=0) || (ar->scale_offset[1]!=0) || (ar->scale_offset[2]!=0))
+ {
+ array_scale_offset(ar->scale_offset, scale, ar->proportion);
+ ar->Mem_Ob[i].transform=1;
+ }
+ if ((ar->loc_offset[0]!=0) || (ar->loc_offset[1]!=0) || (ar->loc_offset[2]!=0))
+ {
+ array_offset(ar->loc_offset, loc, ar->sign);
+ ar->Mem_Ob[i].transform=1;
+ }
+ if (ar->Mem_Ob[i].transform)
+ {
+ loc_eul_size_to_mat4(ar->Mem_Ob[i].location, loc, rot, scale);
+ }
+ if (ar->rand_group & MOD_ARR_RAND_GROUP)
+ {
+ ar->Mem_Ob[i].rand_group_obj = BLI_rand() % BLI_countlist(&group->gobject);
+ ar->Mem_Ob[i].rand_group_obj++;
+ }
+ }
+ if (ar->mode & MOD_ARR_MOD_ADV_MAT)
+ {
+ if (totmat>1)
+ {
+ if (ar->rand_mat & MOD_ARR_MAT) {
+ ar->Mem_Ob[i].id_mat = BLI_rand() % totmat;
+ }
+ else {
+ if (cont_mat == 0 ){
+ cont_mat = ar->cont_mat;
+ if (act_mat + 1 < totmat)
+ act_mat++;
+ else
+ act_mat = 0;
+ }
+ ar->Mem_Ob[i].id_mat = act_mat;
+ cont_mat--;
+ }
+ }
+ }
+
+ }
+}
+
+
+static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd, int dloc)
+{
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_m4m4(cd->objectspace, par->obmat, ob->imat);
+ invert_m4_m4(cd->curvespace, cd->objectspace);
+ copy_m3_m4(cd->objectspace3, cd->objectspace);
+
+ // offset vector for 'no smear'
+ if(dloc) {
+ invert_m4_m4(par->imat, par->obmat);
+ mul_v3_m4v3(cd->dloc, par->imat, ob->obmat[3]);
+ }
+ else {
+ cd->dloc[0]=cd->dloc[1]=cd->dloc[2]= 0.0f;
+ }
+
+ cd->no_rot_axis= 0;
+}
+
+
+/* this makes sure we can extend for non-cyclic. *vec needs 4 items! */
+static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius) /* returns OK */
+{
+ Curve *cu= ob->data;
+ BevList *bl;
+ float ctime1;
+ int cycl=0;
+
+ /* test for cyclic */
+ bl= cu->bev.first;
+ if (!bl->nr) return 0;
+ if(bl && bl->poly> -1) cycl= 1;
+
+ if(cycl==0) {
+ ctime1= CLAMPIS(ctime, 0.0f, 1.0f);
+ }
+ else ctime1= ctime;
+
+ /* vec needs 4 items */
+ if(where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
+
+ if(cycl==0) {
+ Path *path= cu->path;
+ float dvec[3];
+
+ if(ctime < 0.0f) {
+ sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec);
+ mul_v3_fl(dvec, ctime*(float)path->len);
+ add_v3_v3(vec, dvec);
+ if(quat) copy_qt_qt(quat, path->data[0].quat);
+ if(radius) *radius= path->data[0].radius;
+ }
+ else if(ctime > 1.0f) {
+ sub_v3_v3v3(dvec, path->data[path->len-1].vec, path->data[path->len-2].vec);
+ mul_v3_fl(dvec, (ctime-1.0f)*(float)path->len);
+ add_v3_v3(vec, dvec);
+ if(quat) copy_qt_qt(quat, path->data[path->len-1].quat);
+ if(radius) *radius= path->data[path->len-1].radius;
+ /* weight - not used but could be added */
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
+
+ /* for each point, rotate & translate to curve */
+ /* use path, since it has constant distances */
+ /* co: local coord, result local too */
+ /* returns quaternion for rotation, using cd->no_rot_axis */
+ /* axis is using another define!!! */
+static int calc_curve_deform(Scene *scene, Object *par, float *co, CurveDeform *cd, float *quatp)
+{
+ Curve *cu= par->data;
+ float fac, loc[4], dir[3], new_quat[4], radius;
+
+ /* to be sure, mostly after file load */
+ if(cu->path==NULL) {
+ makeDispListCurveTypes(scene, par, 0);
+ if(cu->path==NULL) return 0; // happens on append...
+ }
+ fac=0;
+ if( where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) { /* returns OK */
+ float quat[4], cent[3];
+
+ if(cd->no_rot_axis) { /* set by caller */
+
+ /* this is not exactly the same as 2.4x, since the axis is having rotation removed rather than
+ * changing the axis before calculating the tilt but serves much the same purpose */
+ float dir_flat[3]={0,0,0}, q[4];
+ copy_v3_v3(dir_flat, dir);
+ dir_flat[cd->no_rot_axis-1]= 0.0f;
+
+ normalize_v3(dir);
+ normalize_v3(dir_flat);
+
+ rotation_between_vecs_to_quat(q, dir, dir_flat); /* Could this be done faster? */
+
+ mul_qt_qtqt(new_quat, q, new_quat);
+ }
+
+
+ /* Logic for 'cent' orientation *
+ *
+ * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
+ *
+ * Use a curve modifier to stretch a cube out, color each side RGB, positive side light, negative dark.
+ * view with X up (default), from the angle that you can see 3 faces RGB colors (light), anti-clockwise
+ * Notice X,Y,Z Up all have light colors and each ordered CCW.
+ *
+ * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
+ *
+ * note: moved functions into quat_apply_track/vec_apply_track
+ * */
+ copy_qt_qt(quat, new_quat);
+ copy_v3_v3(cent, co);
+
+ /* zero the axis which is not used,
+ * the big block of text above now applies to these 3 lines */
+ //quat_apply_track(quat, axis-1, (axis==1 || axis==3) ? 1:0); /* up flag is a dummy, set so no rotation is done */
+ //vec_apply_track(cent, axis-1);
+ //cent[axis < 4 ? axis-1 : axis-4]= 0.0f;
+
+
+ /* scale if enabled */
+ if(cu->flag & CU_PATH_RADIUS)
+ mul_v3_fl(cent, radius);
+
+ /* local rotation */
+ normalize_qt(quat);
+ mul_qt_v3(quat, cent);
+
+ /* translation */
+ add_v3_v3v3(co, cent, loc);
+
+ if(quatp)
+ copy_qt_qt(quatp, quat);
+
+ return 1;
+ }
+ return 0;
+}
+
+
+void array_to_curve(Scene *scene, Object *cuOb, Object *target, float (*vertexCos)[3], int numVerts)
+{
+ Curve *cu;
+ int a, flag;
+ CurveDeform cd;
+ int use_vgroups;
+
+ if(cuOb->type != OB_CURVE)
+ return;
+
+ cu = cuOb->data;
+ flag = cu->flag;
+ cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist
+
+ init_curve_deform(cuOb, target, &cd, (cu->flag & CU_STRETCH)==0);
+
+ for(a = 0; a < numVerts; a++) {
+ mul_m4_v3(cd.curvespace, vertexCos[a]);
+ }
+
+ for(a = 0; a < numVerts; a++) {
+ calc_curve_deform(scene, cuOb, vertexCos[a], &cd, NULL);
+ mul_m4_v3(cd.objectspace, vertexCos[a]);
+ }
+ cu->flag = flag;
+}
+
+
+/*DerivedMesh *insert_start_cap(ArrayModifierData *amd, DerivedMesh *dm, DerivedMesh *result, DerivedMesh *start_cap, IndexMapEntry *indexMap,
+ EdgeHash *edges, int numVerts, int numEdges, int numFaces, float offset[4][4])
+{
+/* add start and end caps */
+/* if(start_cap) {
+ float startoffset[4][4];
+ MVert *cap_mvert, *mvert, *src_mvert;
+ MEdge *cap_medge, *medge;
+ MFace *cap_mface, *mface;
+ int *origindex;
+ int *vert_map;
+ int capVerts, capEdges, capFaces;
+ int maxVerts, i;
+
+ maxVerts = dm->getNumVerts(dm);
+ mvert = CDDM_get_verts(result);
+ medge = CDDM_get_edges(result);
+ mface = CDDM_get_faces(result);
+ src_mvert = dm->getVertArray(dm);
+
+ capVerts = start_cap->getNumVerts(start_cap);
+ capEdges = start_cap->getNumEdges(start_cap);
+ capFaces = start_cap->getNumFaces(start_cap);
+ cap_mvert = start_cap->getVertArray(start_cap);
+ cap_medge = start_cap->getEdgeArray(start_cap);
+ cap_mface = start_cap->getFaceArray(start_cap);
+
+ invert_m4_m4(startoffset, offset);
+
+ vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
+ "arrayModifier_doArray vert_map");
+
+ origindex = result->getVertDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capVerts; i++) {
+ MVert *mv = &cap_mvert[i];
+ short merged = 0;
+
+ if(amd->flags & MOD_ARR_MERGE) {
+ float tmp_co[3];
+ MVert *in_mv;
+ int j;
+
+ copy_v3_v3(tmp_co, mv->co);
+ mul_m4_v3(startoffset, tmp_co);
+
+ for(j = 0; j < maxVerts; j++) {
+ in_mv = &src_mvert[j];
+ /* if this vert is within merge limit, merge */
+/* if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
+ vert_map[i] = calc_mapping(indexMap, j, 0);
+ merged = 1;
+ break;
+ }
+ }
+ }
+
+ if(!merged) {
+ DM_copy_vert_data(start_cap, result, i, numVerts, 1);
+ mvert[numVerts] = *mv;
+ mul_m4_v3(startoffset, mvert[numVerts].co);
+ origindex[numVerts] = ORIGINDEX_NONE;
+
+ vert_map[i] = numVerts;
+
+ numVerts++;
+ }
+ }
+ origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capEdges; i++) {
+ int v1, v2;
+
+ v1 = vert_map[cap_medge[i].v1];
+ v2 = vert_map[cap_medge[i].v2];
+
+ if(!BLI_edgehash_haskey(edges, v1, v2)) {
+ DM_copy_edge_data(start_cap, result, i, numEdges, 1);
+ medge[numEdges] = cap_medge[i];
+ medge[numEdges].v1 = v1;
+ medge[numEdges].v2 = v2;
+ origindex[numEdges] = ORIGINDEX_NONE;
+
+ numEdges++;
+ }
+ }
+ origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
+ for(i = 0; i < capFaces; i++) {
+ DM_copy_face_data(start_cap, result, i, numFaces, 1);
+ mface[numFaces] = cap_mface[i];
+ mface[numFaces].v1 = vert_map[mface[numFaces].v1];
+ mface[numFaces].v2 = vert_map[mface[numFaces].v2];
+ mface[numFaces].v3 = vert_map[mface[numFaces].v3];
+ if(mface[numFaces].v4) {
+ mface[numFaces].v4 = vert_map[mface[numFaces].v4];
+
+ test_index_face_maxvert(&mface[numFaces], &result->faceData,
+ numFaces, 4, numVerts);
+ }
+ else
+ {
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 3);
+ }
+
+ origindex[numFaces] = ORIGINDEX_NONE;
+
+ numFaces++;
+ }
+
+ MEM_freeN(vert_map);
+ start_cap->release(start_cap);
+ }
+ return result;
+}*/
Index: source/blender/blenkernel/intern/anim.c
===================================================================
--- source/blender/blenkernel/intern/anim.c (revisione 39737)
+++ source/blender/blenkernel/intern/anim.c (copia locale)
@@ -35,6 +35,7 @@


#include <stdio.h>
+#include <time.h>
#include <math.h>
#include <string.h>

@@ -51,6 +52,7 @@
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"

@@ -751,6 +753,137 @@
}
}

+static void group_arrayduplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated)
+{
+ DupliObject *dob;
+ Group *group;
+ GroupObject *go;
+ float mat[4][4], tmat[4][4], offset[4][4], rot[4][4];
+ ModifierData *md;
+ int i, cont_rnd;
+ float d_alp, alpha;
+
+ if(ob->dup_group==NULL) return;
+ group= ob->dup_group;
+
+ /* simple preventing of too deep nested groups */
+ if(level>MAX_DUPLI_RECUR) return;
+
+ /* handles animated groups, and */
+ /* we need to check update for objects that are not in scene... */
+ group_handle_recalc_and_update(scene, ob, group);
+ animated= animated || group_is_animated(ob, group);
+
+ for(md=ob->modifiers.first; md; md=md->next) {
+ if(md->type == eModifierType_Array) {
+ if (md->mode&eModifierMode_Realtime || md->mode&eModifierMode_Render){
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ d_alp=0;
+ if (amd->rays > 1)
+ alpha = (float)6.2831 / amd->rays;
+ copy_m4_m4(offset, amd->delta);
+
+ for (i = 0; i < amd->count-1; i++)
+ {
+ cont_rnd = 0;
+ for(go= group->gobject.first; go; go= go->next)
+ {
+ cont_rnd++;
+ /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
+ if(go->ob!=ob)
+ {
+ if (amd->rand_group & MOD_ARR_RAND_GROUP)
+ {
+ if ((amd->Mem_Ob[i].rand_group_obj != 0) && (amd->Mem_Ob[i].rand_group_obj != cont_rnd))
+ continue;
+ }
+ /* Group Dupli Offset, should apply after everything else */
+ if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) {
+ copy_m4_m4(tmat, go->ob->obmat);
+ sub_v3_v3v3(tmat[3], tmat[3], group->dupli_ofs);
+ mul_m4_m4m4(mat, tmat, ob->obmat);
+ } else {
+ mul_m4_m4m4(mat, go->ob->obmat, ob->obmat);
+ }
+
+ copy_m4_m4(tmat, mat);
+ if (amd->rays>1)
+ {
+ unit_m4(rot);
+ if (amd->rays_dir == MOD_ARR_RAYS_X)
+ rotate_m4(rot,'X',d_alp);
+ else if (amd->rays_dir == MOD_ARR_RAYS_Y)
+ rotate_m4(rot,'Y',d_alp);
+ else
+ rotate_m4(rot,'Z',d_alp);
+ if (d_alp == 0){
+ mul_m4_m4m4(mat, offset, tmat);
+
+ copy_m4_m4(tmat, mat);
+ mul_m4_m4m4(mat, rot, tmat);
+ }
+ else{
+ mul_m4_m4m4(mat, offset, tmat);
+
+ copy_m4_m4(tmat, mat);
+ mul_m4_m4m4(mat, rot, tmat);
+ }
+ }
+ else
+ {
+ mul_m4_m4m4(mat, offset, tmat);
+ }
+ //Noise
+ if (amd->mode & MOD_ARR_MOD_ADV)
+ {
+ if (amd->Mem_Ob[i].transform == 1)
+ {
+ copy_m4_m4(tmat, mat);
+ mul_m4_m4m4(mat, amd->Mem_Ob[i].location, tmat);
+ }
+ }
+
+ dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIARRAY, animated);
+
+ if (!(md->mode&eModifierMode_Render))
+ dob->no_render = 1;
+ else
+ dob->no_render = 0;
+ /* check the group instance and object layers match, also that the object visible flags are ok. */
+ if(((dob->origlay & group->layer)==0 ||
+ (G.rendering==0 && dob->ob->restrictflag & OB_RESTRICT_VIEW) ||
+ (G.rendering && dob->ob->restrictflag & OB_RESTRICT_RENDER)) ||
+ !(md->mode&eModifierMode_Realtime) || (!(md->mode&eModifierMode_Editmode) && (ob->mode == OB_MODE_EDIT)))
+ {
+ dob->no_draw= 1;
+ }
+ else {
+ dob->no_draw= 0;
+ }
+ if(go->ob->transflag & OB_DUPLI) {
+ copy_m4_m4(dob->ob->obmat, dob->mat);
+ object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, level+1, animated);
+ copy_m4_m4(dob->ob->obmat, dob->omat);
+ }
+ }
+ }
+ //Increment for rays
+ if (amd->rays>1)
+ {
+ d_alp = d_alp + alpha;
+ if (d_alp>6.2831)
+ d_alp=0;
+ }
+ //Offset for clone group
+ if (d_alp == 0)
+ mul_m4_m4m4(offset, offset, amd->delta);
+ }
+ }
+ }
+ }
+}
+
static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated)
{
extern int enable_cu_speed; /* object.c */
@@ -1599,6 +1732,15 @@
if(dob->type == OB_DUPLIGROUP)
copy_m4_m4(dob->ob->obmat, dob->mat);
}
+ } else if(ob->transflag & OB_DUPLIARRAY) {
+ DupliObject *dob;
+
+ group_arrayduplilist(duplilist, scene, ob, level+1, animated);
+ if (level==0) {
+ for(dob= duplilist->first; dob; dob= dob->next)
+ if(dob->type == OB_DUPLIARRAY)
+ copy_m4_m4(dob->ob->obmat, dob->mat);
+ }
}
}

Index: source/blender/blenloader/intern/readfile.c
===================================================================
--- source/blender/blenloader/intern/readfile.c (revisione 39737)
+++ source/blender/blenloader/intern/readfile.c (copia locale)
@@ -3886,6 +3886,15 @@
}
}

+ {
+ ArrayModifierData *amd = (ArrayModifierData *)modifiers_findByType(ob, eModifierType_Array);
+
+ if(amd)
+ {
+ amd->arr_group = newlibadr(fd, ob->id.lib, amd->arr_group);
+ }
+ }
+
/* texture field */
if(ob->pd)
lib_link_partdeflect(fd, &ob->id, ob->pd);
@@ -4157,6 +4166,11 @@
if(tmd->curfalloff)
direct_link_curvemapping(fd, tmd->curfalloff);
}
+ else if (md->type==eModifierType_Array) {
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ amd->Mem_Ob = newdataadr(fd, amd->Mem_Ob);
+ }
}
}

Index: source/blender/blenloader/intern/writefile.c
===================================================================
--- source/blender/blenloader/intern/writefile.c (revisione 39737)
+++ source/blender/blenloader/intern/writefile.c (copia locale)
@@ -1308,6 +1308,11 @@
write_curvemapping(wd, tmd->curfalloff);
}
}
+ else if (md->type==eModifierType_Array) {
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ writestruct(wd, DATA, "ArrayChangeObject", amd->count, amd->Mem_Ob);
+ }
}
}

Index: source/blender/editors/object/object_intern.h
===================================================================
--- source/blender/editors/object/object_intern.h (revisione 39737)
+++ source/blender/editors/object/object_intern.h (copia locale)
@@ -160,6 +160,7 @@
void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot);
void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);
void OBJECT_OT_explode_refresh(struct wmOperatorType *ot);
+void OBJECT_OT_array_rand(struct wmOperatorType *ot);

/* object_constraint.c */
void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
Index: source/blender/editors/object/object_modifier.c
===================================================================
--- source/blender/editors/object/object_modifier.c (revisione 39737)
+++ source/blender/editors/object/object_modifier.c (copia locale)
@@ -203,6 +203,10 @@
else if(md->type == eModifierType_Smoke) {
ob->dt = OB_TEXTURE;
}
+ else if(md->type == eModifierType_Array) {
+ ob->transflag = 0;
+ ob->dup_group = NULL;
+ }
else if(md->type == eModifierType_Multires) {
int ok= 1;
Mesh *me= ob->data;
@@ -1404,3 +1408,49 @@
edit_modifier_properties(ot);
}

+/****************** array rand operator *********************/
+
+static int array_poll(bContext *C)
+{
+ return edit_modifier_poll_generic(C, &RNA_ArrayModifier, 0);
+}
+
+static int array_rand_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ ArrayModifierData *amd = (ArrayModifierData *)edit_modifier_property_get(op, ob, eModifierType_Array);
+
+ if (!amd)
+ return OPERATOR_CANCELLED;
+
+ amd->lock = 0;
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int array_rand_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+ if (edit_modifier_invoke_properties(C, op))
+ return array_rand_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+
+void OBJECT_OT_array_rand(wmOperatorType *ot)
+{
+ ot->name= "Array Refresh";
+ ot->description= "Refresh data in the Array modifier";
+ ot->idname= "OBJECT_OT_array_rand";
+
+ ot->poll= array_poll;
+ ot->invoke= array_rand_invoke;
+ ot->exec= array_rand_exec;
+
+ /* flags */
+ //ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+ edit_modifier_properties(ot);
+}
Index: source/blender/editors/object/object_ops.c
===================================================================
--- source/blender/editors/object/object_ops.c (revisione 39737)
+++ source/blender/editors/object/object_ops.c (copia locale)
@@ -143,7 +143,8 @@
WM_operatortype_append(OBJECT_OT_multires_external_pack);
WM_operatortype_append(OBJECT_OT_meshdeform_bind);
WM_operatortype_append(OBJECT_OT_explode_refresh);
-
+ WM_operatortype_append(OBJECT_OT_array_rand);
+
WM_operatortype_append(OBJECT_OT_constraint_add);
WM_operatortype_append(OBJECT_OT_constraint_add_with_targets);
WM_operatortype_append(POSE_OT_constraint_add);
Index: source/blender/makesdna/DNA_modifier_types.h
===================================================================
--- source/blender/makesdna/DNA_modifier_types.h (revisione 39737)
+++ source/blender/makesdna/DNA_modifier_types.h (copia locale)
@@ -173,11 +173,24 @@
/* Mask Modifier -> flag */
#define MOD_MASK_INV (1<<0)

+
+typedef struct ArrayChangeObject {
+ float location[4][4];
+ /*0 not modified
+ 1 modified
+ */
+ int transform;
+ int id_mat;
+ int rand_group_obj;
+} ArrayChangeObject;
+
typedef struct ArrayModifierData {
ModifierData modifier;

/* the object with which to cap the start of the array */
struct Object *start_cap;
+ /* the object with which to cap the mid of the array */
+ struct Object *mid_cap;
/* the object with which to cap the end of the array */
struct Object *end_cap;
/* the curve object to use for MOD_ARR_FITCURVE */
@@ -192,6 +205,7 @@
1 means the duplicates are 1 object-width apart
*/
float scale[3];
+ float delta[4][4];
/* the length over which to distribute the duplicates */
float length;
/* the limit below which to merge vertices in adjacent duplicates */
@@ -215,6 +229,29 @@
int flags;
/* the number of duplicates to generate for MOD_ARR_FIXEDCOUNT */
int count;
+ /*Normal Mode-Advanced Mode*/
+ int mode;
+ /*Direction Offset*/
+ int sign;
+ /* min and max limit */
+ //float limit[2];
+ float loc_offset[3];
+ float rot_offset[3];
+ float scale_offset[3];
+ //Lock the noise offset
+ int lock;
+ struct ArrayChangeObject *Mem_Ob;
+
+ int proportion;
+ int rays;
+ int rays_dir;
+ int rand_mat;
+ int cont_mat;
+ int cont_mid_cap;
+ struct Group *arr_group;
+ int rand_group;
+ int distribution;
+
} ArrayModifierData;

/* ArrayModifierData->fit_type */
@@ -226,11 +263,44 @@
#define MOD_ARR_OFF_CONST (1<<0)
#define MOD_ARR_OFF_RELATIVE (1<<1)
#define MOD_ARR_OFF_OBJ (1<<2)
+#define MOD_ARR_OFF_BETW (1<<3)

/* ArrayModifierData->flags */
-#define MOD_ARR_MERGE (1<<0)
-#define MOD_ARR_MERGEFINAL (1<<1)
+#define MOD_ARR_MERGE (1<<0)
+#define MOD_ARR_MERGEFINAL (1<<1)

+/* ArrayModifierData->mode */
+#define MOD_ARR_MOD_ADV (1<<0)
+#define MOD_ARR_MOD_ADV_MAT (1<<1)
+#define MOD_ARR_MOD_ADV_CURVE (1<<2)
+#define MOD_ARR_MOD_ADV_MID (1<<3)
+
+/* ArrayModifierData->sign */
+#define MOD_ARR_SIGN_P (1<<0)
+#define MOD_ARR_SIGN_L (1<<1)
+
+/* ArrayModifierData->mode */
+#define MOD_ARR_LOCK (1<<0)
+
+/* ArrayModifierData->proportion */
+#define MOD_ARR_PROP (1<<0)
+
+/* ArrayModifierData->rnd_mat */
+#define MOD_ARR_MAT (1<<0)
+#define MOD_ARR_SEQ (1<<1)
+
+/* ArrayModifierData->rays_dir */
+#define MOD_ARR_RAYS_X 0
+#define MOD_ARR_RAYS_Y 1
+#define MOD_ARR_RAYS_Z 2
+
+/* ArrayModifierData->rand_group */
+#define MOD_ARR_RAND_GROUP (1<<0)
+
+/* ArrayModifierData->distribution */
+#define MOD_ARR_DIST_EVENLY (1<<0)
+#define MOD_ARR_DIST_SEGMENT (1<<1)
+
typedef struct MirrorModifierData {
ModifierData modifier;

Index: source/blender/makesdna/DNA_object_types.h
===================================================================
--- source/blender/makesdna/DNA_object_types.h (revisione 39737)
+++ source/blender/makesdna/DNA_object_types.h (copia locale)
@@ -285,9 +285,10 @@
struct DupliObject *next, *prev;
struct Object *ob;
unsigned int origlay;
- int index, no_draw, type, animated;
+ int index, no_draw, no_render, type, animated;
float mat[4][4], omat[4][4];
float orco[3], uv[2];
+ int pad;
} DupliObject;

/* **************** OBJECT ********************* */
@@ -328,7 +329,7 @@
/*#define OB_OFFS_LOCAL 1*/ /*UNUSED*/
/* #define OB_QUAT 2 */ /* never used, free flag */
#define OB_NEG_SCALE 4
-#define OB_DUPLI (8+16+256+512+2048)
+#define OB_DUPLI (8+16+256+512+2048+4096)
#define OB_DUPLIFRAMES 8
#define OB_DUPLIVERTS 16
#define OB_DUPLIROT 32
@@ -338,8 +339,9 @@
#define OB_DUPLIFACES 512
#define OB_DUPLIFACES_SCALE 1024
#define OB_DUPLIPARTS 2048
-#define OB_RENDER_DUPLI 4096
-#define OB_NO_CONSTRAINTS 8192 /* runtime constraints disable */
+#define OB_DUPLIARRAY 4096
+#define OB_RENDER_DUPLI 8192
+#define OB_NO_CONSTRAINTS 16384

/* (short) ipoflag */
// XXX depreceated - old animation system crap
Index: source/blender/makesrna/intern/rna_modifier.c
===================================================================
--- source/blender/makesrna/intern/rna_modifier.c (revisione 39737)
+++ source/blender/makesrna/intern/rna_modifier.c (copia locale)
@@ -523,6 +523,11 @@
modifier_object_set(ptr->id.data, &((ArrayModifierData*)ptr->data)->start_cap, OB_MESH, value);
}

+static void rna_ArrayModifier_mid_cap_set(PointerRNA *ptr, PointerRNA value)
+{
+ modifier_object_set(ptr->id.data, &((ArrayModifierData*)ptr->data)->mid_cap, OB_MESH, value);
+}
+
static void rna_ArrayModifier_curve_set(PointerRNA *ptr, PointerRNA value)
{
modifier_object_set(ptr->id.data, &((ArrayModifierData*)ptr->data)->curve_ob, OB_CURVE, value);
@@ -1287,12 +1292,23 @@
StructRNA *srna;
PropertyRNA *prop;

+ static EnumPropertyItem prop_material_items[] = {
+ {MOD_ARR_MAT, "RANDOM", 0, "Random", "Use a random material"},
+ {MOD_ARR_SEQ, "SEQUENCE", 0, "Sequence", "Use the materials in sequence"},
+ {0, NULL, 0, NULL, NULL}};
+
static EnumPropertyItem prop_fit_type_items[] = {
{MOD_ARR_FIXEDCOUNT, "FIXED_COUNT", 0, "Fixed Count", "Duplicate the object a certain number of times"},
{MOD_ARR_FITLENGTH, "FIT_LENGTH", 0, "Fit Length", "Duplicate the object as many times as fits in a certain length"},
{MOD_ARR_FITCURVE, "FIT_CURVE", 0, "Fit Curve", "Fit the duplicated objects to a curve"},
{0, NULL, 0, NULL, NULL}};

+ static EnumPropertyItem prop_rays_dir_items[] = {
+ {MOD_ARR_RAYS_X, "X", 0, "X", "Rays Direction X"},
+ {MOD_ARR_RAYS_Y, "Y", 0, "Y", "Rays Direction Y"},
+ {MOD_ARR_RAYS_Z, "Z", 0, "Z", "Rays Direction Z"},
+ {0, NULL, 0, NULL, NULL}};
+
srna= RNA_def_struct(brna, "ArrayModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Array Modifier", "Array duplication modifier");
RNA_def_struct_sdna(srna, "ArrayModifierData");
@@ -1375,6 +1391,11 @@
RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");

+ prop= RNA_def_property(srna, "use_between_offset", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "offset_type", MOD_ARR_OFF_BETW);
+ RNA_def_property_ui_text(prop, "Between Offset", "Number of duplicates between two objects");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
/* Caps */
prop= RNA_def_property(srna, "start_cap", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Start Cap", "Mesh object to use as a start cap");
@@ -1382,11 +1403,125 @@
RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_Modifier_update");

+ prop= RNA_def_property(srna, "mid_cap", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Mid Cap", "Mesh object to use as a mid cap");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_ArrayModifier_mid_cap_set", NULL, "rna_Mesh_object_poll");
+ RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "cont_mid_cap", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_ui_range(prop, 1, 1000, 1, 0);
+ RNA_def_property_ui_text(prop, "Count Mid Cap", "Number of duplicates of Mid Cap");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop= RNA_def_property(srna, "end_cap", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "End Cap", "Mesh object to use as an end cap");
RNA_def_property_pointer_funcs(prop, NULL, "rna_ArrayModifier_end_cap_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ /* Advanced parameters */
+ prop= RNA_def_property(srna, "use_advanced", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", MOD_ARR_MOD_ADV);
+ RNA_def_property_ui_text(prop, "Advanced", "Use Advanced Array");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "sign_p", PROP_BOOLEAN, PROP_TRANSLATION);
+ RNA_def_property_boolean_sdna(prop, NULL, "sign", MOD_ARR_SIGN_P);
+ RNA_def_property_ui_text(prop, "+", "Random Sign Between + and -");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "sign_l", PROP_BOOLEAN, PROP_TRANSLATION);
+ RNA_def_property_boolean_sdna(prop, NULL, "sign", MOD_ARR_SIGN_L);
+ RNA_def_property_ui_text(prop, "-", "Random Sign Between + and -");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "location_offset", PROP_FLOAT, PROP_TRANSLATION);
+ RNA_def_property_float_sdna(prop, NULL, "loc_offset");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0, FLT_MAX, 1, 5);
+ RNA_def_property_ui_text(prop, "Location Offset Displacement", "Add a location offset to vertices or object");
+ RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "rotation_offset", PROP_FLOAT, PROP_EULER);
+ RNA_def_property_float_sdna(prop, NULL, "rot_offset");
+ RNA_def_property_ui_text(prop, "Rotation Offset Displacement", "Add a rotation offset to vertices or object");
+ RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "scale_offset", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "scale_offset");
+ RNA_def_property_range(prop, 0, 10);
+ RNA_def_property_ui_range(prop, 0, 10, 1,5);
+ RNA_def_property_ui_text(prop, "Scale Offset Displacement", "Add a scale offset to vertices or object");
+ RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale_offset[0]");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0, FLT_MAX, 1, 5);
+ RNA_def_property_ui_text(prop, "Scale Offset Displacement", "Add a scale offset to vertices or object");
+ RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "proportion", PROP_BOOLEAN, PROP_TRANSLATION);
+ RNA_def_property_boolean_sdna(prop, NULL, "proportion", MOD_ARR_SIGN_P);
+ RNA_def_property_ui_text(prop, "Constrain Proportions", "Constrain Proportions");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "rays", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 365);
+ RNA_def_property_ui_range(prop, 1, 365, 1,0);
+ RNA_def_property_ui_text(prop, "Rays", "Rays");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "material", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "rand_mat");
+ RNA_def_property_enum_items(prop, prop_material_items);
+ RNA_def_property_ui_text(prop, "Offset Material", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "cont_mat", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_ui_range(prop, 1, 1000, 1, 0);
+ RNA_def_property_ui_text(prop, "Count Material", "Repetition of material");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "rays_dir", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_rays_dir_items);
+ RNA_def_property_ui_text(prop, "Rays Direction", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "array_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "arr_group");
+ RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Dupli Group", "Show Group");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "rand_group", PROP_BOOLEAN, PROP_TRANSLATION);
+ RNA_def_property_boolean_sdna(prop, NULL, "rand_group", MOD_ARR_RAND_GROUP);
+ RNA_def_property_ui_text(prop, "Rand Object", "Object random group");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "use_advanced_curve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", MOD_ARR_MOD_ADV_CURVE);
+ RNA_def_property_ui_text(prop, "Advanced Curve", "Using a curve in an array");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "all_curve", PROP_BOOLEAN, PROP_TRANSLATION);
+ RNA_def_property_boolean_sdna(prop, NULL, "distribution", MOD_ARR_DIST_EVENLY);
+ RNA_def_property_ui_text(prop, "Spread Evenly", "Spread evenly on a curve");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "for_segment", PROP_BOOLEAN, PROP_TRANSLATION);
+ RNA_def_property_boolean_sdna(prop, NULL, "distribution", MOD_ARR_DIST_SEGMENT);
+ RNA_def_property_ui_text(prop, "For Segment", "Spread evenly for all segments");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "use_advanced_material", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", MOD_ARR_MOD_ADV_MAT);
+ RNA_def_property_ui_text(prop, "Advanced Material", "Settings of the material in an array");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
}

static void rna_def_modifier_edgesplit(BlenderRNA *brna)
Index: source/blender/modifiers/intern/MOD_array.c
===================================================================
--- source/blender/modifiers/intern/MOD_array.c (revisione 39737)
+++ source/blender/modifiers/intern/MOD_array.c (copia locale)
@@ -37,6 +37,8 @@

/* Array modifier: duplicates the object multiple times along an axis */

+#include <time.h>
+#include <math.h>
#include "MEM_guardedalloc.h"

#include "BLI_math.h"
@@ -45,6 +47,7 @@
#include "BLI_edgehash.h"

#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"

@@ -53,9 +56,12 @@
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BKE_anim.h"

+//#include "BLI_rand.h"
+
#include "depsgraph_private.h"
-
+#include "BKE_ama.h"
#include "MOD_util.h"

static void initData(ModifierData *md)
@@ -65,7 +71,7 @@
/* default to 2 duplicates distributed along the x-axis by an
offset of 1 object-width
*/
- amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
+ amd->start_cap = amd->mid_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
amd->count = 2;
amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
amd->scale[0] = 1;
@@ -75,6 +81,22 @@
amd->fit_type = MOD_ARR_FIXEDCOUNT;
amd->offset_type = MOD_ARR_OFF_RELATIVE;
amd->flags = 0;
+
+ amd->mode = !MOD_ARR_MOD_ADV;
+ amd->loc_offset[0] = amd->loc_offset[1] = amd->loc_offset[2] = 0;
+ amd->rot_offset[0] = amd->rot_offset[1] = amd->rot_offset[2] = 0;
+ amd->scale_offset[0] = amd->scale_offset[1] = amd->scale_offset[2] = 0;
+ amd->sign = MOD_ARR_SIGN_P;
+ amd->lock = !MOD_ARR_LOCK;
+ amd->proportion = MOD_ARR_PROP;
+ amd->rays = 1;
+ amd->rand_mat = MOD_ARR_MAT;
+ amd->cont_mat = 1;
+ amd->cont_mid_cap = 1;
+ amd->rays_dir = MOD_ARR_RAYS_X;
+ amd->arr_group = NULL;
+ amd->rand_group = !MOD_ARR_RAND_GROUP;
+ amd->distribution = MOD_ARR_DIST_EVENLY;
}

static void copyData(ModifierData *md, ModifierData *target)
@@ -83,6 +105,7 @@
ArrayModifierData *tamd = (ArrayModifierData*) target;

tamd->start_cap = amd->start_cap;
+ tamd->mid_cap = amd->mid_cap;
tamd->end_cap = amd->end_cap;
tamd->curve_ob = amd->curve_ob;
tamd->offset_ob = amd->offset_ob;
@@ -94,6 +117,23 @@
tamd->fit_type = amd->fit_type;
tamd->offset_type = amd->offset_type;
tamd->flags = amd->flags;
+
+ tamd->mode = amd->mode;
+ copy_v3_v3(tamd->loc_offset, amd->loc_offset);
+ copy_v3_v3(tamd->rot_offset, amd->rot_offset);
+ copy_v3_v3(tamd->scale_offset, amd->scale_offset);
+ tamd->sign = amd->sign;
+ tamd->lock = amd->lock;
+ tamd->proportion = amd->proportion;
+ tamd->rays = amd->rays;
+ tamd->Mem_Ob = MEM_dupallocN(amd->Mem_Ob);
+ tamd->rand_mat = amd->rand_mat;
+ tamd->cont_mat = amd->cont_mat;
+ tamd->cont_mid_cap = amd->cont_mid_cap;
+ tamd->rays_dir = amd->rays_dir;
+ tamd->arr_group = amd->arr_group;
+ tamd->rand_group = amd->rand_group;
+ tamd->distribution = amd->distribution;
}

static void foreachObjectLink(
@@ -104,6 +144,7 @@
ArrayModifierData *amd = (ArrayModifierData*) md;

walk(userData, ob, &amd->start_cap);
+ walk(userData, ob, &amd->mid_cap);
walk(userData, ob, &amd->end_cap);
walk(userData, ob, &amd->curve_ob);
walk(userData, ob, &amd->offset_ob);
@@ -120,6 +161,12 @@
dag_add_relation(forest, curNode, obNode,
DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
}
+ if (amd->mid_cap) {
+ DagNode *curNode = dag_get_node(forest, amd->mid_cap);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
+ }
if (amd->end_cap) {
DagNode *curNode = dag_get_node(forest, amd->end_cap);

@@ -140,102 +187,25 @@
}
}

-static float vertarray_size(MVert *mvert, int numVerts, int axis)
-{
- int i;
- float min_co, max_co;
-
- /* if there are no vertices, width is 0 */
- if(numVerts == 0) return 0;
-
- /* find the minimum and maximum coordinates on the desired axis */
- min_co = max_co = mvert->co[axis];
- ++mvert;
- for(i = 1; i < numVerts; ++i, ++mvert) {
- if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
- if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
- }
-
- return max_co - min_co;
-}
-
-/* XXX This function fixes bad merging code, in some cases removing vertices creates indices > maxvert */
-
-static int test_index_face_maxvert(MFace *mface, CustomData *fdata, int mfindex, int nr, int maxvert)
-{
- if(mface->v1 >= maxvert) {
- // printf("bad index in array\n");
- mface->v1= maxvert - 1;
- }
- if(mface->v2 >= maxvert) {
- // printf("bad index in array\n");
- mface->v2= maxvert - 1;
- }
- if(mface->v3 >= maxvert) {
- // printf("bad index in array\n");
- mface->v3= maxvert - 1;
- }
- if(mface->v4 >= maxvert) {
- // printf("bad index in array\n");
- mface->v4= maxvert - 1;
- }
-
- return test_index_face(mface, fdata, mfindex, nr);
-}
-
-typedef struct IndexMapEntry {
- /* the new vert index that this old vert index maps to */
- int new;
- /* -1 if this vert isn't merged, otherwise the old vert index it
- * should be replaced with
- */
- int merge;
- /* 1 if this vert's first copy is merged with the last copy of its
- * merge target, otherwise 0
- */
- short merge_final;
-} IndexMapEntry;
-
-/* indexMap - an array of IndexMap entries
- * oldIndex - the old index to map
- * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
- */
-static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
-{
- if(indexMap[oldIndex].merge < 0) {
- /* vert wasn't merged, so use copy of this vert */
- return indexMap[oldIndex].new + copyNum;
- } else if(indexMap[oldIndex].merge == oldIndex) {
- /* vert was merged with itself */
- return indexMap[oldIndex].new;
- } else {
- /* vert was merged with another vert */
- /* follow the chain of merges to the end, or until we've passed
- * a number of vertices equal to the copy number
- */
- if(copyNum <= 0)
- return indexMap[oldIndex].new;
- else
- return calc_mapping(indexMap, indexMap[oldIndex].merge,
- copyNum - 1);
- }
-}
-
static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
struct Scene *scene, Object *ob, DerivedMesh *dm,
int initFlags)
{
- int i, j;
+ int i, j, flag;
+ int dim, start;
/* offset matrix */
float offset[4][4];
float final_offset[4][4];
+ float mid_offset[4][4];
float tmp_mat[4][4];
float length = amd->length;
+ float alpha, d_alp, circle;
+ float f_o;
int count = amd->count;
int numVerts, numEdges, numFaces;
int maxVerts, maxEdges, maxFaces;
int finalVerts, finalEdges, finalFaces;
- DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
+ DerivedMesh *result, *start_cap = NULL, *mid_cap = NULL, *end_cap = NULL;
MVert *mvert, *src_mvert;
MEdge *medge;
MFace *mface;
@@ -243,10 +213,12 @@
IndexMapEntry *indexMap;

EdgeHash *edges;
-
+
/* need to avoid infinite recursion here */
if(amd->start_cap && amd->start_cap != ob)
start_cap = amd->start_cap->derivedFinal;
+ if(amd->mid_cap && amd->mid_cap != ob)
+ mid_cap = amd->mid_cap->derivedFinal;
if(amd->end_cap && amd->end_cap != ob)
end_cap = amd->end_cap->derivedFinal;

@@ -277,42 +249,31 @@
unit_m4(obinv);

mul_serie_m4(result_mat, offset,
- obinv, amd->offset_ob->obmat,
- NULL, NULL, NULL, NULL, NULL);
+ obinv, amd->offset_ob->obmat,
+ NULL, NULL, NULL, NULL, NULL);
copy_m4_m4(offset, result_mat);
}

+ if ((amd->offset_type & MOD_ARR_OFF_BETW) && (amd->offset_ob)) {
+ float dist = sqrt(dot_v3v3(amd->offset_ob->obmat[3], amd->offset_ob->obmat[3]));
+ offset[3][0] = amd->offset_ob->obmat[3][0] / (count - 1);
+ offset[3][1] = amd->offset_ob->obmat[3][1] / (count - 1);
+ offset[3][2] = amd->offset_ob->obmat[3][2] / (count - 1);
+ }
if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
- Curve *cu = amd->curve_ob->data;
- if(cu) {
- float tmp_mat[3][3];
- float scale;
-
- object_to_mat3(amd->curve_ob, tmp_mat);
- scale = mat3_to_scale(tmp_mat);
-
- if(!cu->path) {
- cu->flag |= CU_PATH; // needed for path & bevlist
- makeDispListCurveTypes(scene, amd->curve_ob, 0);
- }
- if(cu->path)
- length = scale*cu->path->totdist;
- }
+ length = length_fitcurve(amd, scene);
}

/* calculate the maximum number of copies which will fit within the
prescribed length */
if(amd->fit_type == MOD_ARR_FITLENGTH
|| amd->fit_type == MOD_ARR_FITCURVE) {
- float dist = sqrt(dot_v3v3(offset[3], offset[3]));
-
- if(dist > 1e-6f)
- /* this gives length = first copy start to last copy end
- add a tiny offset for floating point rounding errors */
- count = (length + 1e-6f) / dist;
- else
- /* if the offset has no translation, just make one copy */
- count = 1;
+ /*if ((amd->fit_type == MOD_ARR_FITLENGTH) && (count>2)){
+ amd->length = count_to_length(count, offset[3]);
+ length = amd->length;
+ }*/
+ count = length_to_count(length, offset[3]);
+ amd->count = count;
}

if(count < 1)
@@ -329,21 +290,62 @@
finalEdges += start_cap->getNumEdges(start_cap);
finalFaces += start_cap->getNumFaces(start_cap);
}
+ if(mid_cap) {
+ finalVerts += mid_cap->getNumVerts(mid_cap) * amd->cont_mid_cap;
+ finalEdges += mid_cap->getNumEdges(mid_cap) * amd->cont_mid_cap;
+ finalFaces += mid_cap->getNumFaces(mid_cap) * amd->cont_mid_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);
+ flag = 0;
+ if ((amd->mode & MOD_ARR_MOD_ADV) || (amd->mode & MOD_ARR_MOD_ADV_MAT)){
+ start = 0;
+ if (!amd->Mem_Ob)
+ amd->Mem_Ob = MEM_callocN(sizeof(*amd->Mem_Ob) * (count), "Mem_Ob");
+ else {
+ dim = MEM_allocN_len(amd->Mem_Ob) / sizeof(*amd->Mem_Ob);
+ if (dim < count) {
+ amd->Mem_Ob = MEM_reallocN(amd->Mem_Ob, sizeof(*amd->Mem_Ob) * (count));
+ start = dim;
+ }
+ }
+
+ //Inizializzare i nuovi cloni creati
+ if (!amd->lock) {
+ init_offset(start, count, amd);
+ create_offset(count, ob->totcol, amd, ob);
+ amd->lock = 1;
+ flag = 1;
+ }
+ else
+ if (start!=0)// || (amd->mode & MOD_ARR_MOD_ADV_MAT))
+ init_offset(start, count, amd);
+ }

+ f_o = count-1;
+
+ if (amd->rays>1) {
+ alpha = (float)6.2831 / amd->rays;
+ circle = (float)(count - 1) / amd->rays;
+ f_o = ceil(circle);
+ }
+
/* calculate the offset matrix of the final copy (for merging) */
unit_m4(final_offset);
-
- for(j=0; j < count - 1; j++) {
+ for(j=0; j < f_o; j++) {
mul_m4_m4m4(tmp_mat, final_offset, offset);
copy_m4_m4(final_offset, tmp_mat);
}
-
+
+ copy_m4_m4(mid_offset, offset);
+ mid_offset[3][0] = mid_offset[3][0] / 2;
+ mid_offset[3][1] = mid_offset[3][1] / 2;
+ mid_offset[3][2] = mid_offset[3][2] / 2;
+ copy_m4_m4(amd->delta, offset);
numVerts = numEdges = numFaces = 0;
mvert = CDDM_get_verts(result);

@@ -402,15 +404,68 @@

/* if no merging, generate copies of this vert */
if(indexMap[i].merge < 0) {
+ if (amd->rays>1)
+ d_alp=0;
+
for(j=0; j < count - 1; j++) {
+ float rot[4][4];
mv2 = &mvert[numVerts];

DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
*mv2 = *mv;
numVerts++;
+ /*//Aggiungendo questa parte ed eliminando 1) e 2)
+ //si ottiene una spirale
+ mul_m4_v3(offset, co);
+ copy_v3_v3(mv2->co, co);*/
+ if (amd->rays>1)
+ {
+ float ro[3];
+ unit_m4(rot);
+ if (amd->rays_dir == MOD_ARR_RAYS_X)
+ rotate_m4(rot,'X',d_alp);
+ else if (amd->rays_dir == MOD_ARR_RAYS_Y)
+ rotate_m4(rot,'Y',d_alp);
+ else
+ rotate_m4(rot,'Z',d_alp);
+ if (d_alp == 0){
+ /*1)*/
+ mul_m4_v3(offset, co);
+ copy_v3_v3(mv2->co, co);
+ /******/
+ copy_v3_v3(ro, mv2->co);
+ mul_m4_v3(rot, ro);
+ copy_v3_v3(mv2->co, ro);
+ }
+ else{
+ copy_v3_v3(ro,co);
+ mul_m4_v3(rot, ro);
+ copy_v3_v3(mv2->co, ro);
+ }
+ d_alp = d_alp + alpha;
+ if (d_alp>6.2831)
+ d_alp=0;
+ }
+ else
+ {
+ /*2)*/
+ mul_m4_v3(offset, co);
+ copy_v3_v3(mv2->co, co);
+ /******/
+ }

- mul_m4_v3(offset, co);
- copy_v3_v3(mv2->co, co);
+ if (amd->mode & MOD_ARR_MOD_ADV)
+ {
+ if (amd->Mem_Ob[j].transform)
+ {
+ float fo[3];
+
+ copy_v3_v3(fo, mv2->co);
+ mul_m4_v3(amd->Mem_Ob[j].location, fo);
+ copy_v3_v3(mv2->co, fo);
+
+ }
+ }
}
} else if(indexMap[i].merge != i && indexMap[i].merge_final) {
/* if this vert is not merging with itself, and it is merging
@@ -555,6 +610,12 @@

numFaces++;

+ /*Rand Material*/
+ if ((flag = 1) && (amd->mode & MOD_ARR_MOD_ADV_MAT) && (ob->totcol>1))
+ {
+ mf2->mat_nr = amd->Mem_Ob[j-1].id_mat;
+ flag = 0;
+ }
/* if the face has fewer than 3 vertices, don't create it */
if(test_index_face_maxvert(mf2, &result->faceData, numFaces-1, inMF.v4?4:3, numVerts) < 3) {
numFaces--;
@@ -563,7 +624,7 @@
}
}

- /* add start and end caps */
+ /* add start, mid and end caps */
if(start_cap) {
float startoffset[4][4];
MVert *cap_mvert;
@@ -665,6 +726,112 @@
start_cap->release(start_cap);
}

+ /*insert_start_cap(amd, dm, result, start_cap, indexMap, edges, numVerts, numEdges, numFaces, offset);*/
+ if(mid_cap) {
+ MVert *cap_mvert;
+ MEdge *cap_medge;
+ MFace *cap_mface;
+ int *origindex;
+ int *vert_map;
+ int capVerts, capEdges, capFaces;
+
+ capVerts = mid_cap->getNumVerts(mid_cap);
+ capEdges = mid_cap->getNumEdges(mid_cap);
+ capFaces = mid_cap->getNumFaces(mid_cap);
+ cap_mvert = mid_cap->getVertArray(mid_cap);
+ cap_medge = mid_cap->getEdgeArray(mid_cap);
+ cap_mface = mid_cap->getFaceArray(mid_cap);
+
+ vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
+ "arrayModifier_doArray vert_map");
+ if (amd->cont_mid_cap>=amd->count)
+ amd->cont_mid_cap = amd->count -1;
+ for(j=0; j < amd->cont_mid_cap; j++) {
+ 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;
+
+ copy_v3_v3(tmp_co, mv->co);
+ mul_m4_v3(mid_offset, tmp_co);
+
+ for(j = 0; j < maxVerts; j++) {
+ in_mv = &src_mvert[j];
+ /* if this vert is within merge limit, merge */
+ if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
+ vert_map[i] = calc_mapping(indexMap, j, 0);
+ merged = 1;
+ break;
+ }
+ }
+ }
+
+ if(!merged) {
+ //for(j=0; j < amd->cont_mid_cap; j++) {
+ DM_copy_vert_data(mid_cap, result, i, numVerts, 1);
+ mvert[numVerts] = *mv;
+ mul_m4_v3(mid_offset, 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(mid_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(mid_cap, result, i, numFaces, 1);
+ mface[numFaces] = cap_mface[i];
+ mface[numFaces].v1 = vert_map[mface[numFaces].v1];
+ mface[numFaces].v2 = vert_map[mface[numFaces].v2];
+ mface[numFaces].v3 = vert_map[mface[numFaces].v3];
+ if(mface[numFaces].v4) {
+ mface[numFaces].v4 = vert_map[mface[numFaces].v4];
+
+ test_index_face_maxvert(&mface[numFaces], &result->faceData,
+ numFaces, 4, numVerts);
+ }
+ else
+ {
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 3);
+ }
+
+ origindex[numFaces] = ORIGINDEX_NONE;
+
+ numFaces++;
+ }
+ mul_m4_m4m4(tmp_mat, mid_offset, offset);
+ copy_m4_m4(mid_offset, tmp_mat);
+ }
+ MEM_freeN(vert_map);
+ mid_cap->release(mid_cap);
+ }
+
if(end_cap) {
float endoffset[4][4];
MVert *cap_mvert;
@@ -765,6 +932,16 @@
end_cap->release(end_cap);
}

+ if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
+ if (amd->distribution == MOD_ARR_DIST_EVENLY){
+ float (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "vertex_array_to_curve");
+
+ for (i=0; i<numVerts; i++)
+ VECCOPY(cos[i], mvert[i].co);
+ array_to_curve(scene, amd->curve_ob, ob, cos, numVerts);
+ }
+ }
+
BLI_edgehash_free(edges, NULL);
MEM_freeN(indexMap);

@@ -785,9 +962,20 @@

result = arrayModifier_doArray(amd, md->scene, ob, dm, 0);

- if(result != dm)
+ if(result != dm) {
CDDM_calc_normals(result);
-
+
+ if(amd->arr_group!=NULL)
+ {
+ ob->transflag = OB_DUPLIARRAY;
+ ob->dup_group = amd->arr_group;
+ }
+ else
+ {
+ ob->transflag = 0;
+ ob->dup_group = NULL;
+ }
+ }
return result;
}

@@ -798,6 +986,16 @@
return applyModifier(md, ob, dm, 0, 1);
}

+static void freeData(ModifierData *md)
+{
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ if (amd)
+ {
+ if (amd->Mem_Ob)
+ MEM_freeN(amd->Mem_Ob);
+ }
+}

ModifierTypeInfo modifierType_Array = {
/* name */ "Array",
@@ -819,12 +1017,11 @@
/* applyModifierEM */ applyModifierEM,
/* initData */ initData,
/* requiredDataMask */ NULL,
- /* freeData */ NULL,
+ /* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
};
Index: source/blender/render/intern/source/convertblender.c
===================================================================
--- source/blender/render/intern/source/convertblender.c (revisione 39737)
+++ source/blender/render/intern/source/convertblender.c (copia locale)
@@ -4713,7 +4713,8 @@
/* override not showing object when duplis are used with particles */
if(ob->transflag & OB_DUPLIPARTS)
; /* let particle system(s) handle showing vs. not showing */
- else if((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES))
+ else if((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES) &&
+ !(ob->transflag & OB_DUPLIARRAY))
return 0;

/* don't add non-basic meta objects, ends up having renderobjects with no geometry */
@@ -4750,7 +4751,7 @@
for(psys=obd->particlesystem.first; psys; psys=psys->next)
if(!ELEM5(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR))
return 0;
-
+
/* don't allow lamp, animated duplis, or radio render */
return (render_object_type(obd->type) &&
(!(dob->type == OB_DUPLIGROUP) || !dob->animated));
@@ -4817,17 +4818,19 @@
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;

+ //if((ob->transflag == OB_DUPLIARRAY) && dob->no_render)
+ // return;
/* recursively go into dupligroups to find objects with OB_RENDER_DUPLI
* that were not created yet */
for(go= group->gobject.first; go; go= go->next) {
ob= go->ob;
-
+
if(ob->flag & OB_DONE) {
if(ob->transflag & OB_RENDER_DUPLI) {
if(allow_render_object(re, ob, nolamps, onlyselected, actob)) {
init_render_object(re, ob, NULL, 0, timeoffset, vectorlay);
ob->transflag &= ~OB_RENDER_DUPLI;
-
+
if(ob->dup_group)
add_group_render_dupli_obs(re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, vectorlay, level+1);
}
@@ -4900,10 +4903,14 @@
Object *obd= dob->ob;

copy_m4_m4(obd->obmat, dob->mat);
-
+
+ if(!(obd->transflag & OB_DUPLIARRAY) && dob->no_render)
+ continue;
+
/* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */
- if(!(obd->transflag & OB_RENDER_DUPLI) && dob->no_draw)
- continue;
+ if (obd->transflag & OB_DUPLIARRAY)
+ if(!(obd->transflag & OB_RENDER_DUPLI) && dob->no_draw)
+ continue;

if(obd->restrictflag & OB_RESTRICT_RENDER)
continue;
@@ -4919,7 +4926,6 @@
ObjectRen *obr = NULL;
int psysindex;
float mat[4][4];
-
obi=NULL;

/* instances instead of the actual object are added in two cases, either
  1. Index: release/scripts/startup/bl_ui/properties_data_modifier.py
  2. ===================================================================
  3. --- release/scripts/startup/bl_ui/properties_data_modifier.py   (revisione 39737)
  4. +++ release/scripts/startup/bl_ui/properties_data_modifier.py   (copia locale)
  5. @@ -81,10 +81,10 @@
  6.              layout.prop(md, "curve")
  7.  
  8.          layout.separator()
  9. -
  10.          split = layout.split()
  11.  
  12.          col = split.column()
  13. +        col.prop(md,"rays")
  14.          col.prop(md, "use_constant_offset")
  15.          sub = col.column()
  16.          sub.active = md.use_constant_offset
  17. @@ -99,6 +99,7 @@
  18.          sub.prop(md, "merge_threshold", text="Distance")
  19.  
  20.          col = split.column()
  21. +        col.prop(md,"rays_dir")
  22.          col.prop(md, "use_relative_offset")
  23.          sub = col.column()
  24.          sub.active = md.use_relative_offset
  25. @@ -110,12 +111,90 @@
  26.          sub = col.column()
  27.          sub.active = md.use_object_offset
  28.          sub.prop(md, "offset_object", text="")
  29. -
  30. +        sub.prop(md, "use_between_offset")
  31.          layout.separator()
  32.  
  33.          layout.prop(md, "start_cap")
  34.          layout.prop(md, "end_cap")
  35. +        layout.prop(md, "mid_cap")
  36. +        act_mid = layout.row()
  37. +        if md.mid_cap is None :
  38. +            act_mid.active = False
  39. +        else:
  40. +            act_mid.active = True
  41. +        act_mid.prop(md, "cont_mid_cap")
  42. +        layout.separator()
  43.  
  44. +        if md.fit_type == 'FIT_CURVE':
  45. +            col = layout.column()
  46. +            row = col.box().row()
  47. +            if md.use_advanced_curve:
  48. +                row.prop(md, "use_advanced_curve",
  49. +                    icon="DOWNARROW_HLT", text="", emboss=False)
  50. +            else:
  51. +                row.prop(md, "use_advanced_curve",
  52. +                    icon="RIGHTARROW", text="", emboss=False)
  53. +            row.label("Advanced Curve")
  54. +            if (md.use_advanced_curve):
  55. +                col = col.box().column()
  56. +                sub_split = col.split()
  57. +                col = sub_split.column()
  58. +                col.prop(md, "all_curve")
  59. +                col = sub_split.column()
  60. +                col.prop(md, "for_segment")
  61. +
  62. +        col = layout.column()
  63. +        row = col.box().row()
  64. +        if md.use_advanced_material:
  65. +            row.prop(md, "use_advanced_material",
  66. +                icon="DOWNARROW_HLT", text="", emboss=False)
  67. +        else:
  68. +            row.prop(md, "use_advanced_material",
  69. +                icon="RIGHTARROW", text="", emboss=False)
  70. +        row.label("Advanced Material", icon="MATERIAL")
  71. +        if (md.use_advanced_material):
  72. +            col = col.box().column()
  73. +            row = col.row()
  74. +            row.prop(md, "material", expand=True)
  75. +            act = col.row()
  76. +            if md.material == 'SEQUENCE' :
  77. +                act.active = True
  78. +            else:
  79. +                act.active = False
  80. +            act.prop(md, "cont_mat")
  81. +
  82. +        col = layout.column()
  83. +        row = col.box().row()
  84. +        row.prop(md, "use_advanced", text="")
  85. +        row.label("Advanced Noise")
  86. +        if (md.use_advanced):
  87. +            col = col.box().column()
  88. +            row = col.row()
  89. +            row.label(text="Sign Offset:")
  90. +            row.prop(md, "sign_p")
  91. +            row.prop(md, "sign_l")
  92. +            off_box = col.row()
  93. +            off_box.column().prop(md, "location_offset", text="Location")
  94. +            off_box.column().prop(md, "rotation_offset", text="Rotation")
  95. +            off_box2 = off_box.split().column()
  96. +            off_box2.column().prop(md, "proportion", text="Scale")
  97. +            if (md.proportion):
  98. +                off_box2.column().prop(md, "scale", text="")
  99. +            else:
  100. +                off_box2.column().prop(md, "scale_offset", text="")
  101. +            col.separator()
  102. +            row = col.row()
  103. +            row.prop(md, "array_group")
  104. +            act = row.row()
  105. +            if md.array_group is None :
  106. +                act.active = False
  107. +            else:
  108. +                act.active = True
  109. +            act.prop(md, "rand_group")
  110. +            col = col.column()
  111. +            col.separator()
  112. +        layout.operator("object.array_rand", text="Refresh Ad. Offset")
  113. +
  114.      def BEVEL(self, layout, ob, md):
  115.          split = layout.split()
  116.  
  117. Index: source/blender/blenkernel/BKE_ama.h
  118. ===================================================================
  119. --- source/blender/blenkernel/BKE_ama.h (revisione 0)
  120. +++ source/blender/blenkernel/BKE_ama.h (revisione 0)
  121. @@ -0,0 +1,84 @@
  122. +/*
  123. + * ***** BEGIN GPL LICENSE BLOCK *****
  124. + *
  125. + * This program is free software; you can redistribute it and/or
  126. + * modify it under the terms of the GNU General Public License
  127. + * as published by the Free Software Foundation; either version 2
  128. + * of the License, or (at your option) any later version.
  129. + *
  130. + * This program is distributed in the hope that it will be useful,
  131. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  132. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  133. + * GNU General Public License for more details.
  134. + *
  135. + * You should have received a copy of the GNU General Public License
  136. + * along with this program; if not, write to the Free Software Foundation,
  137. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  138. + *
  139. + * The Original Code is Copyright (C) Blender Foundation.
  140. + * All rights reserved.
  141. + *
  142. + * The Original Code is: all of this file.
  143. + *
  144. + * Contributor(s): none yet.
  145. + *
  146. + * ***** END GPL LICENSE BLOCK *****
  147. + */
  148. +#ifndef BKE_AMA_H
  149. +#define BKE_AMA_H
  150. +
  151. +/** \file BKE_ama.h
  152. + *  \ingroup bke
  153. + */
  154. +
  155. +struct ArrayModifierData;
  156. +struct Object;
  157. +struct Scene;
  158. +struct MVert;
  159. +struct MFace;
  160. +struct DerivedMesh;
  161. +struct CustomData;
  162. +struct EdgeHash;
  163. +
  164. +typedef struct IndexMapEntry {
  165. +       /* the new vert index that this old vert index maps to */
  166. +       int new;
  167. +       /* -1 if this vert isn't merged, otherwise the old vert index it
  168. +       * should be replaced with
  169. +       */
  170. +       int merge;
  171. +       /* 1 if this vert's first copy is merged with the last copy of its
  172. +       * merge target, otherwise 0
  173. +       */
  174. +       short merge_final;
  175. +} IndexMapEntry;
  176. +
  177. +
  178. +/* calculations is in local space of deformed object
  179. +          so we store in latmat transform from path coord inside object
  180. +        */
  181. +typedef struct {
  182. +       float dmin[3], dmax[3], dsize, dloc[3];
  183. +       float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
  184. +       int no_rot_axis;
  185. +} CurveDeform;
  186. +
  187. +
  188. +float vertarray_size(struct MVert *mvert, int numVerts, int axis);
  189. +int test_index_face_maxvert(struct MFace *mface, struct CustomData *fdata, int mfindex, int nr, int maxvert);
  190. +int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum);
  191. +
  192. +float length_fitcurve(struct ArrayModifierData *amd, struct Scene *scene);
  193. +int length_to_count(float length, const float offset[3]);
  194. +float count_to_length(int count, const float offset[3]);
  195. +float f_rand_max(float max);
  196. +void array_scale_offset(const float max_off[3], float rit[3],int prop);
  197. +void array_offset(const float max_off[3], float rit[3],int sign);
  198. +void init_offset(const int start, const int end, struct ArrayModifierData *ar);
  199. +void create_offset(const int n, const int totmat, struct ArrayModifierData *ar, struct Object *ob);
  200. +void array_to_curve(struct Scene *scene, struct Object *cuOb, struct Object *target, float (*vertexCos)[3], int numVerts);
  201. +/*struct DerivedMesh *insert_start_cap(struct ArrayModifierData *amd, struct DerivedMesh *dm, struct DerivedMesh *result, struct DerivedMesh *start_cap, IndexMapEntry *indexMap,
  202. +       struct EdgeHash *edges, int numVerts, int numEdges, int numFaces, float offset[4][4]);*/
  203. +
  204. +#endif
  205. +
  206. Index: source/blender/blenkernel/CMakeLists.txt
  207. ===================================================================
  208. --- source/blender/blenkernel/CMakeLists.txt    (revisione 39737)
  209. +++ source/blender/blenkernel/CMakeLists.txt    (copia locale)
  210. @@ -73,6 +73,7 @@
  211.         intern/CCGSubSurf.c
  212.         intern/DerivedMesh.c
  213.         intern/action.c
  214. +       intern/ama.c
  215.         intern/anim.c
  216.         intern/anim_sys.c
  217.         intern/armature.c
  218. @@ -152,6 +153,7 @@
  219.         
  220.         BKE_DerivedMesh.h
  221.         BKE_action.h
  222. +       BKE_ama.h
  223.         BKE_anim.h
  224.         BKE_animsys.h
  225.         BKE_armature.h
  226. Index: source/blender/blenkernel/intern/ama.c
  227. ===================================================================
  228. --- source/blender/blenkernel/intern/ama.c      (revisione 0)
  229. +++ source/blender/blenkernel/intern/ama.c      (revisione 0)
  230. @@ -0,0 +1,625 @@
  231. +/*
  232. + * $Id: ama.c 36773 2011-08-13 13:46:00Z ruesp83 $
  233. + *
  234. + * ***** BEGIN GPL LICENSE BLOCK *****
  235. + *
  236. + * This program is free software; you can redistribute it and/or
  237. + * modify it under the terms of the GNU General Public License
  238. + * as published by the Free Software Foundation; either version 2
  239. + * of the License, or (at your option) any later version.
  240. + *
  241. + * This program is distributed in the hope that it will be useful,
  242. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  243. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  244. + * GNU General Public License for more details.
  245. + *
  246. + * You should have received a copy of the GNU General Public License
  247. + * along with this program; if not, write to the Free Software Foundation,
  248. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  249. + *
  250. + * The Original Code is Copyright (C) Blender Foundation.
  251. + * All rights reserved.
  252. + *
  253. + * The Original Code is: all of this file.
  254. + *
  255. + * Contributor(s): Fabio Russo
  256. + *
  257. + * ***** END GPL LICENSE BLOCK *****
  258. + */
  259. +
  260. +/** \file blender/blenkernel/intern/ama.c
  261. + *  \ingroup bke
  262. + */
  263. +
  264. +#include "MEM_guardedalloc.h"
  265. +#include "BLI_math.h"
  266. +#include "BLI_utildefines.h"
  267. +#include "BLI_rand.h"
  268. +#include "BLI_listbase.h"
  269. +#include "BLI_edgehash.h"
  270. +#include "DNA_group_types.h"
  271. +#include "DNA_object_types.h"
  272. +#include "DNA_curve_types.h"
  273. +#include "DNA_modifier_types.h"
  274. +#include "DNA_meshdata_types.h"
  275. +#include "DNA_scene_types.h"
  276. +#include "BKE_object.h"
  277. +#include "BKE_displist.h"
  278. +#include "BKE_ama.h"
  279. +#include "BKE_anim.h"
  280. +#include "BKE_cdderivedmesh.h"
  281. +#include "BKE_mesh.h"
  282. +
  283. +
  284. +float vertarray_size(MVert *mvert, int numVerts, int axis)
  285. +{
  286. +       int i;
  287. +       float min_co, max_co;
  288. +
  289. +       /* if there are no vertices, width is 0 */
  290. +       if(numVerts == 0) return 0;
  291. +
  292. +       /* find the minimum and maximum coordinates on the desired axis */
  293. +       min_co = max_co = mvert->co[axis];
  294. +       ++mvert;
  295. +       for(i = 1; i < numVerts; ++i, ++mvert) {
  296. +               if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
  297. +               if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
  298. +       }
  299. +
  300. +       return max_co - min_co;
  301. +}
  302. +
  303. +
  304. +/* XXX This function fixes bad merging code, in some cases removing vertices creates indices > maxvert */
  305. +int test_index_face_maxvert(MFace *mface, CustomData *fdata, int mfindex, int nr, int maxvert)
  306. +{
  307. +       if(mface->v1 >= maxvert) {
  308. +               // printf("bad index in array\n");
  309. +               mface->v1= maxvert - 1;
  310. +       }
  311. +       if(mface->v2 >= maxvert) {
  312. +               // printf("bad index in array\n");
  313. +               mface->v2= maxvert - 1;
  314. +       }
  315. +       if(mface->v3 >= maxvert) {
  316. +               // printf("bad index in array\n");
  317. +               mface->v3= maxvert - 1;
  318. +       }
  319. +       if(mface->v4 >= maxvert) {
  320. +               // printf("bad index in array\n");
  321. +               mface->v4= maxvert - 1;
  322. +       }
  323. +       
  324. +       return test_index_face(mface, fdata, mfindex, nr);
  325. +}
  326. +
  327. +
  328. +/* indexMap - an array of IndexMap entries
  329. + * oldIndex - the old index to map
  330. + * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
  331. + */
  332. +int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
  333. +{
  334. +       if(indexMap[oldIndex].merge < 0) {
  335. +               /* vert wasn't merged, so use copy of this vert */
  336. +               return indexMap[oldIndex].new + copyNum;
  337. +       } else if(indexMap[oldIndex].merge == oldIndex) {
  338. +               /* vert was merged with itself */
  339. +               return indexMap[oldIndex].new;
  340. +       } else {
  341. +               /* vert was merged with another vert */
  342. +               /* follow the chain of merges to the end, or until we've passed
  343. +               * a number of vertices equal to the copy number
  344. +               */
  345. +               if(copyNum <= 0)
  346. +                       return indexMap[oldIndex].new;
  347. +               else
  348. +                       return calc_mapping(indexMap, indexMap[oldIndex].merge,
  349. +                                               copyNum - 1);
  350. +       }
  351. +}
  352. +
  353. +
  354. +float length_fitcurve(ArrayModifierData *amd, struct Scene *scene)
  355. +{
  356. +       float length = 0;
  357. +
  358. +       Curve *cu = amd->curve_ob->data;
  359. +       if(cu) {
  360. +               float tmp_mat[3][3];
  361. +               float scale;
  362. +                      
  363. +               object_to_mat3(amd->curve_ob, tmp_mat);
  364. +               scale = mat3_to_scale(tmp_mat);
  365. +
  366. +               if(!cu->path) {
  367. +                       cu->flag |= CU_PATH; // needed for path & bevlist
  368. +                       makeDispListCurveTypes(scene, amd->curve_ob, 0);
  369. +               }
  370. +               if(cu->path)
  371. +                       length = scale*cu->path->totdist;
  372. +       }
  373. +       return length;
  374. +}
  375. +
  376. +
  377. +int length_to_count(float length, const float offset[3])
  378. +{
  379. +       int count = 0;
  380. +
  381. +       float dist = sqrt(dot_v3v3(offset, offset));
  382. +
  383. +       if(dist > 1e-6f)
  384. +               /* this gives length = first copy start to last copy end
  385. +               add a tiny offset for floating point rounding errors */
  386. +               count = (length + 1e-6f) / dist;
  387. +       else
  388. +               /* if the offset has no translation, just make one copy */
  389. +               count = 1;
  390. +       return count;
  391. +}
  392. +
  393. +
  394. +float count_to_length(int count, const float offset[3])
  395. +{
  396. +       float length = 0;
  397. +       float dist = sqrt(dot_v3v3(offset, offset));
  398. +
  399. +       if(dist > 1e-6f)
  400. +               /* this gives length = first copy start to last copy end
  401. +               add a tiny offset for floating point rounding errors */
  402. +               //count = (length + 1e-6f) / dist;
  403. +               length = count * dist - 1e-6f;
  404. +       else
  405. +               /* if the offset has no translation, just make one copy */
  406. +               length = 1;
  407. +       return length;
  408. +}
  409. +
  410. +
  411. +//generates a psuedo-random float between 0.0 and max
  412. +float f_rand_max(float max)
  413. +{
  414. +       return BLI_frand()*max;
  415. +}
  416. +
  417. +
  418. +void array_scale_offset(const float max_off[3], float rit[3],int prop)
  419. +{
  420. +       //TODO:far valere anche valori meno di uno,
  421. +       //così si possono ottenere oggetti anche più piccoli dell'originale
  422. +              
  423. +       rit[0] = f_rand_max(max_off[0]);
  424. +       rit[0] = 1+rit[0];
  425. +       
  426. +       if (!prop)
  427. +       {
  428. +               rit[1] = f_rand_max(max_off[1]);
  429. +               rit[1] = 1+rit[1];
  430. +              
  431. +               rit[2] = f_rand_max(max_off[2]);
  432. +               rit[2] = 1+rit[2];
  433. +       }
  434. +       else
  435. +       {
  436. +               rit[1] = rit[0];
  437. +               rit[2] = rit[0];
  438. +       }
  439. +}
  440. +
  441. +
  442. +void array_offset(const float max_off[3], float rit[3],int sign)
  443. +{     
  444. +       int j;
  445. +       
  446. +       rit[0] = f_rand_max(max_off[0]);
  447. +       if (sign & MOD_ARR_SIGN_L)
  448. +       {
  449. +               if (sign & MOD_ARR_SIGN_P)
  450. +               {
  451. +                       j = BLI_rand() % 2;
  452. +                       if (j == 0)
  453. +                               rit[0] = rit[0]*(-1);
  454. +               }
  455. +               else
  456. +                       rit[0] = rit[0]*(-1);
  457. +       }
  458. +              
  459. +       rit[1] = f_rand_max(max_off[1]);
  460. +       if (sign & MOD_ARR_SIGN_L)
  461. +       {
  462. +               if (sign & MOD_ARR_SIGN_P)
  463. +               {
  464. +                       j = BLI_rand() % 2;
  465. +                       if (j == 0)
  466. +                               rit[1] = rit[1]*(-1);
  467. +               }
  468. +               else
  469. +                       rit[1] = rit[1]*(-1);
  470. +       }
  471. +
  472. +       rit[2] = f_rand_max(max_off[2]);
  473. +       if (sign & MOD_ARR_SIGN_L)
  474. +       {
  475. +               if (sign & MOD_ARR_SIGN_P)
  476. +               {
  477. +                       j = BLI_rand() % 2;
  478. +                       if (j == 0)
  479. +                               rit[2] = rit[2]*(-1);
  480. +               }
  481. +               else
  482. +                       rit[2] = rit[2]*(-1);
  483. +       }
  484. +}
  485. +
  486. +
  487. +void init_offset(const int start, const int end, ArrayModifierData *ar)
  488. +{
  489. +       int i;
  490. +
  491. +       for (i=start; i< end; i++)
  492. +       {
  493. +               unit_m4(ar->Mem_Ob[i].location);
  494. +               ar->Mem_Ob[i].id_mat = 0;
  495. +               ar->Mem_Ob[i].transform = 0;
  496. +               ar->Mem_Ob[i].rand_group_obj = 0;
  497. +       }
  498. +}
  499. +
  500. +
  501. +void create_offset(const int n, const int totmat, ArrayModifierData *ar, Object *ob)
  502. +{
  503. +       float loc[3];
  504. +       float rot[3];
  505. +       float rotAxis[3];
  506. +       float scale[3];
  507. +       int i, act_mat = 0;
  508. +       int cont_mat = ar->cont_mat-1;
  509. +       Group *group;
  510. +
  511. +       if(ob->dup_group!=NULL)
  512. +               group= ob->dup_group;
  513. +
  514. +       scale[0]=scale[1]=scale[2]=1;
  515. +
  516. +       for (i=0; i < n-1; i++)
  517. +       {
  518. +               if (ar->mode & MOD_ARR_MOD_ADV)
  519. +               {
  520. +                       if ((ar->rot_offset[0]!=0) || (ar->rot_offset[1]!=0) || (ar->rot_offset[2]!=0))
  521. +                       {
  522. +                               array_offset(ar->rot_offset, rot, ar->sign);
  523. +                               ar->Mem_Ob[i].transform=1;
  524. +                       }
  525. +                       if ((ar->scale_offset[0]!=0) || (ar->scale_offset[1]!=0) || (ar->scale_offset[2]!=0))
  526. +                       {
  527. +                               array_scale_offset(ar->scale_offset, scale, ar->proportion);
  528. +                               ar->Mem_Ob[i].transform=1;
  529. +                       }
  530. +                       if ((ar->loc_offset[0]!=0) || (ar->loc_offset[1]!=0) || (ar->loc_offset[2]!=0))
  531. +                       {
  532. +                               array_offset(ar->loc_offset, loc, ar->sign);
  533. +                               ar->Mem_Ob[i].transform=1;
  534. +                       }
  535. +                       if (ar->Mem_Ob[i].transform)
  536. +                       {
  537. +                               loc_eul_size_to_mat4(ar->Mem_Ob[i].location, loc, rot, scale);
  538. +                       }
  539. +                       if (ar->rand_group & MOD_ARR_RAND_GROUP)
  540. +                       {
  541. +                               ar->Mem_Ob[i].rand_group_obj = BLI_rand() % BLI_countlist(&group->gobject);
  542. +                               ar->Mem_Ob[i].rand_group_obj++;
  543. +                       }
  544. +               }
  545. +               if (ar->mode & MOD_ARR_MOD_ADV_MAT)
  546. +               {
  547. +                       if (totmat>1)
  548. +                       {
  549. +                               if (ar->rand_mat & MOD_ARR_MAT) {
  550. +                                       ar->Mem_Ob[i].id_mat = BLI_rand() % totmat;
  551. +                               }
  552. +                               else {
  553. +                                       if (cont_mat == 0 ){
  554. +                                               cont_mat = ar->cont_mat;
  555. +                                               if (act_mat + 1 < totmat)
  556. +                                                       act_mat++;
  557. +                                               else
  558. +                                                       act_mat = 0;
  559. +                                       }
  560. +                                       ar->Mem_Ob[i].id_mat = act_mat;
  561. +                                       cont_mat--;
  562. +                               }
  563. +                       }
  564. +               }
  565. +              
  566. +       }
  567. +}
  568. +
  569. +
  570. +static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd, int dloc)
  571. +{
  572. +       invert_m4_m4(ob->imat, ob->obmat);
  573. +       mul_m4_m4m4(cd->objectspace, par->obmat, ob->imat);
  574. +       invert_m4_m4(cd->curvespace, cd->objectspace);
  575. +       copy_m3_m4(cd->objectspace3, cd->objectspace);
  576. +       
  577. +       // offset vector for 'no smear'
  578. +       if(dloc) {
  579. +               invert_m4_m4(par->imat, par->obmat);
  580. +               mul_v3_m4v3(cd->dloc, par->imat, ob->obmat[3]);
  581. +       }
  582. +       else {
  583. +               cd->dloc[0]=cd->dloc[1]=cd->dloc[2]= 0.0f;
  584. +       }
  585. +
  586. +       cd->no_rot_axis= 0;
  587. +}
  588. +
  589. +
  590. +/* this makes sure we can extend for non-cyclic. *vec needs 4 items! */
  591. +static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius)   /* returns OK */
  592. +{
  593. +       Curve *cu= ob->data;
  594. +       BevList *bl;
  595. +       float ctime1;
  596. +       int cycl=0;
  597. +       
  598. +       /* test for cyclic */
  599. +       bl= cu->bev.first;
  600. +       if (!bl->nr) return 0;
  601. +       if(bl && bl->poly> -1) cycl= 1;
  602. +
  603. +       if(cycl==0) {
  604. +               ctime1= CLAMPIS(ctime, 0.0f, 1.0f);
  605. +       }
  606. +       else ctime1= ctime;
  607. +       
  608. +       /* vec needs 4 items */
  609. +       if(where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
  610. +              
  611. +               if(cycl==0) {
  612. +                       Path *path= cu->path;
  613. +                       float dvec[3];
  614. +                      
  615. +                       if(ctime < 0.0f) {
  616. +                               sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec);
  617. +                               mul_v3_fl(dvec, ctime*(float)path->len);
  618. +                               add_v3_v3(vec, dvec);
  619. +                               if(quat) copy_qt_qt(quat, path->data[0].quat);
  620. +                               if(radius) *radius= path->data[0].radius;
  621. +                       }
  622. +                       else if(ctime > 1.0f) {
  623. +                               sub_v3_v3v3(dvec, path->data[path->len-1].vec, path->data[path->len-2].vec);
  624. +                               mul_v3_fl(dvec, (ctime-1.0f)*(float)path->len);
  625. +                               add_v3_v3(vec, dvec);
  626. +                               if(quat) copy_qt_qt(quat, path->data[path->len-1].quat);
  627. +                               if(radius) *radius= path->data[path->len-1].radius;
  628. +                               /* weight - not used but could be added */
  629. +                       }
  630. +               }
  631. +               return 1;
  632. +       }
  633. +       return 0;
  634. +}
  635. +
  636. +
  637. +       /* for each point, rotate & translate to curve */
  638. +       /* use path, since it has constant distances */
  639. +       /* co: local coord, result local too */
  640. +       /* returns quaternion for rotation, using cd->no_rot_axis */
  641. +       /* axis is using another define!!! */
  642. +static int calc_curve_deform(Scene *scene, Object *par, float *co, CurveDeform *cd, float *quatp)
  643. +{
  644. +       Curve *cu= par->data;
  645. +       float fac, loc[4], dir[3], new_quat[4], radius;
  646. +       
  647. +       /* to be sure, mostly after file load */
  648. +       if(cu->path==NULL) {
  649. +               makeDispListCurveTypes(scene, par, 0);
  650. +               if(cu->path==NULL) return 0;    // happens on append...
  651. +       }
  652. +       fac=0;
  653. +       if( where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) {      /* returns OK */
  654. +               float quat[4], cent[3];
  655. +
  656. +               if(cd->no_rot_axis) {   /* set by caller */
  657. +
  658. +                       /* this is not exactly the same as 2.4x, since the axis is having rotation removed rather than
  659. +                        * changing the axis before calculating the tilt but serves much the same purpose */
  660. +                       float dir_flat[3]={0,0,0}, q[4];
  661. +                       copy_v3_v3(dir_flat, dir);
  662. +                       dir_flat[cd->no_rot_axis-1]= 0.0f;
  663. +
  664. +                       normalize_v3(dir);
  665. +                       normalize_v3(dir_flat);
  666. +
  667. +                       rotation_between_vecs_to_quat(q, dir, dir_flat); /* Could this be done faster? */
  668. +
  669. +                       mul_qt_qtqt(new_quat, q, new_quat);
  670. +               }
  671. +
  672. +
  673. +               /* Logic for 'cent' orientation *
  674. +                *
  675. +                * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
  676. +                *
  677. +                * Use a curve modifier to stretch a cube out, color each side RGB, positive side light, negative dark.
  678. +                * view with X up (default), from the angle that you can see 3 faces RGB colors (light), anti-clockwise
  679. +                * Notice X,Y,Z Up all have light colors and each ordered CCW.
  680. +                *
  681. +                * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
  682. +                *
  683. +                * note: moved functions into quat_apply_track/vec_apply_track
  684. +                * */
  685. +               copy_qt_qt(quat, new_quat);
  686. +               copy_v3_v3(cent, co);
  687. +
  688. +               /* zero the axis which is not used,
  689. +                * the big block of text above now applies to these 3 lines */
  690. +               //quat_apply_track(quat, axis-1, (axis==1 || axis==3) ? 1:0); /* up flag is a dummy, set so no rotation is done */
  691. +               //vec_apply_track(cent, axis-1);
  692. +               //cent[axis < 4 ? axis-1 : axis-4]= 0.0f;
  693. +
  694. +
  695. +               /* scale if enabled */
  696. +               if(cu->flag & CU_PATH_RADIUS)
  697. +                       mul_v3_fl(cent, radius);
  698. +              
  699. +               /* local rotation */
  700. +               normalize_qt(quat);
  701. +               mul_qt_v3(quat, cent);
  702. +
  703. +               /* translation */
  704. +               add_v3_v3v3(co, cent, loc);
  705. +
  706. +               if(quatp)
  707. +                       copy_qt_qt(quatp, quat);
  708. +
  709. +               return 1;
  710. +       }
  711. +       return 0;
  712. +}
  713. +
  714. +
  715. +void array_to_curve(Scene *scene, Object *cuOb, Object *target, float (*vertexCos)[3], int numVerts)
  716. +{
  717. +       Curve *cu;
  718. +       int a, flag;
  719. +       CurveDeform cd;
  720. +       int use_vgroups;
  721. +              
  722. +       if(cuOb->type != OB_CURVE)
  723. +               return;
  724. +
  725. +       cu = cuOb->data;
  726. +       flag = cu->flag;
  727. +       cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist
  728. +
  729. +       init_curve_deform(cuOb, target, &cd, (cu->flag & CU_STRETCH)==0);
  730. +
  731. +       for(a = 0; a < numVerts; a++) {
  732. +               mul_m4_v3(cd.curvespace, vertexCos[a]);
  733. +       }
  734. +       
  735. +       for(a = 0; a < numVerts; a++) {
  736. +               calc_curve_deform(scene, cuOb, vertexCos[a], &cd, NULL);
  737. +               mul_m4_v3(cd.objectspace, vertexCos[a]);
  738. +       }
  739. +       cu->flag = flag;
  740. +}
  741. +
  742. +
  743. +/*DerivedMesh *insert_start_cap(ArrayModifierData *amd, DerivedMesh *dm, DerivedMesh *result, DerivedMesh *start_cap, IndexMapEntry *indexMap,
  744. +       EdgeHash *edges, int numVerts, int numEdges, int numFaces, float offset[4][4])
  745. +{
  746. +/* add start and end caps */
  747. +/*     if(start_cap) {
  748. +               float startoffset[4][4];
  749. +               MVert *cap_mvert, *mvert, *src_mvert;
  750. +               MEdge *cap_medge, *medge;
  751. +               MFace *cap_mface, *mface;
  752. +               int *origindex;
  753. +               int *vert_map;
  754. +               int capVerts, capEdges, capFaces;
  755. +               int maxVerts, i;
  756. +
  757. +               maxVerts = dm->getNumVerts(dm);
  758. +               mvert = CDDM_get_verts(result);
  759. +               medge = CDDM_get_edges(result);
  760. +               mface = CDDM_get_faces(result);
  761. +               src_mvert = dm->getVertArray(dm);
  762. +
  763. +               capVerts = start_cap->getNumVerts(start_cap);
  764. +               capEdges = start_cap->getNumEdges(start_cap);
  765. +               capFaces = start_cap->getNumFaces(start_cap);
  766. +               cap_mvert = start_cap->getVertArray(start_cap);
  767. +               cap_medge = start_cap->getEdgeArray(start_cap);
  768. +               cap_mface = start_cap->getFaceArray(start_cap);
  769. +
  770. +               invert_m4_m4(startoffset, offset);
  771. +
  772. +               vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
  773. +               "arrayModifier_doArray vert_map");
  774. +
  775. +               origindex = result->getVertDataArray(result, CD_ORIGINDEX);
  776. +               for(i = 0; i < capVerts; i++) {
  777. +                       MVert *mv = &cap_mvert[i];
  778. +                       short merged = 0;
  779. +
  780. +                       if(amd->flags & MOD_ARR_MERGE) {
  781. +                               float tmp_co[3];
  782. +                               MVert *in_mv;
  783. +                               int j;
  784. +
  785. +                               copy_v3_v3(tmp_co, mv->co);
  786. +                               mul_m4_v3(startoffset, tmp_co);
  787. +
  788. +                               for(j = 0; j < maxVerts; j++) {
  789. +                                       in_mv = &src_mvert[j];
  790. +                                       /* if this vert is within merge limit, merge */
  791. +/*                                     if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
  792. +                                               vert_map[i] = calc_mapping(indexMap, j, 0);
  793. +                                               merged = 1;
  794. +                                               break;
  795. +                                       }
  796. +                               }
  797. +                       }
  798. +
  799. +                       if(!merged) {
  800. +                               DM_copy_vert_data(start_cap, result, i, numVerts, 1);
  801. +                               mvert[numVerts] = *mv;
  802. +                               mul_m4_v3(startoffset, mvert[numVerts].co);
  803. +                               origindex[numVerts] = ORIGINDEX_NONE;
  804. +
  805. +                               vert_map[i] = numVerts;
  806. +
  807. +                               numVerts++;
  808. +                       }
  809. +               }
  810. +               origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
  811. +               for(i = 0; i < capEdges; i++) {
  812. +                       int v1, v2;
  813. +
  814. +                       v1 = vert_map[cap_medge[i].v1];
  815. +                       v2 = vert_map[cap_medge[i].v2];
  816. +
  817. +                       if(!BLI_edgehash_haskey(edges, v1, v2)) {
  818. +                               DM_copy_edge_data(start_cap, result, i, numEdges, 1);
  819. +                               medge[numEdges] = cap_medge[i];
  820. +                               medge[numEdges].v1 = v1;
  821. +                               medge[numEdges].v2 = v2;
  822. +                               origindex[numEdges] = ORIGINDEX_NONE;
  823. +
  824. +                               numEdges++;
  825. +                       }
  826. +               }
  827. +               origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
  828. +               for(i = 0; i < capFaces; i++) {
  829. +                       DM_copy_face_data(start_cap, result, i, numFaces, 1);
  830. +                       mface[numFaces] = cap_mface[i];
  831. +                       mface[numFaces].v1 = vert_map[mface[numFaces].v1];
  832. +                       mface[numFaces].v2 = vert_map[mface[numFaces].v2];
  833. +                       mface[numFaces].v3 = vert_map[mface[numFaces].v3];
  834. +                       if(mface[numFaces].v4) {
  835. +                               mface[numFaces].v4 = vert_map[mface[numFaces].v4];
  836. +
  837. +                               test_index_face_maxvert(&mface[numFaces], &result->faceData,
  838. +                               numFaces, 4, numVerts);
  839. +                       }
  840. +                       else
  841. +                       {
  842. +                               test_index_face(&mface[numFaces], &result->faceData,
  843. +                               numFaces, 3);
  844. +                       }
  845. +
  846. +                       origindex[numFaces] = ORIGINDEX_NONE;
  847. +
  848. +                       numFaces++;
  849. +               }
  850. +
  851. +               MEM_freeN(vert_map);
  852. +               start_cap->release(start_cap);
  853. +       }
  854. +       return result;
  855. +}*/
  856. Index: source/blender/blenkernel/intern/anim.c
  857. ===================================================================
  858. --- source/blender/blenkernel/intern/anim.c     (revisione 39737)
  859. +++ source/blender/blenkernel/intern/anim.c     (copia locale)
  860. @@ -35,6 +35,7 @@
  861.  
  862.  
  863.  #include <stdio.h>
  864. +#include <time.h>
  865.  #include <math.h>
  866.  #include <string.h>
  867.  
  868. @@ -51,6 +52,7 @@
  869.  #include "DNA_group_types.h"
  870.  #include "DNA_key_types.h"
  871.  #include "DNA_meshdata_types.h"
  872. +#include "DNA_modifier_types.h"
  873.  #include "DNA_scene_types.h"
  874.  #include "DNA_vfont_types.h"
  875.  
  876. @@ -751,6 +753,137 @@
  877.         }
  878.  }
  879.  
  880. +static void group_arrayduplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated)
  881. +{
  882. +       DupliObject *dob;
  883. +       Group *group;
  884. +       GroupObject *go;
  885. +       float mat[4][4], tmat[4][4], offset[4][4], rot[4][4];
  886. +       ModifierData *md;
  887. +       int i, cont_rnd;
  888. +       float d_alp, alpha;
  889. +       
  890. +       if(ob->dup_group==NULL) return;
  891. +               group= ob->dup_group;
  892. +       
  893. +       /* simple preventing of too deep nested groups */
  894. +       if(level>MAX_DUPLI_RECUR) return;
  895. +       
  896. +       /* handles animated groups, and */
  897. +       /* we need to check update for objects that are not in scene... */
  898. +       group_handle_recalc_and_update(scene, ob, group);
  899. +       animated= animated || group_is_animated(ob, group);
  900. +
  901. +       for(md=ob->modifiers.first; md; md=md->next) {
  902. +               if(md->type == eModifierType_Array) {
  903. +                       if (md->mode&eModifierMode_Realtime || md->mode&eModifierMode_Render){
  904. +                               ArrayModifierData *amd = (ArrayModifierData*) md;
  905. +
  906. +                               d_alp=0;
  907. +                               if (amd->rays > 1)
  908. +                                       alpha = (float)6.2831 / amd->rays;
  909. +                               copy_m4_m4(offset, amd->delta);
  910. +                                      
  911. +                               for (i = 0; i < amd->count-1; i++)
  912. +                               {
  913. +                                       cont_rnd = 0;
  914. +                                       for(go= group->gobject.first; go; go= go->next)
  915. +                                       {
  916. +                                               cont_rnd++;
  917. +                                               /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
  918. +                                               if(go->ob!=ob)
  919. +                                               {
  920. +                                                       if (amd->rand_group & MOD_ARR_RAND_GROUP)
  921. +                                                       {
  922. +                                                               if ((amd->Mem_Ob[i].rand_group_obj != 0) && (amd->Mem_Ob[i].rand_group_obj != cont_rnd))
  923. +                                                                       continue;
  924. +                                                       }
  925. +                                                       /* Group Dupli Offset, should apply after everything else */
  926. +                                                       if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) {
  927. +                                                               copy_m4_m4(tmat, go->ob->obmat);
  928. +                                                               sub_v3_v3v3(tmat[3], tmat[3], group->dupli_ofs);
  929. +                                                               mul_m4_m4m4(mat, tmat, ob->obmat);
  930. +                                                       } else {
  931. +                                                               mul_m4_m4m4(mat, go->ob->obmat, ob->obmat);
  932. +                                                       }
  933. +                                              
  934. +                                                       copy_m4_m4(tmat, mat);
  935. +                                                       if (amd->rays>1)
  936. +                                                       {
  937. +                                                               unit_m4(rot);
  938. +                                                               if (amd->rays_dir == MOD_ARR_RAYS_X)
  939. +                                                                       rotate_m4(rot,'X',d_alp);
  940. +                                                               else if (amd->rays_dir == MOD_ARR_RAYS_Y)
  941. +                                                                       rotate_m4(rot,'Y',d_alp);
  942. +                                                               else
  943. +                                                                       rotate_m4(rot,'Z',d_alp);
  944. +                                                               if (d_alp == 0){
  945. +                                                                       mul_m4_m4m4(mat, offset, tmat);
  946. +
  947. +                                                                       copy_m4_m4(tmat, mat);
  948. +                                                                       mul_m4_m4m4(mat, rot, tmat);
  949. +                                                               }
  950. +                                                               else{
  951. +                                                                       mul_m4_m4m4(mat, offset, tmat);
  952. +
  953. +                                                                       copy_m4_m4(tmat, mat);
  954. +                                                                       mul_m4_m4m4(mat, rot, tmat);
  955. +                                                               }
  956. +                                                       }
  957. +                                                       else
  958. +                                                       {
  959. +                                                               mul_m4_m4m4(mat, offset, tmat);
  960. +                                                       }
  961. +                                                       //Noise
  962. +                                                       if (amd->mode & MOD_ARR_MOD_ADV)
  963. +                                                       {
  964. +                                                               if (amd->Mem_Ob[i].transform == 1)
  965. +                                                               {
  966. +                                                                       copy_m4_m4(tmat, mat);
  967. +                                                                       mul_m4_m4m4(mat, amd->Mem_Ob[i].location, tmat);
  968. +                                                               }
  969. +                                                       }
  970. +                                              
  971. +                                                       dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIARRAY, animated);
  972. +                                                              
  973. +                                                       if (!(md->mode&eModifierMode_Render))
  974. +                                                               dob->no_render = 1;
  975. +                                                       else
  976. +                                                               dob->no_render = 0;
  977. +                                                       /* check the group instance and object layers match, also that the object visible flags are ok. */
  978. +                                                       if(((dob->origlay & group->layer)==0 ||
  979. +                                                               (G.rendering==0 && dob->ob->restrictflag & OB_RESTRICT_VIEW) ||
  980. +                                                               (G.rendering && dob->ob->restrictflag & OB_RESTRICT_RENDER)) ||
  981. +                                                               !(md->mode&eModifierMode_Realtime) || (!(md->mode&eModifierMode_Editmode) && (ob->mode == OB_MODE_EDIT)))
  982. +                                                       {
  983. +                                                               dob->no_draw= 1;
  984. +                                                       }
  985. +                                                       else {
  986. +                                                               dob->no_draw= 0;
  987. +                                                       }
  988. +                                                       if(go->ob->transflag & OB_DUPLI) {
  989. +                                                               copy_m4_m4(dob->ob->obmat, dob->mat);
  990. +                                                               object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, level+1, animated);
  991. +                                                               copy_m4_m4(dob->ob->obmat, dob->omat);
  992. +                                                       }
  993. +                                               }
  994. +                                       }
  995. +                                       //Increment for rays
  996. +                                       if (amd->rays>1)
  997. +                                       {
  998. +                                               d_alp = d_alp + alpha;
  999. +                                               if (d_alp>6.2831)
  1000. +                                                       d_alp=0;
  1001. +                                       }
  1002. +                                       //Offset for clone group
  1003. +                                       if (d_alp == 0)
  1004. +                                               mul_m4_m4m4(offset, offset, amd->delta);
  1005. +                               }
  1006. +                       }
  1007. +               }
  1008. +       }
  1009. +}
  1010. +
  1011.  static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated)
  1012.  {
  1013.         extern int enable_cu_speed;     /* object.c */
  1014. @@ -1599,6 +1732,15 @@
  1015.                                 if(dob->type == OB_DUPLIGROUP)
  1016.                                         copy_m4_m4(dob->ob->obmat, dob->mat);
  1017.                 }
  1018. +       } else if(ob->transflag & OB_DUPLIARRAY) {
  1019. +               DupliObject *dob;
  1020. +
  1021. +               group_arrayduplilist(duplilist, scene, ob, level+1, animated);
  1022. +               if (level==0) {
  1023. +                       for(dob= duplilist->first; dob; dob= dob->next)
  1024. +                               if(dob->type == OB_DUPLIARRAY)
  1025. +                                       copy_m4_m4(dob->ob->obmat, dob->mat);
  1026. +               }
  1027.         }
  1028.  }
  1029.  
  1030. Index: source/blender/blenloader/intern/readfile.c
  1031. ===================================================================
  1032. --- source/blender/blenloader/intern/readfile.c (revisione 39737)
  1033. +++ source/blender/blenloader/intern/readfile.c (copia locale)
  1034. @@ -3886,6 +3886,15 @@
  1035.                                 }
  1036.                         }
  1037.  
  1038. +                       {
  1039. +                               ArrayModifierData *amd = (ArrayModifierData *)modifiers_findByType(ob, eModifierType_Array);
  1040. +                              
  1041. +                               if(amd)
  1042. +                               {
  1043. +                                       amd->arr_group = newlibadr(fd, ob->id.lib, amd->arr_group);
  1044. +                               }
  1045. +                       }
  1046. +                      
  1047.                         /* texture field */
  1048.                         if(ob->pd)
  1049.                                 lib_link_partdeflect(fd, &ob->id, ob->pd);
  1050. @@ -4157,6 +4166,11 @@
  1051.                         if(tmd->curfalloff)
  1052.                                 direct_link_curvemapping(fd, tmd->curfalloff);
  1053.                 }
  1054. +               else if (md->type==eModifierType_Array) {
  1055. +                       ArrayModifierData *amd = (ArrayModifierData*) md;
  1056. +
  1057. +                       amd->Mem_Ob = newdataadr(fd, amd->Mem_Ob);
  1058. +               }
  1059.         }
  1060.  }
  1061.  
  1062. Index: source/blender/blenloader/intern/writefile.c
  1063. ===================================================================
  1064. --- source/blender/blenloader/intern/writefile.c        (revisione 39737)
  1065. +++ source/blender/blenloader/intern/writefile.c        (copia locale)
  1066. @@ -1308,6 +1308,11 @@
  1067.                                 write_curvemapping(wd, tmd->curfalloff);
  1068.                         }
  1069.                 }
  1070. +               else if (md->type==eModifierType_Array) {
  1071. +                       ArrayModifierData *amd = (ArrayModifierData*) md;
  1072. +                      
  1073. +                       writestruct(wd, DATA, "ArrayChangeObject", amd->count, amd->Mem_Ob);
  1074. +               }
  1075.         }
  1076.  }
  1077.  
  1078. Index: source/blender/editors/object/object_intern.h
  1079. ===================================================================
  1080. --- source/blender/editors/object/object_intern.h       (revisione 39737)
  1081. +++ source/blender/editors/object/object_intern.h       (copia locale)
  1082. @@ -160,6 +160,7 @@
  1083.  void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot);
  1084.  void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);
  1085.  void OBJECT_OT_explode_refresh(struct wmOperatorType *ot);
  1086. +void OBJECT_OT_array_rand(struct wmOperatorType *ot);
  1087.  
  1088.  /* object_constraint.c */
  1089.  void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
  1090. Index: source/blender/editors/object/object_modifier.c
  1091. ===================================================================
  1092. --- source/blender/editors/object/object_modifier.c     (revisione 39737)
  1093. +++ source/blender/editors/object/object_modifier.c     (copia locale)
  1094. @@ -203,6 +203,10 @@
  1095.         else if(md->type == eModifierType_Smoke) {
  1096.                 ob->dt = OB_TEXTURE;
  1097.         }
  1098. +       else if(md->type == eModifierType_Array) {
  1099. +               ob->transflag = 0;
  1100. +               ob->dup_group = NULL;
  1101. +       }
  1102.         else if(md->type == eModifierType_Multires) {
  1103.                 int ok= 1;
  1104.                 Mesh *me= ob->data;
  1105. @@ -1404,3 +1408,49 @@
  1106.         edit_modifier_properties(ot);
  1107.  }
  1108.  
  1109. +/****************** array rand operator *********************/
  1110. +
  1111. +static int array_poll(bContext *C)
  1112. +{
  1113. +       return edit_modifier_poll_generic(C, &RNA_ArrayModifier, 0);
  1114. +}
  1115. +
  1116. +static int array_rand_exec(bContext *C, wmOperator *op)
  1117. +{
  1118. +       Object *ob = ED_object_active_context(C);
  1119. +       ArrayModifierData *amd = (ArrayModifierData *)edit_modifier_property_get(op, ob, eModifierType_Array);
  1120. +       
  1121. +       if (!amd)
  1122. +               return OPERATOR_CANCELLED;
  1123. +
  1124. +       amd->lock = 0;
  1125. +
  1126. +       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
  1127. +       WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
  1128. +       
  1129. +       return OPERATOR_FINISHED;
  1130. +}
  1131. +
  1132. +static int array_rand_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
  1133. +{
  1134. +       if (edit_modifier_invoke_properties(C, op))
  1135. +               return array_rand_exec(C, op);
  1136. +       else
  1137. +               return OPERATOR_CANCELLED;
  1138. +}
  1139. +
  1140. +
  1141. +void OBJECT_OT_array_rand(wmOperatorType *ot)
  1142. +{
  1143. +       ot->name= "Array Refresh";
  1144. +       ot->description= "Refresh data in the Array modifier";
  1145. +       ot->idname= "OBJECT_OT_array_rand";
  1146. +
  1147. +       ot->poll= array_poll;
  1148. +       ot->invoke= array_rand_invoke;
  1149. +       ot->exec= array_rand_exec;
  1150. +       
  1151. +       /* flags */
  1152. +       //ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
  1153. +       edit_modifier_properties(ot);
  1154. +}
  1155. Index: source/blender/editors/object/object_ops.c
  1156. ===================================================================
  1157. --- source/blender/editors/object/object_ops.c  (revisione 39737)
  1158. +++ source/blender/editors/object/object_ops.c  (copia locale)
  1159. @@ -143,7 +143,8 @@
  1160.         WM_operatortype_append(OBJECT_OT_multires_external_pack);
  1161.         WM_operatortype_append(OBJECT_OT_meshdeform_bind);
  1162.         WM_operatortype_append(OBJECT_OT_explode_refresh);
  1163. -       
  1164. +       WM_operatortype_append(OBJECT_OT_array_rand);
  1165. +
  1166.         WM_operatortype_append(OBJECT_OT_constraint_add);
  1167.         WM_operatortype_append(OBJECT_OT_constraint_add_with_targets);
  1168.         WM_operatortype_append(POSE_OT_constraint_add);
  1169. Index: source/blender/makesdna/DNA_modifier_types.h
  1170. ===================================================================
  1171. --- source/blender/makesdna/DNA_modifier_types.h        (revisione 39737)
  1172. +++ source/blender/makesdna/DNA_modifier_types.h        (copia locale)
  1173. @@ -173,11 +173,24 @@
  1174.  /* Mask Modifier -> flag */
  1175.  #define MOD_MASK_INV                   (1<<0)
  1176.  
  1177. +
  1178. +typedef struct ArrayChangeObject {
  1179. +       float location[4][4];
  1180. +       /*0 not modified
  1181. +         1 modified
  1182. +       */
  1183. +       int transform;
  1184. +       int id_mat;
  1185. +       int rand_group_obj;
  1186. +} ArrayChangeObject;
  1187. +
  1188.  typedef struct ArrayModifierData {
  1189.         ModifierData modifier;
  1190.  
  1191.         /* the object with which to cap the start of the array  */
  1192.         struct Object *start_cap;
  1193. +       /* the object with which to cap the mid of the array  */
  1194. +       struct Object *mid_cap;
  1195.         /* the object with which to cap the end of the array  */
  1196.         struct Object *end_cap;
  1197.         /* the curve object to use for MOD_ARR_FITCURVE */
  1198. @@ -192,6 +205,7 @@
  1199.            1 means the duplicates are 1 object-width apart
  1200.         */
  1201.         float scale[3];
  1202. +       float delta[4][4];
  1203.         /* the length over which to distribute the duplicates */
  1204.         float length;
  1205.         /* the limit below which to merge vertices in adjacent duplicates */
  1206. @@ -215,6 +229,29 @@
  1207.         int flags;
  1208.         /* the number of duplicates to generate for MOD_ARR_FIXEDCOUNT */
  1209.         int count;
  1210. +       /*Normal Mode-Advanced Mode*/
  1211. +       int mode;
  1212. +       /*Direction Offset*/
  1213. +       int sign;
  1214. +       /* min and max limit */ 
  1215. +       //float limit[2];                      
  1216. +       float loc_offset[3];
  1217. +       float rot_offset[3];
  1218. +       float scale_offset[3];
  1219. +       //Lock the noise offset
  1220. +       int lock;
  1221. +       struct ArrayChangeObject *Mem_Ob;
  1222. +       
  1223. +       int proportion;
  1224. +       int rays;
  1225. +       int rays_dir;
  1226. +       int rand_mat;
  1227. +       int cont_mat;
  1228. +       int cont_mid_cap;
  1229. +       struct Group *arr_group;
  1230. +       int rand_group;
  1231. +       int distribution;
  1232. +
  1233.  } ArrayModifierData;
  1234.  
  1235.  /* ArrayModifierData->fit_type */
  1236. @@ -226,11 +263,44 @@
  1237.  #define MOD_ARR_OFF_CONST    (1<<0)
  1238.  #define MOD_ARR_OFF_RELATIVE (1<<1)
  1239.  #define MOD_ARR_OFF_OBJ      (1<<2)
  1240. +#define MOD_ARR_OFF_BETW     (1<<3)
  1241.  
  1242.  /* ArrayModifierData->flags */
  1243. -#define MOD_ARR_MERGE      (1<<0)
  1244. -#define MOD_ARR_MERGEFINAL (1<<1)
  1245. +#define MOD_ARR_MERGE          (1<<0)
  1246. +#define MOD_ARR_MERGEFINAL     (1<<1)
  1247.  
  1248. +/* ArrayModifierData->mode */
  1249. +#define MOD_ARR_MOD_ADV                        (1<<0)
  1250. +#define MOD_ARR_MOD_ADV_MAT            (1<<1)
  1251. +#define MOD_ARR_MOD_ADV_CURVE  (1<<2)
  1252. +#define MOD_ARR_MOD_ADV_MID            (1<<3)
  1253. +
  1254. +/* ArrayModifierData->sign */
  1255. +#define MOD_ARR_SIGN_P         (1<<0)
  1256. +#define MOD_ARR_SIGN_L         (1<<1)
  1257. +
  1258. +/* ArrayModifierData->mode */
  1259. +#define MOD_ARR_LOCK           (1<<0)
  1260. +
  1261. +/* ArrayModifierData->proportion */
  1262. +#define MOD_ARR_PROP           (1<<0)
  1263. +
  1264. +/* ArrayModifierData->rnd_mat */
  1265. +#define MOD_ARR_MAT                    (1<<0)
  1266. +#define MOD_ARR_SEQ                    (1<<1)
  1267. +
  1268. +/* ArrayModifierData->rays_dir */
  1269. +#define MOD_ARR_RAYS_X 0
  1270. +#define MOD_ARR_RAYS_Y 1
  1271. +#define MOD_ARR_RAYS_Z 2
  1272. +
  1273. +/* ArrayModifierData->rand_group */
  1274. +#define MOD_ARR_RAND_GROUP    (1<<0)
  1275. +
  1276. +/* ArrayModifierData->distribution */
  1277. +#define MOD_ARR_DIST_EVENLY    (1<<0)
  1278. +#define MOD_ARR_DIST_SEGMENT   (1<<1)
  1279. +
  1280.  typedef struct MirrorModifierData {
  1281.         ModifierData modifier;
  1282.  
  1283. Index: source/blender/makesdna/DNA_object_types.h
  1284. ===================================================================
  1285. --- source/blender/makesdna/DNA_object_types.h  (revisione 39737)
  1286. +++ source/blender/makesdna/DNA_object_types.h  (copia locale)
  1287. @@ -285,9 +285,10 @@
  1288.         struct DupliObject *next, *prev;
  1289.         struct Object *ob;
  1290.         unsigned int origlay;
  1291. -       int index, no_draw, type, animated;
  1292. +       int index, no_draw, no_render, type, animated;
  1293.         float mat[4][4], omat[4][4];
  1294.         float orco[3], uv[2];
  1295. +       int pad;
  1296.  } DupliObject;
  1297.  
  1298.  /* **************** OBJECT ********************* */
  1299. @@ -328,7 +329,7 @@
  1300.  /*#define OB_OFFS_LOCAL                1*/ /*UNUSED*/
  1301.  /* #define OB_QUAT                             2 */ /* never used, free flag */
  1302.  #define OB_NEG_SCALE           4
  1303. -#define OB_DUPLI                       (8+16+256+512+2048)
  1304. +#define OB_DUPLI                       (8+16+256+512+2048+4096)
  1305.  #define OB_DUPLIFRAMES         8
  1306.  #define OB_DUPLIVERTS          16
  1307.  #define OB_DUPLIROT                    32
  1308. @@ -338,8 +339,9 @@
  1309.  #define OB_DUPLIFACES          512
  1310.  #define OB_DUPLIFACES_SCALE    1024
  1311.  #define OB_DUPLIPARTS          2048
  1312. -#define OB_RENDER_DUPLI                4096
  1313. -#define OB_NO_CONSTRAINTS      8192 /* runtime constraints disable */
  1314. +#define OB_DUPLIARRAY          4096
  1315. +#define OB_RENDER_DUPLI                8192
  1316. +#define OB_NO_CONSTRAINTS      16384
  1317.  
  1318.  /* (short) ipoflag */
  1319.         // XXX depreceated - old animation system crap
  1320. Index: source/blender/makesrna/intern/rna_modifier.c
  1321. ===================================================================
  1322. --- source/blender/makesrna/intern/rna_modifier.c       (revisione 39737)
  1323. +++ source/blender/makesrna/intern/rna_modifier.c       (copia locale)
  1324. @@ -523,6 +523,11 @@
  1325.         modifier_object_set(ptr->id.data, &((ArrayModifierData*)ptr->data)->start_cap, OB_MESH, value);
  1326.  }
  1327.  
  1328. +static void rna_ArrayModifier_mid_cap_set(PointerRNA *ptr, PointerRNA value)
  1329. +{
  1330. +       modifier_object_set(ptr->id.data, &((ArrayModifierData*)ptr->data)->mid_cap, OB_MESH, value);
  1331. +}
  1332. +
  1333.  static void rna_ArrayModifier_curve_set(PointerRNA *ptr, PointerRNA value)
  1334.  {
  1335.         modifier_object_set(ptr->id.data, &((ArrayModifierData*)ptr->data)->curve_ob, OB_CURVE, value);
  1336. @@ -1287,12 +1292,23 @@
  1337.         StructRNA *srna;
  1338.         PropertyRNA *prop;
  1339.  
  1340. +       static EnumPropertyItem prop_material_items[] = {
  1341. +               {MOD_ARR_MAT, "RANDOM", 0, "Random", "Use a random material"},
  1342. +               {MOD_ARR_SEQ, "SEQUENCE", 0, "Sequence", "Use the materials in sequence"},
  1343. +               {0, NULL, 0, NULL, NULL}};
  1344. +
  1345.         static EnumPropertyItem prop_fit_type_items[] = {
  1346.                 {MOD_ARR_FIXEDCOUNT, "FIXED_COUNT", 0, "Fixed Count", "Duplicate the object a certain number of times"},
  1347.                 {MOD_ARR_FITLENGTH, "FIT_LENGTH", 0, "Fit Length", "Duplicate the object as many times as fits in a certain length"},
  1348.                 {MOD_ARR_FITCURVE, "FIT_CURVE", 0, "Fit Curve", "Fit the duplicated objects to a curve"},
  1349.                 {0, NULL, 0, NULL, NULL}};
  1350.  
  1351. +       static EnumPropertyItem prop_rays_dir_items[] = {
  1352. +               {MOD_ARR_RAYS_X, "X", 0, "X", "Rays Direction X"},
  1353. +               {MOD_ARR_RAYS_Y, "Y", 0, "Y", "Rays Direction Y"},
  1354. +               {MOD_ARR_RAYS_Z, "Z", 0, "Z", "Rays Direction Z"},
  1355. +               {0, NULL, 0, NULL, NULL}};
  1356. +
  1357.         srna= RNA_def_struct(brna, "ArrayModifier", "Modifier");
  1358.         RNA_def_struct_ui_text(srna, "Array Modifier", "Array duplication modifier");
  1359.         RNA_def_struct_sdna(srna, "ArrayModifierData");
  1360. @@ -1375,6 +1391,11 @@
  1361.         RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
  1362.         RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
  1363.         
  1364. +       prop= RNA_def_property(srna, "use_between_offset", PROP_BOOLEAN, PROP_NONE);
  1365. +       RNA_def_property_boolean_sdna(prop, NULL, "offset_type", MOD_ARR_OFF_BETW);
  1366. +       RNA_def_property_ui_text(prop, "Between Offset", "Number of duplicates between two objects");
  1367. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1368. +
  1369.         /* Caps */
  1370.         prop= RNA_def_property(srna, "start_cap", PROP_POINTER, PROP_NONE);
  1371.         RNA_def_property_ui_text(prop, "Start Cap", "Mesh object to use as a start cap");
  1372. @@ -1382,11 +1403,125 @@
  1373.         RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
  1374.         RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1375.  
  1376. +       prop= RNA_def_property(srna, "mid_cap", PROP_POINTER, PROP_NONE);
  1377. +       RNA_def_property_ui_text(prop, "Mid Cap", "Mesh object to use as a mid cap");
  1378. +       RNA_def_property_pointer_funcs(prop, NULL, "rna_ArrayModifier_mid_cap_set", NULL, "rna_Mesh_object_poll");
  1379. +       RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
  1380. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1381. +
  1382. +       prop= RNA_def_property(srna, "cont_mid_cap", PROP_INT, PROP_NONE);
  1383. +       RNA_def_property_range(prop, 1, INT_MAX);
  1384. +       RNA_def_property_ui_range(prop, 1, 1000, 1, 0);
  1385. +       RNA_def_property_ui_text(prop, "Count Mid Cap",  "Number of duplicates of Mid Cap");
  1386. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1387. +
  1388.         prop= RNA_def_property(srna, "end_cap", PROP_POINTER, PROP_NONE);
  1389.         RNA_def_property_ui_text(prop, "End Cap", "Mesh object to use as an end cap");
  1390.         RNA_def_property_pointer_funcs(prop, NULL, "rna_ArrayModifier_end_cap_set", NULL, "rna_Mesh_object_poll");
  1391.         RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
  1392.         RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
  1393. +
  1394. +       /* Advanced parameters */
  1395. +       prop= RNA_def_property(srna, "use_advanced", PROP_BOOLEAN, PROP_NONE);
  1396. +       RNA_def_property_boolean_sdna(prop, NULL, "mode", MOD_ARR_MOD_ADV);
  1397. +       RNA_def_property_ui_text(prop, "Advanced", "Use Advanced Array");
  1398. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1399. +
  1400. +       prop= RNA_def_property(srna, "sign_p", PROP_BOOLEAN, PROP_TRANSLATION);
  1401. +       RNA_def_property_boolean_sdna(prop, NULL, "sign", MOD_ARR_SIGN_P);
  1402. +       RNA_def_property_ui_text(prop, "+", "Random Sign Between + and -");
  1403. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1404. +
  1405. +       prop= RNA_def_property(srna, "sign_l", PROP_BOOLEAN, PROP_TRANSLATION);
  1406. +       RNA_def_property_boolean_sdna(prop, NULL, "sign", MOD_ARR_SIGN_L);
  1407. +       RNA_def_property_ui_text(prop, "-", "Random Sign Between + and -");
  1408. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1409. +
  1410. +       prop= RNA_def_property(srna, "location_offset", PROP_FLOAT, PROP_TRANSLATION);
  1411. +       RNA_def_property_float_sdna(prop, NULL, "loc_offset");
  1412. +       RNA_def_property_range(prop, 0, FLT_MAX);
  1413. +       RNA_def_property_ui_range(prop, 0, FLT_MAX, 1, 5);
  1414. +       RNA_def_property_ui_text(prop, "Location Offset Displacement", "Add a location offset to vertices or object");
  1415. +       RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Modifier_update");
  1416. +       
  1417. +       prop= RNA_def_property(srna, "rotation_offset", PROP_FLOAT,  PROP_EULER);
  1418. +       RNA_def_property_float_sdna(prop, NULL, "rot_offset");
  1419. +       RNA_def_property_ui_text(prop, "Rotation Offset Displacement", "Add a rotation offset to vertices or object");
  1420. +       RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Modifier_update");
  1421. +       
  1422. +       prop= RNA_def_property(srna, "scale_offset", PROP_FLOAT, PROP_XYZ);
  1423. +       RNA_def_property_float_sdna(prop, NULL, "scale_offset");
  1424. +       RNA_def_property_range(prop, 0, 10);
  1425. +       RNA_def_property_ui_range(prop, 0, 10, 1,5);
  1426. +       RNA_def_property_ui_text(prop, "Scale Offset Displacement", "Add a scale offset to vertices or object");
  1427. +       RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Modifier_update");
  1428. +
  1429. +       prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
  1430. +       RNA_def_property_float_sdna(prop, NULL, "scale_offset[0]");
  1431. +       RNA_def_property_range(prop, 0, FLT_MAX);
  1432. +       RNA_def_property_ui_range(prop, 0, FLT_MAX, 1, 5);
  1433. +       RNA_def_property_ui_text(prop, "Scale Offset Displacement", "Add a scale offset to vertices or object");
  1434. +       RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Modifier_update");
  1435. +
  1436. +       prop= RNA_def_property(srna, "proportion", PROP_BOOLEAN, PROP_TRANSLATION);
  1437. +       RNA_def_property_boolean_sdna(prop, NULL, "proportion", MOD_ARR_SIGN_P);
  1438. +       RNA_def_property_ui_text(prop, "Constrain Proportions", "Constrain Proportions");
  1439. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1440. +
  1441. +       prop= RNA_def_property(srna, "rays", PROP_INT, PROP_NONE);
  1442. +       RNA_def_property_range(prop, 1, 365);
  1443. +       RNA_def_property_ui_range(prop, 1, 365, 1,0);
  1444. +       RNA_def_property_ui_text(prop, "Rays", "Rays");
  1445. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1446. +
  1447. +       prop= RNA_def_property(srna, "material", PROP_ENUM, PROP_NONE);
  1448. +       RNA_def_property_enum_sdna(prop, NULL, "rand_mat");
  1449. +       RNA_def_property_enum_items(prop, prop_material_items);
  1450. +       RNA_def_property_ui_text(prop, "Offset Material", "");
  1451. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1452. +
  1453. +       prop= RNA_def_property(srna, "cont_mat", PROP_INT, PROP_NONE);
  1454. +       RNA_def_property_range(prop, 1, INT_MAX);
  1455. +       RNA_def_property_ui_range(prop, 1, 1000, 1, 0);
  1456. +       RNA_def_property_ui_text(prop, "Count Material",  "Repetition of material");
  1457. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1458. +
  1459. +       prop= RNA_def_property(srna, "rays_dir", PROP_ENUM, PROP_NONE);
  1460. +       RNA_def_property_enum_items(prop, prop_rays_dir_items);
  1461. +       RNA_def_property_ui_text(prop, "Rays Direction", "");
  1462. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1463. +
  1464. +       prop= RNA_def_property(srna, "array_group", PROP_POINTER, PROP_NONE);
  1465. +       RNA_def_property_pointer_sdna(prop, NULL, "arr_group");
  1466. +       RNA_def_property_struct_type(prop, "Group");
  1467. +       RNA_def_property_flag(prop, PROP_EDITABLE);
  1468. +       RNA_def_property_ui_text(prop, "Dupli Group", "Show Group");
  1469. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1470. +
  1471. +       prop= RNA_def_property(srna, "rand_group", PROP_BOOLEAN, PROP_TRANSLATION);
  1472. +       RNA_def_property_boolean_sdna(prop, NULL, "rand_group", MOD_ARR_RAND_GROUP);
  1473. +       RNA_def_property_ui_text(prop, "Rand Object", "Object random group");
  1474. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1475. +
  1476. +       prop= RNA_def_property(srna, "use_advanced_curve", PROP_BOOLEAN, PROP_NONE);
  1477. +       RNA_def_property_boolean_sdna(prop, NULL, "mode", MOD_ARR_MOD_ADV_CURVE);
  1478. +       RNA_def_property_ui_text(prop, "Advanced Curve", "Using a curve in an array");
  1479. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1480. +
  1481. +       prop= RNA_def_property(srna, "all_curve", PROP_BOOLEAN, PROP_TRANSLATION);
  1482. +       RNA_def_property_boolean_sdna(prop, NULL, "distribution", MOD_ARR_DIST_EVENLY);
  1483. +       RNA_def_property_ui_text(prop, "Spread Evenly", "Spread evenly on a curve");
  1484. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1485. +
  1486. +       prop= RNA_def_property(srna, "for_segment", PROP_BOOLEAN, PROP_TRANSLATION);
  1487. +       RNA_def_property_boolean_sdna(prop, NULL, "distribution", MOD_ARR_DIST_SEGMENT);
  1488. +       RNA_def_property_ui_text(prop, "For Segment", "Spread evenly for all segments");
  1489. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1490. +
  1491. +       prop= RNA_def_property(srna, "use_advanced_material", PROP_BOOLEAN, PROP_NONE);
  1492. +       RNA_def_property_boolean_sdna(prop, NULL, "mode", MOD_ARR_MOD_ADV_MAT);
  1493. +       RNA_def_property_ui_text(prop, "Advanced Material", "Settings of the material in an array");
  1494. +       RNA_def_property_update(prop, 0, "rna_Modifier_update");
  1495.  }
  1496.  
  1497.  static void rna_def_modifier_edgesplit(BlenderRNA *brna)
  1498. Index: source/blender/modifiers/intern/MOD_array.c
  1499. ===================================================================
  1500. --- source/blender/modifiers/intern/MOD_array.c (revisione 39737)
  1501. +++ source/blender/modifiers/intern/MOD_array.c (copia locale)
  1502. @@ -37,6 +37,8 @@
  1503.  
  1504.  /* Array modifier: duplicates the object multiple times along an axis */
  1505.  
  1506. +#include <time.h>
  1507. +#include <math.h>
  1508.  #include "MEM_guardedalloc.h"
  1509.  
  1510.  #include "BLI_math.h"
  1511. @@ -45,6 +47,7 @@
  1512.  #include "BLI_edgehash.h"
  1513.  
  1514.  #include "DNA_curve_types.h"
  1515. +#include "DNA_group_types.h"
  1516.  #include "DNA_meshdata_types.h"
  1517.  #include "DNA_object_types.h"
  1518.  
  1519. @@ -53,9 +56,12 @@
  1520.  #include "BKE_mesh.h"
  1521.  #include "BKE_modifier.h"
  1522.  #include "BKE_object.h"
  1523. +#include "BKE_anim.h"
  1524.  
  1525. +//#include "BLI_rand.h"
  1526. +
  1527.  #include "depsgraph_private.h"
  1528. -
  1529. +#include "BKE_ama.h"
  1530.  #include "MOD_util.h"
  1531.  
  1532.  static void initData(ModifierData *md)
  1533. @@ -65,7 +71,7 @@
  1534.         /* default to 2 duplicates distributed along the x-axis by an
  1535.         offset of 1 object-width
  1536.         */
  1537. -       amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
  1538. +       amd->start_cap = amd->mid_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
  1539.         amd->count = 2;
  1540.         amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
  1541.         amd->scale[0] = 1;
  1542. @@ -75,6 +81,22 @@
  1543.         amd->fit_type = MOD_ARR_FIXEDCOUNT;
  1544.         amd->offset_type = MOD_ARR_OFF_RELATIVE;
  1545.         amd->flags = 0;
  1546. +
  1547. +       amd->mode = !MOD_ARR_MOD_ADV;
  1548. +       amd->loc_offset[0] = amd->loc_offset[1] = amd->loc_offset[2] = 0;
  1549. +       amd->rot_offset[0] = amd->rot_offset[1] = amd->rot_offset[2] = 0;
  1550. +       amd->scale_offset[0] = amd->scale_offset[1] = amd->scale_offset[2] = 0;
  1551. +       amd->sign = MOD_ARR_SIGN_P;
  1552. +       amd->lock = !MOD_ARR_LOCK;
  1553. +       amd->proportion = MOD_ARR_PROP;
  1554. +       amd->rays = 1;
  1555. +       amd->rand_mat = MOD_ARR_MAT;
  1556. +       amd->cont_mat = 1;
  1557. +       amd->cont_mid_cap = 1;
  1558. +       amd->rays_dir = MOD_ARR_RAYS_X;
  1559. +       amd->arr_group = NULL;
  1560. +       amd->rand_group = !MOD_ARR_RAND_GROUP;
  1561. +       amd->distribution = MOD_ARR_DIST_EVENLY;
  1562.  }
  1563.  
  1564.  static void copyData(ModifierData *md, ModifierData *target)
  1565. @@ -83,6 +105,7 @@
  1566.         ArrayModifierData *tamd = (ArrayModifierData*) target;
  1567.  
  1568.         tamd->start_cap = amd->start_cap;
  1569. +       tamd->mid_cap = amd->mid_cap;
  1570.         tamd->end_cap = amd->end_cap;
  1571.         tamd->curve_ob = amd->curve_ob;
  1572.         tamd->offset_ob = amd->offset_ob;
  1573. @@ -94,6 +117,23 @@
  1574.         tamd->fit_type = amd->fit_type;
  1575.         tamd->offset_type = amd->offset_type;
  1576.         tamd->flags = amd->flags;
  1577. +
  1578. +       tamd->mode = amd->mode;
  1579. +       copy_v3_v3(tamd->loc_offset, amd->loc_offset);
  1580. +       copy_v3_v3(tamd->rot_offset, amd->rot_offset);
  1581. +       copy_v3_v3(tamd->scale_offset, amd->scale_offset);
  1582. +       tamd->sign = amd->sign; 
  1583. +       tamd->lock = amd->lock;
  1584. +       tamd->proportion = amd->proportion;
  1585. +       tamd->rays = amd->rays;
  1586. +       tamd->Mem_Ob = MEM_dupallocN(amd->Mem_Ob);
  1587. +       tamd->rand_mat = amd->rand_mat;
  1588. +       tamd->cont_mat = amd->cont_mat;
  1589. +       tamd->cont_mid_cap = amd->cont_mid_cap;
  1590. +       tamd->rays_dir = amd->rays_dir;
  1591. +       tamd->arr_group = amd->arr_group;
  1592. +       tamd->rand_group = amd->rand_group;
  1593. +       tamd->distribution = amd->distribution;
  1594.  }
  1595.  
  1596.  static void foreachObjectLink(
  1597. @@ -104,6 +144,7 @@
  1598.         ArrayModifierData *amd = (ArrayModifierData*) md;
  1599.  
  1600.         walk(userData, ob, &amd->start_cap);
  1601. +       walk(userData, ob, &amd->mid_cap);
  1602.         walk(userData, ob, &amd->end_cap);
  1603.         walk(userData, ob, &amd->curve_ob);
  1604.         walk(userData, ob, &amd->offset_ob);
  1605. @@ -120,6 +161,12 @@
  1606.                 dag_add_relation(forest, curNode, obNode,
  1607.                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
  1608.         }
  1609. +       if (amd->mid_cap) {
  1610. +               DagNode *curNode = dag_get_node(forest, amd->mid_cap);
  1611. +
  1612. +               dag_add_relation(forest, curNode, obNode,
  1613. +                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
  1614. +       }
  1615.         if (amd->end_cap) {
  1616.                 DagNode *curNode = dag_get_node(forest, amd->end_cap);
  1617.  
  1618. @@ -140,102 +187,25 @@
  1619.         }
  1620.  }
  1621.  
  1622. -static float vertarray_size(MVert *mvert, int numVerts, int axis)
  1623. -{
  1624. -       int i;
  1625. -       float min_co, max_co;
  1626. -
  1627. -       /* if there are no vertices, width is 0 */
  1628. -       if(numVerts == 0) return 0;
  1629. -
  1630. -       /* find the minimum and maximum coordinates on the desired axis */
  1631. -       min_co = max_co = mvert->co[axis];
  1632. -       ++mvert;
  1633. -       for(i = 1; i < numVerts; ++i, ++mvert) {
  1634. -               if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
  1635. -               if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
  1636. -       }
  1637. -
  1638. -       return max_co - min_co;
  1639. -}
  1640. -
  1641. -/* XXX This function fixes bad merging code, in some cases removing vertices creates indices > maxvert */
  1642. -
  1643. -static int test_index_face_maxvert(MFace *mface, CustomData *fdata, int mfindex, int nr, int maxvert)
  1644. -{
  1645. -       if(mface->v1 >= maxvert) {
  1646. -               // printf("bad index in array\n");
  1647. -               mface->v1= maxvert - 1;
  1648. -       }
  1649. -       if(mface->v2 >= maxvert) {
  1650. -               // printf("bad index in array\n");
  1651. -               mface->v2= maxvert - 1;
  1652. -       }
  1653. -       if(mface->v3 >= maxvert) {
  1654. -               // printf("bad index in array\n");
  1655. -               mface->v3= maxvert - 1;
  1656. -       }
  1657. -       if(mface->v4 >= maxvert) {
  1658. -               // printf("bad index in array\n");
  1659. -               mface->v4= maxvert - 1;
  1660. -       }
  1661. -       
  1662. -       return test_index_face(mface, fdata, mfindex, nr);
  1663. -}
  1664. -
  1665. -typedef struct IndexMapEntry {
  1666. -       /* the new vert index that this old vert index maps to */
  1667. -       int new;
  1668. -       /* -1 if this vert isn't merged, otherwise the old vert index it
  1669. -       * should be replaced with
  1670. -       */
  1671. -       int merge;
  1672. -       /* 1 if this vert's first copy is merged with the last copy of its
  1673. -       * merge target, otherwise 0
  1674. -       */
  1675. -       short merge_final;
  1676. -} IndexMapEntry;
  1677. -
  1678. -/* indexMap - an array of IndexMap entries
  1679. - * oldIndex - the old index to map
  1680. - * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
  1681. - */
  1682. -static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
  1683. -{
  1684. -       if(indexMap[oldIndex].merge < 0) {
  1685. -               /* vert wasn't merged, so use copy of this vert */
  1686. -               return indexMap[oldIndex].new + copyNum;
  1687. -       } else if(indexMap[oldIndex].merge == oldIndex) {
  1688. -               /* vert was merged with itself */
  1689. -               return indexMap[oldIndex].new;
  1690. -       } else {
  1691. -               /* vert was merged with another vert */
  1692. -               /* follow the chain of merges to the end, or until we've passed
  1693. -               * a number of vertices equal to the copy number
  1694. -               */
  1695. -               if(copyNum <= 0)
  1696. -                       return indexMap[oldIndex].new;
  1697. -               else
  1698. -                       return calc_mapping(indexMap, indexMap[oldIndex].merge,
  1699. -                                               copyNum - 1);
  1700. -       }
  1701. -}
  1702. -
  1703.  static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
  1704.                                           struct Scene *scene, Object *ob, DerivedMesh *dm,
  1705.            int initFlags)
  1706.  {
  1707. -       int i, j;
  1708. +       int i, j, flag;
  1709. +       int dim, start;
  1710.         /* offset matrix */
  1711.         float offset[4][4];
  1712.         float final_offset[4][4];
  1713. +       float mid_offset[4][4];
  1714.         float tmp_mat[4][4];
  1715.         float length = amd->length;
  1716. +       float alpha, d_alp, circle;
  1717. +       float f_o;
  1718.         int count = amd->count;
  1719.         int numVerts, numEdges, numFaces;
  1720.         int maxVerts, maxEdges, maxFaces;
  1721.         int finalVerts, finalEdges, finalFaces;
  1722. -       DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
  1723. +       DerivedMesh *result, *start_cap = NULL, *mid_cap = NULL, *end_cap = NULL;
  1724.         MVert *mvert, *src_mvert;
  1725.         MEdge *medge;
  1726.         MFace *mface;
  1727. @@ -243,10 +213,12 @@
  1728.         IndexMapEntry *indexMap;
  1729.  
  1730.         EdgeHash *edges;
  1731. -
  1732. +       
  1733.         /* need to avoid infinite recursion here */
  1734.         if(amd->start_cap && amd->start_cap != ob)
  1735.                 start_cap = amd->start_cap->derivedFinal;
  1736. +       if(amd->mid_cap && amd->mid_cap != ob)
  1737. +               mid_cap = amd->mid_cap->derivedFinal;
  1738.         if(amd->end_cap && amd->end_cap != ob)
  1739.                 end_cap = amd->end_cap->derivedFinal;
  1740.  
  1741. @@ -277,42 +249,31 @@
  1742.                         unit_m4(obinv);
  1743.  
  1744.                 mul_serie_m4(result_mat, offset,
  1745. -                                obinv, amd->offset_ob->obmat,
  1746. -        NULL, NULL, NULL, NULL, NULL);
  1747. +                                       obinv, amd->offset_ob->obmat,
  1748. +                                       NULL, NULL, NULL, NULL, NULL);
  1749.                 copy_m4_m4(offset, result_mat);
  1750.         }
  1751.  
  1752. +       if ((amd->offset_type & MOD_ARR_OFF_BETW) && (amd->offset_ob)) {
  1753. +                       float dist = sqrt(dot_v3v3(amd->offset_ob->obmat[3], amd->offset_ob->obmat[3]));
  1754. +                       offset[3][0] = amd->offset_ob->obmat[3][0] / (count - 1);
  1755. +                       offset[3][1] = amd->offset_ob->obmat[3][1] / (count - 1);
  1756. +                       offset[3][2] = amd->offset_ob->obmat[3][2] / (count - 1);
  1757. +       }
  1758.         if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
  1759. -               Curve *cu = amd->curve_ob->data;
  1760. -               if(cu) {
  1761. -                       float tmp_mat[3][3];
  1762. -                       float scale;
  1763. -                      
  1764. -                       object_to_mat3(amd->curve_ob, tmp_mat);
  1765. -                       scale = mat3_to_scale(tmp_mat);
  1766. -                              
  1767. -                       if(!cu->path) {
  1768. -                               cu->flag |= CU_PATH; // needed for path & bevlist
  1769. -                               makeDispListCurveTypes(scene, amd->curve_ob, 0);
  1770. -                       }
  1771. -                       if(cu->path)
  1772. -                               length = scale*cu->path->totdist;
  1773. -               }
  1774. +               length = length_fitcurve(amd, scene);
  1775.         }
  1776.  
  1777.         /* calculate the maximum number of copies which will fit within the
  1778.         prescribed length */
  1779.         if(amd->fit_type == MOD_ARR_FITLENGTH
  1780.                   || amd->fit_type == MOD_ARR_FITCURVE) {
  1781. -               float dist = sqrt(dot_v3v3(offset[3], offset[3]));
  1782. -
  1783. -               if(dist > 1e-6f)
  1784. -                       /* this gives length = first copy start to last copy end
  1785. -                       add a tiny offset for floating point rounding errors */
  1786. -                       count = (length + 1e-6f) / dist;
  1787. -               else
  1788. -                       /* if the offset has no translation, just make one copy */
  1789. -                       count = 1;
  1790. +               /*if ((amd->fit_type == MOD_ARR_FITLENGTH) && (count>2)){
  1791. +                       amd->length = count_to_length(count, offset[3]);
  1792. +                       length = amd->length;
  1793. +               }*/
  1794. +               count = length_to_count(length, offset[3]);
  1795. +               amd->count = count;
  1796.         }
  1797.  
  1798.         if(count < 1)
  1799. @@ -329,21 +290,62 @@
  1800.                 finalEdges += start_cap->getNumEdges(start_cap);
  1801.                 finalFaces += start_cap->getNumFaces(start_cap);
  1802.         }
  1803. +       if(mid_cap) {
  1804. +               finalVerts += mid_cap->getNumVerts(mid_cap) * amd->cont_mid_cap;
  1805. +               finalEdges += mid_cap->getNumEdges(mid_cap) * amd->cont_mid_cap;
  1806. +               finalFaces += mid_cap->getNumFaces(mid_cap) * amd->cont_mid_cap;
  1807. +       }
  1808.         if(end_cap) {
  1809.                 finalVerts += end_cap->getNumVerts(end_cap);
  1810.                 finalEdges += end_cap->getNumEdges(end_cap);
  1811.                 finalFaces += end_cap->getNumFaces(end_cap);
  1812.         }
  1813.         result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
  1814. +       flag = 0;
  1815. +       if ((amd->mode & MOD_ARR_MOD_ADV) || (amd->mode & MOD_ARR_MOD_ADV_MAT)){
  1816. +               start = 0;
  1817. +               if (!amd->Mem_Ob)
  1818. +                       amd->Mem_Ob = MEM_callocN(sizeof(*amd->Mem_Ob) * (count), "Mem_Ob");
  1819. +               else {
  1820. +                       dim = MEM_allocN_len(amd->Mem_Ob) / sizeof(*amd->Mem_Ob);
  1821. +                       if (dim < count) {
  1822. +                               amd->Mem_Ob = MEM_reallocN(amd->Mem_Ob, sizeof(*amd->Mem_Ob) * (count));
  1823. +                               start = dim;
  1824. +                       }
  1825. +               }
  1826. +              
  1827. +               //Inizializzare i nuovi cloni creati
  1828. +               if (!amd->lock) {
  1829. +                       init_offset(start, count, amd);
  1830. +                       create_offset(count, ob->totcol, amd, ob);
  1831. +                       amd->lock = 1;
  1832. +                       flag = 1;
  1833. +               }
  1834. +               else
  1835. +                       if (start!=0)// || (amd->mode & MOD_ARR_MOD_ADV_MAT))
  1836. +                               init_offset(start, count, amd);
  1837. +       }
  1838.  
  1839. +       f_o = count-1;
  1840. +
  1841. +       if (amd->rays>1) {
  1842. +               alpha = (float)6.2831 / amd->rays;
  1843. +               circle = (float)(count - 1) / amd->rays;
  1844. +               f_o = ceil(circle);
  1845. +       }
  1846. +
  1847.         /* calculate the offset matrix of the final copy (for merging) */
  1848.         unit_m4(final_offset);
  1849. -
  1850. -       for(j=0; j < count - 1; j++) {
  1851. +       for(j=0; j < f_o; j++) {
  1852.                 mul_m4_m4m4(tmp_mat, final_offset, offset);
  1853.                 copy_m4_m4(final_offset, tmp_mat);
  1854.         }
  1855. -
  1856. +       
  1857. +       copy_m4_m4(mid_offset, offset);
  1858. +       mid_offset[3][0] = mid_offset[3][0] / 2;
  1859. +       mid_offset[3][1] = mid_offset[3][1] / 2;
  1860. +       mid_offset[3][2] = mid_offset[3][2] / 2;
  1861. +       copy_m4_m4(amd->delta, offset);
  1862.         numVerts = numEdges = numFaces = 0;
  1863.         mvert = CDDM_get_verts(result);
  1864.  
  1865. @@ -402,15 +404,68 @@
  1866.  
  1867.                 /* if no merging, generate copies of this vert */
  1868.                 if(indexMap[i].merge < 0) {
  1869. +                       if (amd->rays>1)
  1870. +                               d_alp=0;
  1871. +
  1872.                         for(j=0; j < count - 1; j++) {
  1873. +                               float rot[4][4];
  1874.                                 mv2 = &mvert[numVerts];
  1875.  
  1876.                                 DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
  1877.                                 *mv2 = *mv;
  1878.                                 numVerts++;
  1879. +                               /*//Aggiungendo questa parte ed eliminando 1) e 2)
  1880. +                               //si ottiene una spirale
  1881. +                               mul_m4_v3(offset, co);
  1882. +                               copy_v3_v3(mv2->co, co);*/
  1883. +                               if (amd->rays>1)
  1884. +                               {
  1885. +                                       float ro[3];
  1886. +                                       unit_m4(rot);
  1887. +                                       if (amd->rays_dir == MOD_ARR_RAYS_X)
  1888. +                                               rotate_m4(rot,'X',d_alp);
  1889. +                                       else if (amd->rays_dir == MOD_ARR_RAYS_Y)
  1890. +                                               rotate_m4(rot,'Y',d_alp);
  1891. +                                       else
  1892. +                                               rotate_m4(rot,'Z',d_alp);
  1893. +                                       if (d_alp == 0){
  1894. +                                               /*1)*/
  1895. +                                               mul_m4_v3(offset, co);
  1896. +                                               copy_v3_v3(mv2->co, co);
  1897. +                                               /******/
  1898. +                                               copy_v3_v3(ro, mv2->co);
  1899. +                                               mul_m4_v3(rot, ro);
  1900. +                                               copy_v3_v3(mv2->co, ro);
  1901. +                                       }
  1902. +                                       else{
  1903. +                                               copy_v3_v3(ro,co);
  1904. +                                               mul_m4_v3(rot, ro);
  1905. +                                               copy_v3_v3(mv2->co, ro);
  1906. +                                       }
  1907. +                                       d_alp = d_alp + alpha;
  1908. +                                       if (d_alp>6.2831)
  1909. +                                               d_alp=0;
  1910. +                               }
  1911. +                               else
  1912. +                               {
  1913. +                                       /*2)*/
  1914. +                                       mul_m4_v3(offset, co);
  1915. +                                       copy_v3_v3(mv2->co, co);
  1916. +                                       /******/
  1917. +                               }
  1918.  
  1919. -                               mul_m4_v3(offset, co);
  1920. -                               copy_v3_v3(mv2->co, co);
  1921. +                               if (amd->mode & MOD_ARR_MOD_ADV)
  1922. +                               {       
  1923. +                                       if (amd->Mem_Ob[j].transform)
  1924. +                                       {
  1925. +                                               float fo[3];
  1926. +                                                                                              
  1927. +                                               copy_v3_v3(fo, mv2->co);
  1928. +                                               mul_m4_v3(amd->Mem_Ob[j].location, fo);
  1929. +                                               copy_v3_v3(mv2->co, fo);
  1930. +                                              
  1931. +                                       }
  1932. +                               }
  1933.                         }
  1934.                 } else if(indexMap[i].merge != i && indexMap[i].merge_final) {
  1935.                         /* if this vert is not merging with itself, and it is merging
  1936. @@ -555,6 +610,12 @@
  1937.  
  1938.                         numFaces++;
  1939.  
  1940. +                       /*Rand Material*/
  1941. +                       if ((flag = 1) && (amd->mode & MOD_ARR_MOD_ADV_MAT) && (ob->totcol>1))
  1942. +                       {
  1943. +                                       mf2->mat_nr = amd->Mem_Ob[j-1].id_mat;
  1944. +                                       flag = 0;
  1945. +                       }
  1946.                         /* if the face has fewer than 3 vertices, don't create it */
  1947.                         if(test_index_face_maxvert(mf2, &result->faceData, numFaces-1, inMF.v4?4:3, numVerts) < 3) {
  1948.                                 numFaces--;
  1949. @@ -563,7 +624,7 @@
  1950.                 }
  1951.         }
  1952.  
  1953. -       /* add start and end caps */
  1954. +       /* add start, mid and end caps */
  1955.         if(start_cap) {
  1956.                 float startoffset[4][4];
  1957.                 MVert *cap_mvert;
  1958. @@ -665,6 +726,112 @@
  1959.                 start_cap->release(start_cap);
  1960.         }
  1961.  
  1962. +       /*insert_start_cap(amd, dm, result, start_cap, indexMap, edges, numVerts, numEdges, numFaces, offset);*/
  1963. +       if(mid_cap) {
  1964. +               MVert *cap_mvert;
  1965. +               MEdge *cap_medge;
  1966. +               MFace *cap_mface;
  1967. +               int *origindex;
  1968. +               int *vert_map;
  1969. +               int capVerts, capEdges, capFaces;
  1970. +
  1971. +               capVerts = mid_cap->getNumVerts(mid_cap);
  1972. +               capEdges = mid_cap->getNumEdges(mid_cap);
  1973. +               capFaces = mid_cap->getNumFaces(mid_cap);
  1974. +               cap_mvert = mid_cap->getVertArray(mid_cap);
  1975. +               cap_medge = mid_cap->getEdgeArray(mid_cap);
  1976. +               cap_mface = mid_cap->getFaceArray(mid_cap);
  1977. +
  1978. +               vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
  1979. +               "arrayModifier_doArray vert_map");
  1980. +               if (amd->cont_mid_cap>=amd->count)
  1981. +                       amd->cont_mid_cap = amd->count -1;
  1982. +               for(j=0; j < amd->cont_mid_cap; j++) {
  1983. +                       origindex = result->getVertDataArray(result, CD_ORIGINDEX);
  1984. +                       for(i = 0; i < capVerts; i++) {
  1985. +                               MVert *mv = &cap_mvert[i];
  1986. +                               short merged = 0;
  1987. +
  1988. +                               if(amd->flags & MOD_ARR_MERGE) {
  1989. +                                       float tmp_co[3];
  1990. +                                       MVert *in_mv;
  1991. +                                       int j;
  1992. +
  1993. +                                       copy_v3_v3(tmp_co, mv->co);
  1994. +                                       mul_m4_v3(mid_offset, tmp_co);
  1995. +
  1996. +                                       for(j = 0; j < maxVerts; j++) {
  1997. +                                               in_mv = &src_mvert[j];
  1998. +                                               /* if this vert is within merge limit, merge */
  1999. +                                               if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
  2000. +                                                       vert_map[i] = calc_mapping(indexMap, j, 0);
  2001. +                                                       merged = 1;
  2002. +                                                       break;
  2003. +                                               }
  2004. +                                       }
  2005. +                               }
  2006. +
  2007. +                               if(!merged) {
  2008. +                                       //for(j=0; j < amd->cont_mid_cap; j++) {
  2009. +                                               DM_copy_vert_data(mid_cap, result, i, numVerts, 1);
  2010. +                                               mvert[numVerts] = *mv;
  2011. +                                               mul_m4_v3(mid_offset, mvert[numVerts].co);
  2012. +                                               origindex[numVerts] = ORIGINDEX_NONE;
  2013. +
  2014. +                                               vert_map[i] = numVerts;
  2015. +
  2016. +                                               numVerts++;
  2017. +                                       //}
  2018. +                               }
  2019. +                       }
  2020. +
  2021. +                       origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
  2022. +                       for(i = 0; i < capEdges; i++) {
  2023. +                               int v1, v2;
  2024. +
  2025. +                               v1 = vert_map[cap_medge[i].v1];
  2026. +                               v2 = vert_map[cap_medge[i].v2];
  2027. +
  2028. +                               if(!BLI_edgehash_haskey(edges, v1, v2)) {
  2029. +                                       DM_copy_edge_data(mid_cap, result, i, numEdges, 1);
  2030. +                                       medge[numEdges] = cap_medge[i];
  2031. +                                       medge[numEdges].v1 = v1;
  2032. +                                       medge[numEdges].v2 = v2;
  2033. +                                       origindex[numEdges] = ORIGINDEX_NONE;
  2034. +
  2035. +                                       numEdges++;
  2036. +                               }
  2037. +                       }
  2038. +                       origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
  2039. +                       for(i = 0; i < capFaces; i++) {
  2040. +                               DM_copy_face_data(mid_cap, result, i, numFaces, 1);
  2041. +                               mface[numFaces] = cap_mface[i];
  2042. +                               mface[numFaces].v1 = vert_map[mface[numFaces].v1];
  2043. +                               mface[numFaces].v2 = vert_map[mface[numFaces].v2];
  2044. +                               mface[numFaces].v3 = vert_map[mface[numFaces].v3];
  2045. +                               if(mface[numFaces].v4) {
  2046. +                                       mface[numFaces].v4 = vert_map[mface[numFaces].v4];
  2047. +
  2048. +                                       test_index_face_maxvert(&mface[numFaces], &result->faceData,
  2049. +                                       numFaces, 4, numVerts);
  2050. +                               }
  2051. +                               else
  2052. +                               {
  2053. +                                       test_index_face(&mface[numFaces], &result->faceData,
  2054. +                                       numFaces, 3);
  2055. +                               }
  2056. +
  2057. +                               origindex[numFaces] = ORIGINDEX_NONE;
  2058. +
  2059. +                               numFaces++;
  2060. +                       }
  2061. +                       mul_m4_m4m4(tmp_mat, mid_offset, offset);
  2062. +                       copy_m4_m4(mid_offset, tmp_mat);
  2063. +               }
  2064. +               MEM_freeN(vert_map);
  2065. +               mid_cap->release(mid_cap);
  2066. +       }
  2067. +
  2068.         if(end_cap) {
  2069.                 float endoffset[4][4];
  2070.                 MVert *cap_mvert;
  2071. @@ -765,6 +932,16 @@
  2072.                 end_cap->release(end_cap);
  2073.         }
  2074.  
  2075. +       if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
  2076. +               if (amd->distribution == MOD_ARR_DIST_EVENLY){
  2077. +                       float (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "vertex_array_to_curve");
  2078. +       
  2079. +                       for (i=0; i<numVerts; i++)
  2080. +                               VECCOPY(cos[i], mvert[i].co);
  2081. +                       array_to_curve(scene, amd->curve_ob, ob, cos, numVerts);
  2082. +               }
  2083. +       }
  2084. +
  2085.         BLI_edgehash_free(edges, NULL);
  2086.         MEM_freeN(indexMap);
  2087.  
  2088. @@ -785,9 +962,20 @@
  2089.  
  2090.         result = arrayModifier_doArray(amd, md->scene, ob, dm, 0);
  2091.  
  2092. -       if(result != dm)
  2093. +       if(result != dm) {
  2094.                 CDDM_calc_normals(result);
  2095. -
  2096. +              
  2097. +               if(amd->arr_group!=NULL)
  2098. +               {       
  2099. +                       ob->transflag = OB_DUPLIARRAY;
  2100. +                       ob->dup_group = amd->arr_group;
  2101. +               }
  2102. +               else
  2103. +               {
  2104. +                       ob->transflag = 0;
  2105. +                       ob->dup_group = NULL;
  2106. +               }
  2107. +       }
  2108.         return result;
  2109.  }
  2110.  
  2111. @@ -798,6 +986,16 @@
  2112.         return applyModifier(md, ob, dm, 0, 1);
  2113.  }
  2114.  
  2115. +static void freeData(ModifierData *md)
  2116. +{
  2117. +       ArrayModifierData *amd = (ArrayModifierData*) md;
  2118. +       
  2119. +       if (amd)
  2120. +       {
  2121. +               if (amd->Mem_Ob)
  2122. +                       MEM_freeN(amd->Mem_Ob);
  2123. +       }
  2124. +}
  2125.  
  2126.  ModifierTypeInfo modifierType_Array = {
  2127.         /* name */              "Array",
  2128. @@ -819,12 +1017,11 @@
  2129.         /* applyModifierEM */   applyModifierEM,
  2130.         /* initData */          initData,
  2131.         /* requiredDataMask */  NULL,
  2132. -       /* freeData */          NULL,
  2133. +       /* freeData */          freeData,
  2134.         /* isDisabled */        NULL,
  2135.         /* updateDepgraph */    updateDepgraph,
  2136.         /* dependsOnTime */     NULL,
  2137.         /* dependsOnNormals */  NULL,
  2138.         /* foreachObjectLink */ foreachObjectLink,
  2139.         /* foreachIDLink */     NULL,
  2140. -       /* foreachTexLink */    NULL,
  2141.  };
  2142. Index: source/blender/render/intern/source/convertblender.c
  2143. ===================================================================
  2144. --- source/blender/render/intern/source/convertblender.c        (revisione 39737)
  2145. +++ source/blender/render/intern/source/convertblender.c        (copia locale)
  2146. @@ -4713,7 +4713,8 @@
  2147.         /* override not showing object when duplis are used with particles */
  2148.         if(ob->transflag & OB_DUPLIPARTS)
  2149.                 ; /* let particle system(s) handle showing vs. not showing */
  2150. -       else if((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES))
  2151. +       else if((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES) &&
  2152. +                       !(ob->transflag & OB_DUPLIARRAY))
  2153.                 return 0;
  2154.         
  2155.         /* don't add non-basic meta objects, ends up having renderobjects with no geometry */
  2156. @@ -4750,7 +4751,7 @@
  2157.         for(psys=obd->particlesystem.first; psys; psys=psys->next)
  2158.                 if(!ELEM5(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR))
  2159.                         return 0;
  2160. -
  2161. +       
  2162.         /* don't allow lamp, animated duplis, or radio render */
  2163.         return (render_object_type(obd->type) &&
  2164.                         (!(dob->type == OB_DUPLIGROUP) || !dob->animated));
  2165. @@ -4817,17 +4818,19 @@
  2166.         /* simple preventing of too deep nested groups */
  2167.         if(level>MAX_DUPLI_RECUR) return;
  2168.  
  2169. +       //if((ob->transflag == OB_DUPLIARRAY) && dob->no_render)
  2170. +       //      return;
  2171.         /* recursively go into dupligroups to find objects with OB_RENDER_DUPLI
  2172.          * that were not created yet */
  2173.         for(go= group->gobject.first; go; go= go->next) {
  2174.                 ob= go->ob;
  2175. -
  2176. +              
  2177.                 if(ob->flag & OB_DONE) {
  2178.                         if(ob->transflag & OB_RENDER_DUPLI) {
  2179.                                 if(allow_render_object(re, ob, nolamps, onlyselected, actob)) {
  2180.                                         init_render_object(re, ob, NULL, 0, timeoffset, vectorlay);
  2181.                                         ob->transflag &= ~OB_RENDER_DUPLI;
  2182. -
  2183. +                                      
  2184.                                         if(ob->dup_group)
  2185.                                                 add_group_render_dupli_obs(re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, vectorlay, level+1);
  2186.                                 }
  2187. @@ -4900,10 +4903,14 @@
  2188.                                         Object *obd= dob->ob;
  2189.                                        
  2190.                                         copy_m4_m4(obd->obmat, dob->mat);
  2191. -
  2192. +                                      
  2193. +                                       if(!(obd->transflag & OB_DUPLIARRAY) && dob->no_render)
  2194. +                                               continue;
  2195. +                                      
  2196.                                         /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */
  2197. -                                       if(!(obd->transflag & OB_RENDER_DUPLI) && dob->no_draw)
  2198. -                                               continue;
  2199. +                                       if (obd->transflag & OB_DUPLIARRAY)
  2200. +                                               if(!(obd->transflag & OB_RENDER_DUPLI) && dob->no_draw)
  2201. +                                                       continue;
  2202.  
  2203.                                         if(obd->restrictflag & OB_RESTRICT_RENDER)
  2204.                                                 continue;
  2205. @@ -4919,7 +4926,6 @@
  2206.                                                 ObjectRen *obr = NULL;
  2207.                                                 int psysindex;
  2208.                                                 float mat[4][4];
  2209. -
  2210.                                                 obi=NULL;
  2211.  
  2212.                                                 /* instances instead of the actual object are added in two cases, either
  2213.  
go to heaven