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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2008-06-06 06:21:17 +0400
committerNicholas Bishop <nicholasbishop@gmail.com>2008-06-06 06:21:17 +0400
commite449bfd6d2fb59accacb7dde8810da076fc936fc (patch)
treedc48c627eccfc01864485838ce429a19f4bc2aaa /source/blender
parent22c4238dd1b25f0097120dde690744a28cff430d (diff)
parent6ffadbfb103f498b7400ae6d7d960c98404a9bdc (diff)
Merged with trunk (15144)
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_bmesh.h43
-rw-r--r--source/blender/blenkernel/BKE_bmeshCustomData.h108
-rw-r--r--source/blender/blenkernel/BKE_cloth.h32
-rw-r--r--source/blender/blenkernel/BKE_collision.h95
-rw-r--r--source/blender/blenkernel/BKE_curve.h11
-rw-r--r--source/blender/blenkernel/intern/BME_Customdata.c198
-rw-r--r--source/blender/blenkernel/intern/BME_conversions.c22
-rw-r--r--source/blender/blenkernel/intern/BME_mesh.c119
-rw-r--r--source/blender/blenkernel/intern/BME_structure.c200
-rw-r--r--source/blender/blenkernel/intern/BME_tools.c30
-rw-r--r--source/blender/blenkernel/intern/bmesh_private.h7
-rw-r--r--source/blender/blenkernel/intern/cloth.c208
-rw-r--r--source/blender/blenkernel/intern/collision.c1433
-rw-r--r--source/blender/blenkernel/intern/constraint.c4
-rw-r--r--source/blender/blenkernel/intern/curve.c150
-rw-r--r--source/blender/blenkernel/intern/displist.c10
-rw-r--r--source/blender/blenkernel/intern/font.c4
-rw-r--r--source/blender/blenkernel/intern/kdop.c860
-rw-r--r--source/blender/blenkernel/intern/modifier.c149
-rw-r--r--source/blender/blenkernel/intern/object.c9
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2
-rw-r--r--source/blender/blenkernel/intern/text.c14
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c2
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h60
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c810
-rw-r--r--source/blender/blenlib/intern/freetypefont.c2
-rw-r--r--source/blender/blenlib/intern/psfont.c2
-rw-r--r--source/blender/blenlib/intern/util.c39
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/imbuf/SConscript8
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h8
-rw-r--r--source/blender/imbuf/intern/anim.c80
-rw-r--r--source/blender/imbuf/intern/util.c18
-rw-r--r--source/blender/include/BDR_editcurve.h3
-rw-r--r--source/blender/include/BIF_editseq.h4
-rw-r--r--source/blender/include/BSE_view.h2
-rw-r--r--source/blender/include/transform.h1
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h2
-rw-r--r--source/blender/makesdna/intern/makesdna.c10
-rw-r--r--source/blender/nodes/intern/Makefile2
-rw-r--r--source/blender/python/BPY_interface.c21
-rw-r--r--source/blender/python/api2_2x/Blender.c2
-rw-r--r--source/blender/python/api2_2x/Draw.c2
-rw-r--r--source/blender/python/api2_2x/Material.c4
-rw-r--r--source/blender/python/api2_2x/Node.c2
-rw-r--r--source/blender/python/api2_2x/Object.c131
-rw-r--r--source/blender/python/api2_2x/Particle.c2
-rw-r--r--source/blender/python/api2_2x/Scene.c27
-rw-r--r--source/blender/python/api2_2x/Sys.c5
-rw-r--r--source/blender/python/api2_2x/doc/Object.py9
-rw-r--r--source/blender/python/api2_2x/sceneRender.c13
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/extern/include/RE_raytrace.h2
-rw-r--r--source/blender/render/intern/include/render_types.h1
-rw-r--r--source/blender/render/intern/source/convertblender.c41
-rw-r--r--source/blender/render/intern/source/envmap.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c1
-rw-r--r--source/blender/render/intern/source/rayshade.c22
-rw-r--r--source/blender/render/intern/source/rendercore.c16
-rw-r--r--source/blender/src/buttons_editing.c27
-rw-r--r--source/blender/src/buttons_scene.c15
-rw-r--r--source/blender/src/drawobject.c207
-rw-r--r--source/blender/src/drawseq.c2
-rw-r--r--source/blender/src/drawview.c22
-rw-r--r--source/blender/src/editaction.c13
-rw-r--r--source/blender/src/editarmature.c64
-rw-r--r--source/blender/src/editcurve.c272
-rw-r--r--source/blender/src/editmesh_tools.c3
-rw-r--r--source/blender/src/editnode.c3
-rw-r--r--source/blender/src/editseq.c93
-rw-r--r--source/blender/src/filesel.c2
-rw-r--r--source/blender/src/fluidsim.c33
-rw-r--r--source/blender/src/interface.c1
-rw-r--r--source/blender/src/meshtools.c11
-rw-r--r--source/blender/src/poseobject.c8
-rw-r--r--source/blender/src/space.c2
-rw-r--r--source/blender/src/toets.c4
-rw-r--r--source/blender/src/transform.c45
-rw-r--r--source/blender/src/transform_conversions.c3
-rw-r--r--source/blender/src/transform_manipulator.c49
-rw-r--r--source/blender/src/transform_orientations.c105
-rw-r--r--source/blender/src/view.c49
83 files changed, 3906 insertions, 2197 deletions
diff --git a/source/blender/blenkernel/BKE_bmesh.h b/source/blender/blenkernel/BKE_bmesh.h
index 08ad8192688..51a5d29dbb7 100644
--- a/source/blender/blenkernel/BKE_bmesh.h
+++ b/source/blender/blenkernel/BKE_bmesh.h
@@ -40,16 +40,35 @@
#include "DNA_listBase.h"
#include "BLI_ghash.h"
#include "BLI_memarena.h"
-#include "DNA_customdata_types.h"
+#include "DNA_image_types.h"
#include "BLI_editVert.h"
#include "BKE_DerivedMesh.h"
#include "transform.h"
+#include "BKE_bmeshCustomData.h"
+/*forward declerations*/
struct BME_Vert;
struct BME_Edge;
struct BME_Poly;
struct BME_Loop;
+
+/*structure for fast memory allocation/frees*/
+typedef struct BME_mempool{
+ struct ListBase chunks;
+ int esize, csize, pchunk; /*size of elements and chunks in bytes and number of elements per chunk*/
+ struct BME_freenode *free; /*free element list. Interleaved into chunk datas.*/
+}BME_mempool;
+
+/*Notes on further structure Cleanup:
+ -Remove the tflags, they belong in custom data layers
+ -Remove the eflags completely, they are mostly not used
+ -Remove the selection/vis/bevel weight flag/values ect and move them to custom data
+ -Remove EID member and move to custom data
+ -Add a radial cycle length, disk cycle length and loop cycle lenght attributes to custom data and have eulers maintain/use them if present.
+ -Move data such as vertex coordinates/normals to custom data and leave pointers in structures to active layer data.
+ -Remove BME_CycleNode structure?
+*/
typedef struct BME_CycleNode{
struct BME_CycleNode *next, *prev;
void *data;
@@ -57,16 +76,21 @@ typedef struct BME_CycleNode{
typedef struct BME_Mesh
{
- ListBase verts, edges, polys, loops;
- int totvert, totedge, totpoly, totloop; /*record keeping*/
- int nextv, nexte, nextp, nextl; /*Next element ID for verts/edges/faces/loops. Never reused*/
- struct CustomData vdata, edata, pdata, ldata; /*Custom Data Layer information*/
+ ListBase verts, edges, polys;
+ /*memory pools used for storing mesh elements*/
+ struct BME_mempool *vpool;
+ struct BME_mempool *epool;
+ struct BME_mempool *ppool;
+ struct BME_mempool *lpool;
/*some scratch arrays used by eulers*/
struct BME_Vert **vtar;
struct BME_Edge **edar;
struct BME_Loop **lpar;
struct BME_Poly **plar;
int vtarlen, edarlen, lparlen, plarlen;
+ int totvert, totedge, totpoly, totloop; /*record keeping*/
+ int nextv, nexte, nextp, nextl; /*Next element ID for verts/edges/faces/loops. Never reused*/
+ struct BME_CustomData vdata, edata, pdata, ldata; /*Custom Data Layer information*/
} BME_Mesh;
typedef struct BME_Vert
@@ -102,7 +126,6 @@ typedef struct BME_Loop
struct BME_Loop *next, *prev; /*circularly linked list around face*/
int EID;
struct BME_CycleNode radial; /*circularly linked list used to find faces around an edge*/
- struct BME_CycleNode *gref; /*pointer to loop ref. Nasty.*/
struct BME_Vert *v; /*vertex that this loop starts at.*/
struct BME_Edge *e; /*edge this loop belongs to*/
struct BME_Poly *f; /*face this loop belongs to*/
@@ -124,7 +147,7 @@ typedef struct BME_Poly
unsigned short flag, h, mat_nr;
} BME_Poly;
-//*EDGE UTILITIES*/
+/*EDGE UTILITIES*/
int BME_verts_in_edge(struct BME_Vert *v1, struct BME_Vert *v2, struct BME_Edge *e);
int BME_vert_in_edge(struct BME_Edge *e, BME_Vert *v);
struct BME_Vert *BME_edge_getothervert(struct BME_Edge *e, struct BME_Vert *v);
@@ -146,7 +169,7 @@ int BME_radial_find_face(struct BME_Edge *e,struct BME_Poly *f);
struct BME_Loop *BME_loop_find_loop(struct BME_Poly *f, struct BME_Vert *v);
/*MESH CREATION/DESTRUCTION*/
-struct BME_Mesh *BME_make_mesh(void);
+struct BME_Mesh *BME_make_mesh(int allocsize[4], struct BME_CustomDataInit init[4]);
void BME_free_mesh(struct BME_Mesh *bm);
/*FULL MESH VALIDATION*/
int BME_validate_mesh(struct BME_Mesh *bm, int halt);
@@ -230,8 +253,8 @@ float *BME_bevel_calc_polynormal(struct BME_Poly *f, struct BME_TransData_Head *
struct BME_Mesh *BME_bevel(struct BME_Mesh *bm, float value, int res, int options, int defgrp_index, float angle, BME_TransData_Head **rtd);
/*CONVERSION FUNCTIONS*/
-struct BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em, struct BME_Mesh *bm);
+struct BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em);
struct EditMesh *BME_bmesh_to_editmesh(struct BME_Mesh *bm, BME_TransData_Head *td);
-struct BME_Mesh *BME_derivedmesh_to_bmesh(struct DerivedMesh *dm, struct BME_Mesh *bm);
+struct BME_Mesh *BME_derivedmesh_to_bmesh(struct DerivedMesh *dm);
struct DerivedMesh *BME_bmesh_to_derivedmesh(struct BME_Mesh *bm, struct DerivedMesh *dm);
#endif
diff --git a/source/blender/blenkernel/BKE_bmeshCustomData.h b/source/blender/blenkernel/BKE_bmeshCustomData.h
new file mode 100644
index 00000000000..423f75e532d
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bmeshCustomData.h
@@ -0,0 +1,108 @@
+/**
+ * BKE_bmesh.h jan 2007
+ *
+ * BMesh modeler structure and functions.
+ *
+ * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#ifndef BKE_BMESHCUSTOMDATA_H
+#define BKE_BMESHCUSTOMDATA_H
+
+struct BME_mempool;
+
+/*Custom Data Types and defines
+ Eventual plan is to move almost everything to custom data and let caller
+ decide when making the mesh what layers they want to store in the mesh
+
+ This stuff should probably go in a seperate file....
+*/
+
+#define BME_CD_FACETEX 0 /*Image texture/texface*/
+#define BME_CD_LOOPTEX 1 /*UV coordinates*/
+#define BME_CD_LOOPCOL 2 /*Vcolors*/
+#define BME_CD_DEFORMVERT 3 /*Vertex Group/Weights*/
+#define BME_CD_NUMTYPES 4
+
+typedef struct BME_CustomDataLayer {
+ int type; /* type of data in layer */
+ int offset; /* offset of layer in block */
+ int active; /* offset of active layer*/
+ char name[32]; /* layer name */
+} BME_CustomDataLayer;
+
+typedef struct BME_CustomData {
+ struct BME_CustomDataLayer *layers; /*Custom Data Layers*/
+ struct BME_mempool *pool; /*pool for alloc of blocks*/
+ int totlayer, totsize; /*total layers and total size in bytes of each block*/
+} BME_CustomData;
+
+typedef struct BME_CustomDataInit{
+ int layout[BME_CD_NUMTYPES];
+ int active[BME_CD_NUMTYPES];
+ int totlayers;
+ char *nametemplate;
+} BME_CustomDataInit;
+
+/*Custom data types*/
+typedef struct BME_DeformWeight {
+ int def_nr;
+ float weight;
+} BME_DeformWeight;
+
+typedef struct BME_DeformVert {
+ struct BME_DeformWeight *dw;
+ int totweight;
+} BME_DeformVert;
+
+typedef struct BME_facetex{
+ struct Image *tpage;
+ char flag, transp;
+ short mode, tile, unwrap;
+}BME_facetex;
+
+typedef struct BME_looptex{
+ float u, v;
+}BME_looptex;
+
+typedef struct BME_loopcol{
+ char r, g, b, a;
+}BME_loopcol;
+
+/*CUSTOM DATA API*/
+void BME_CD_Create(struct BME_CustomData *data, struct BME_CustomDataInit *init, int initalloc);
+void BME_CD_Free(struct BME_CustomData *data);
+void BME_CD_free_block(struct BME_CustomData *data, void **block);
+void BME_CD_copy_data(const struct BME_CustomData *source, struct BME_CustomData *dest, void *src_block, void **dest_block);
+void BME_CD_set_default(struct BME_CustomData *data, void **block);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index af920e9762d..2e5da236a89 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -24,14 +24,14 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Daniel Genrich
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef BKE_CLOTH_H
#define BKE_CLOTH_H
-#include "float.h"
+#include <float.h>
#include "BLI_linklist.h"
#include "BKE_customdata.h"
@@ -102,7 +102,8 @@ typedef struct Cloth
unsigned char old_solver_type; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
- struct BVH *tree; /* collision tree for this cloth object */
+ struct BVHTree *bvhtree; /* collision tree for this cloth object */
+ struct BVHTree *bvhselftree; /* collision tree for this cloth object */
struct MFace *mfaces;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */
@@ -171,17 +172,10 @@ ClothSpring;
/* These are the bits used in SimSettings.flags. */
typedef enum
{
- //CLOTH_SIMSETTINGS_FLAG_RESET = ( 1 << 1 ), // The CM object requires a reinitializaiton.
CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ),// object is only collision object, no cloth simulation is done
CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled
CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled
- //CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled
- //CLOTH_SIMSETTINGS_FLAG_EDITMODE = ( 1 << 6 ), // are we in editmode? -several things disabled
- //CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE = ( 1 << 7 ), /* force cache freeing */
CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */
- //CLOTH_SIMSETTINGS_FLAG_LOADED = ( 1 << 9 ), /* did we just got load? */
- //CLOTH_SIMSETTINGS_FLAG_AUTOPROTECT = ( 1 << 10 ), /* is autoprotect enabled? */
- //CLOTH_SIMSETTINGS_FLAG_CCACHE_OUTDATED = (1 << 11), /* while protected, did cache get outdated? */
CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12) /* edit cache in editmode */
} CLOTH_SIMSETTINGS_FLAGS;
@@ -208,6 +202,7 @@ typedef enum
CLOTH_SPRING_FLAG_NEEDED = ( 1 << 2 ), // springs has values to be applied
} CLOTH_SPRINGS_FLAGS;
+
/////////////////////////////////////////////////
// collision.c
////////////////////////////////////////////////
@@ -246,7 +241,8 @@ DerivedMesh *clothModifier_do ( ClothModifierData *clmd,Object *ob, DerivedMesh
void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface );
// needed for collision.c
-void bvh_update_from_cloth ( ClothModifierData *clmd, int moving );
+void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving );
+void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving );
// needed for editmesh.c
void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr );
@@ -261,11 +257,6 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in
////////////////////////////////////////////////
-/* Typedefs for function pointers we need for solvers and collision detection. */
-typedef void ( *CM_COLLISION_SELF ) ( ClothModifierData *clmd, int step );
-typedef void ( *CM_COLLISION_OBJ ) ( ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response );
-
-
/* This enum provides the IDs for our solvers. */
// only one available in the moment
typedef enum
@@ -286,15 +277,6 @@ typedef struct
}
CM_SOLVER_DEF;
-/* used for caching in implicit.c */
-typedef struct Frame
-{
- ClothVertex *verts;
- ClothSpring *springs;
- unsigned int numverts, numsprings;
- float time; /* we need float since we want to support sub-frames */
-}
-Frame;
#endif
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 7328f9108e3..2966d932a49 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -24,7 +24,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Daniel Genrich
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -32,7 +32,7 @@
#define BKE_COLLISIONS_H
#include <math.h>
-#include "float.h"
+#include <float.h>
#include <stdlib.h>
#include <string.h>
@@ -47,68 +47,27 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
+#include "BLI_kdopbvh.h"
+
struct Object;
struct Cloth;
struct MFace;
struct DerivedMesh;
struct ClothModifierData;
-struct CollisionTree;
-
////////////////////////////////////////
-// used in kdop.c and collision.c
+// used for collisions in collision.c
////////////////////////////////////////
-typedef struct CollisionTree
-{
- struct CollisionTree *nodes[4]; // 4 children --> quad-tree
- struct CollisionTree *parent;
- struct CollisionTree *nextLeaf;
- struct CollisionTree *prevLeaf;
- float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP
- unsigned int tri_index; // this saves the index of the face
- // int point_index[4]; // supports up to 4 points in a leaf
- int count_nodes; // how many nodes are used
- int traversed; // how many nodes already traversed until this level?
- int isleaf;
- float alpha; /* for selfcollision */
- float normal[3]; /* for selfcollision */
-}
-CollisionTree;
-typedef struct BVH
+/* COLLISION FLAGS */
+typedef enum
{
- unsigned int numfaces;
- unsigned int numverts;
- MVert *current_x; // e.g. txold in clothvertex
- MVert *current_xold; // e.g. tx in clothvertex
- MFace *mfaces; // just a pointer to the original datastructure
- struct LinkNode *tree;
- CollisionTree *root; // TODO: saving the root --> is this really needed? YES!
- CollisionTree *leaf_tree; /* Tail of the leaf linked list. */
- CollisionTree *leaf_root; /* Head of the leaf linked list. */
- float epsilon; /* epslion is used for inflation of the k-dop */
- int flags; /* bvhFlags */
-}
-BVH;
-////////////////////////////////////////
+ COLLISION_IN_FUTURE = ( 1 << 1 ),
+} COLLISION_FLAGS;
-
-////////////////////////////////////////
-// kdop.c
////////////////////////////////////////
-
-// needed for collision.c
-typedef void ( *CM_COLLISION_RESPONSE ) ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 );
-
-// needed for collision.c
-int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision);
-
-////////////////////////////////////////
-
-
-////////////////////////////////////////
-// used for collisions in kdop.c and also collision.c
+// used for collisions in collision.c
////////////////////////////////////////
/* used for collisions in collision.c */
typedef struct CollPair
@@ -119,10 +78,10 @@ typedef struct CollPair
float normal[3];
float vector[3]; // unnormalized collision vector: p2-p1
float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
- int lastsign; // indicates if the distance sign has changed, unused itm
+ int flag;
float time; // collision time, from 0 up to 1
- unsigned int ap1, ap2, ap3, bp1, bp2, bp3;
- unsigned int pointsb[4];
+ int ap1, ap2, ap3, bp1, bp2, bp3;
+ int pointsb[4];
}
CollPair;
@@ -157,32 +116,22 @@ FaceCollPair;
// forward declarations
/////////////////////////////////////////////////
-// NOTICE: mvert-routines for building + update the BVH are the most native ones
-
-// builds bounding volume hierarchy
-void bvh_build (BVH *bvh);
-BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon);
-
-// frees the same
-void bvh_free ( BVH * bvh );
-
-// checks two bounding volume hierarchies for potential collisions and returns some list with those
-
-
-// update bounding volumes, needs updated positions in bvh->current_xold (static)
-// and also bvh->current_x if moving==1
-void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving);
-void bvh_update(BVH * bvh, int moving);
+/////////////////////////////////////////////////
+// used in modifier.c from collision.c
+/////////////////////////////////////////////////
+BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon );
+void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving );
+/////////////////////////////////////////////////
LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr );
// move Collision modifier object inter-frame with step = [0,1]
// defined in collisions.c
-void collision_move_object(CollisionModifierData *collmd, float step, float prevstep);
+void collision_move_object ( CollisionModifierData *collmd, float step, float prevstep );
// interface for collision functions
-void collisions_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3);
-void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3);
+void collisions_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 );
+void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 );
/////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 60444675047..45d8193b16f 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -39,8 +39,8 @@ struct ListBase;
struct BezTriple;
struct BevList;
-#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (nu->orderu-1)*((nu)->flagu & 1) )
-#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (nu->orderv-1)*((nu)->flagv & 1) )
+#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (nu->orderu-1)*((nu)->flagu & CU_CYCLIC) )
+#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (nu->orderv-1)*((nu)->flagv & CU_CYCLIC) )
void unlink_curve( struct Curve *cu);
@@ -84,5 +84,12 @@ void switchdirectionNurb( struct Nurb *nu);
float (*curve_getVertexCos(struct Curve *cu, struct ListBase *lb, int *numVerts_r))[3];
void curve_applyVertexCos(struct Curve *cu, struct ListBase *lb, float (*vertexCos)[3]);
+/* nurb checks if they can be drawn, also clamp order func */
+int check_valid_nurb_u( struct Nurb *nu);
+int check_valid_nurb_v( struct Nurb *nu);
+
+int clamp_nurb_order_u( struct Nurb *nu);
+int clamp_nurb_order_v( struct Nurb *nu);
+
#endif
diff --git a/source/blender/blenkernel/intern/BME_Customdata.c b/source/blender/blenkernel/intern/BME_Customdata.c
new file mode 100644
index 00000000000..8b48efbdbd2
--- /dev/null
+++ b/source/blender/blenkernel/intern/BME_Customdata.c
@@ -0,0 +1,198 @@
+/**
+ * BME_customdata.c jan 2007
+ *
+ * Custom Data functions for Bmesh
+ *
+ * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle, Brecht Van Lommel, Ben Batt
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include "BKE_bmesh.h"
+#include "BKE_bmeshCustomData.h"
+#include "bmesh_private.h"
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+/********************* Layer type information **********************/
+typedef struct BME_LayerTypeInfo {
+ int size;
+ char *defaultname;
+ void (*copy)(const void *source, void *dest, int count);
+ void (*free)(void *data, int count, int size);
+ void (*interp)(void **sources, float *weights, float *sub_weights, int count, void *dest);
+ void (*set_default)(void *data, int count);
+} BME_LayerTypeInfo;
+const BME_LayerTypeInfo BMELAYERTYPEINFO[BME_CD_NUMTYPES] = {
+ {sizeof(BME_facetex), "TexFace", NULL, NULL, NULL, NULL},
+ {sizeof(BME_looptex), "UV", NULL, NULL, NULL, NULL},
+ {sizeof(BME_loopcol), "VCol", NULL, NULL, NULL, NULL},
+ {sizeof(BME_DeformVert), "Group", NULL, NULL, NULL, NULL}
+};
+static const BME_LayerTypeInfo *BME_layerType_getInfo(int type)
+{
+ if(type < 0 || type >= CD_NUMTYPES) return NULL;
+
+ return &BMELAYERTYPEINFO[type];
+}
+void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc)
+{
+ int i, j, offset=0;
+ const BME_LayerTypeInfo *info;
+
+ /*initialize data members*/
+ data->layers = NULL;
+ data->pool = NULL;
+ data->totlayer = 0;
+ data->totsize = 0;
+
+ /*first count how many layers to alloc*/
+ for(i=0; i < BME_CD_NUMTYPES; i++){
+ info = BME_layerType_getInfo(i);
+ data->totlayer += init->layout[i];
+ data->totsize += (init->layout[i] * info->size);
+ }
+ /*alloc our layers*/
+ if(data->totlayer){
+ /*alloc memory*/
+ data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers");
+ data->pool = BME_mempool_create(data->totsize, initalloc, initalloc);
+ /*initialize layer data*/
+ for(i=0; i < BME_CD_NUMTYPES; i++){
+ if(init->layout[i]){
+ info = BME_layerType_getInfo(i);
+ for(j=0; j < init->layout[i]; j++){
+ if(j==0) data->layers[j+i].active = init->active[i];
+ data->layers[j+i].type = i;
+ data->layers[j+i].offset = offset;
+ strcpy(data->layers[j+i].name, &(init->nametemplate[j+i]));
+ offset += info->size;
+ }
+ }
+ }
+ }
+}
+
+void BME_CD_Free(BME_CustomData *data)
+{
+ if(data->pool) BME_mempool_destroy(data->pool);
+}
+
+/*Block level ops*/
+void BME_CD_free_block(BME_CustomData *data, void **block)
+{
+ const BME_LayerTypeInfo *typeInfo;
+ int i;
+
+ if(!*block) return;
+ for(i = 0; i < data->totlayer; ++i) {
+ typeInfo = BME_layerType_getInfo(data->layers[i].type);
+ if(typeInfo->free) {
+ int offset = data->layers[i].offset;
+ typeInfo->free((char*)*block + offset, 1, typeInfo->size);
+ }
+ }
+ BME_mempool_free(data->pool, *block);
+ *block = NULL;
+}
+
+
+static void BME_CD_alloc_block(BME_CustomData *data, void **block)
+{
+
+ if (*block) BME_CD_free_block(data, block); //if we copy layers that have their own free functions like deformverts
+
+ if (data->totsize > 0)
+ *block = BME_mempool_alloc(data->pool);
+ else
+ *block = NULL;
+}
+
+void BME_CD_copy_data(const BME_CustomData *source, BME_CustomData *dest,
+ void *src_block, void **dest_block)
+{
+ const BME_LayerTypeInfo *typeInfo;
+ int dest_i, src_i;
+
+ if (!*dest_block) /*for addXXXlist functions!*/
+ BME_CD_alloc_block(dest, dest_block);
+
+ /* copies a layer at a time */
+ dest_i = 0;
+ for(src_i = 0; src_i < source->totlayer; ++src_i) {
+
+ /* find the first dest layer with type >= the source type
+ * (this should work because layers are ordered by type)
+ */
+ while(dest_i < dest->totlayer
+ && dest->layers[dest_i].type < source->layers[src_i].type)
+ ++dest_i;
+
+ /* if there are no more dest layers, we're done */
+ if(dest_i >= dest->totlayer) return;
+
+ /* if we found a matching layer, copy the data */
+ if(dest->layers[dest_i].type == source->layers[src_i].type &&
+ strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) {
+ char *src_data = (char*)src_block + source->layers[src_i].offset;
+ char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset;
+
+ typeInfo = BME_layerType_getInfo(source->layers[src_i].type);
+
+ if(typeInfo->copy)
+ typeInfo->copy(src_data, dest_data, 1);
+ else
+ memcpy(dest_data, src_data, typeInfo->size);
+
+ /* if there are multiple source & dest layers of the same type,
+ * we don't want to copy all source layers to the same dest, so
+ * increment dest_i
+ */
+ ++dest_i;
+ }
+ }
+}
+void BME_CD_set_default(BME_CustomData *data, void **block)
+{
+ const BME_LayerTypeInfo *typeInfo;
+ int i;
+
+ if (!*block)
+ BME_CD_alloc_block(data, block); //for addXXXlist functions...
+
+ for(i = 0; i < data->totlayer; ++i) {
+ int offset = data->layers[i].offset;
+
+ typeInfo = BME_layerType_getInfo(data->layers[i].type);
+
+ if(typeInfo->set_default)
+ typeInfo->set_default((char*)*block + offset, 1);
+ }
+}
diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c
index 369c19b16c8..08483711c45 100644
--- a/source/blender/blenkernel/intern/BME_conversions.c
+++ b/source/blender/blenkernel/intern/BME_conversions.c
@@ -55,7 +55,10 @@
#include "BSE_edit.h"
-BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em, BME_Mesh *bm) {
+BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) {
+ BME_Mesh *bm;
+ int allocsize[4] = {512,512,2048,512};
+ BME_CustomDataInit *init = MEM_callocN(sizeof(BME_CustomDataInit) * 4, "Bmesh custom data init");
BME_Vert *v1, *v2;
BME_Edge *e, *edar[4];
BME_Poly *f;
@@ -65,7 +68,7 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em, BME_Mesh *bm) {
EditFace *efa;
int len;
-
+ bm = BME_make_mesh(allocsize,init);
BME_model_begin(bm);
/*add verts*/
@@ -134,6 +137,7 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em, BME_Mesh *bm) {
efa = efa->next;
}
BME_model_end(bm);
+ MEM_freeN(init);
return bm;
}
@@ -224,21 +228,24 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) {
}
/* Adds the geometry found in dm to bm
- * NOTE: it does not allocate a new BME_Mesh!
- */
-BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm, BME_Mesh *bm)
+ */
+BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
{
+
+ BME_Mesh *bm;
+ int allocsize[4] = {512,512,2048,512};
+ BME_CustomDataInit *init = MEM_callocN(sizeof(BME_CustomDataInit) * 4, "Bmesh custom data init");
MVert *mvert, *mv;
MEdge *medge, *me;
MFace *mface, *mf;
int totface,totedge,totvert,i,len;
-
BME_Vert *v1=NULL,*v2=NULL, **vert_array;
BME_Edge *e=NULL;
BME_Poly *f=NULL;
EdgeHash *edge_hash = BLI_edgehash_new();
-
+
+ bm = BME_make_mesh(allocsize,init);
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
totface = dm->getNumFaces(dm);
@@ -293,6 +300,7 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm, BME_Mesh *bm)
BME_model_end(bm);
BLI_edgehash_free(edge_hash, NULL);
MEM_freeN(vert_array);
+ MEM_freeN(init);
return bm;
}
diff --git a/source/blender/blenkernel/intern/BME_mesh.c b/source/blender/blenkernel/intern/BME_mesh.c
index d9d2354ef36..184ef2b8a0e 100644
--- a/source/blender/blenkernel/intern/BME_mesh.c
+++ b/source/blender/blenkernel/intern/BME_mesh.c
@@ -59,14 +59,39 @@
/*
* BME MAKE MESH
*
- * Allocates a new BME_Mesh structure
+ * Allocates a new BME_Mesh structure.
+ * The arguments are two arrays, one of type int
+ * and another of type BME_CustomDataInit. The first array
+ * contains the allocation size for each element pool in
+ * the mesh. For instance allocsize[0] contains the number
+ * of vertices to allocate at a time for the vertex pool.
+ *
+ * The second array contains structures describing the layout
+ * of custom data for each element type in the mesh. So init[0]
+ * contains the custom data layout information for vertices, init[1]
+ * the layout information for edges and so on.
+ *
+ * Returns -
+ * Pointer to a Bmesh
+ *
*/
-BME_Mesh *BME_make_mesh(void){
+BME_Mesh *BME_make_mesh(int allocsize[4], BME_CustomDataInit init[4])
+{
+ /*allocate the structure*/
BME_Mesh *bm = MEM_callocN(sizeof(BME_Mesh),"BMesh");
+ /*allocate the memory pools for the mesh elements*/
+ bm->vpool = BME_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0]);
+ bm->epool = BME_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1]);
+ bm->lpool = BME_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2]);
+ bm->ppool = BME_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3]);
+ /*Setup custom data layers*/
+ BME_CD_Create(&bm->vdata, &init[0], allocsize[0]);
+ BME_CD_Create(&bm->edata, &init[1], allocsize[1]);
+ BME_CD_Create(&bm->ldata, &init[2], allocsize[2]);
+ BME_CD_Create(&bm->pdata, &init[3], allocsize[3]);
return bm;
}
-
/*
* BME FREE MESH
*
@@ -75,45 +100,31 @@ BME_Mesh *BME_make_mesh(void){
void BME_free_mesh(BME_Mesh *bm)
{
- BME_Poly *bf, *nextf;
- BME_Edge *be, *nexte;
- BME_Vert *bv, *nextv;
- BME_CycleNode *loopref;
-
- /*destroy polygon data*/
- bf = bm->polys.first;
- while(bf){
- nextf = bf->next;
- BLI_remlink(&(bm->polys), bf);
- BME_free_poly(bm, bf);
-
- bf = nextf;
- }
- /*destroy edge data*/
- be = bm->edges.first;
- while(be){
- nexte = be->next;
- BLI_remlink(&(bm->edges), be);
- BME_free_edge(bm, be);
- be = nexte;
- }
- /*destroy vert data*/
- bv = bm->verts.first;
- while(bv){
- nextv = bv->next;
- BLI_remlink(&(bm->verts), bv);
- BME_free_vert(bm, bv);
- bv = nextv;
+ BME_Vert *v;
+ BME_Edge *e;
+ BME_Loop *l;
+ BME_Poly *f;
+
+ for(v=bm->verts.first; v; v=v->next) BME_CD_free_block(&bm->vdata, &v->data);
+ for(e=bm->edges.first; e; e=e->next) BME_CD_free_block(&bm->edata, &e->data);
+ for(f=bm->polys.first; f; f=f->next){
+ BME_CD_free_block(&bm->pdata, &f->data);
+ l = f->loopbase;
+ do{
+ BME_CD_free_block(&bm->ldata, &l->data);
+ l = l->next;
+ }while(l!=f->loopbase);
}
-
- for(loopref=bm->loops.first;loopref;loopref=loopref->next) BME_delete_loop(bm,loopref->data);
- BLI_freelistN(&(bm->loops));
-
- //CustomData_free(&bm->vdata, 0);
- //CustomData_free(&bm->edata, 0);
- //CustomData_free(&bm->ldata, 0);
- //CustomData_free(&bm->pdata, 0);
-
+ /*destroy element pools*/
+ BME_mempool_destroy(bm->vpool);
+ BME_mempool_destroy(bm->epool);
+ BME_mempool_destroy(bm->ppool);
+ BME_mempool_destroy(bm->lpool);
+ /*free custom data pools*/
+ BME_CD_Free(&bm->vdata);
+ BME_CD_Free(&bm->edata);
+ BME_CD_Free(&bm->ldata);
+ BME_CD_Free(&bm->pdata);
MEM_freeN(bm);
}
@@ -124,17 +135,12 @@ void BME_free_mesh(BME_Mesh *bm)
* must begin with a call to BME_model_end() and finish with a call to BME_model_end().
* No modification of mesh data is allowed except in between these two calls.
*
- * TODO
- * FOR BME_MODEL_BEGIN:
- * -integrate euler undo system.
- * -make full copy of structure to safely recover from errors.
- * -accept a toolname string.
- * -accept param to turn off full copy if just selection tool. (perhaps check for this in eulers...)
+ * The purpose of these calls is allow for housekeeping tasks to be performed,
+ * such as allocating/freeing scratch arrays or performing debug validation of
+ * the mesh structure.
*
- * BME_MODEL_END:
- * -full mesh validation if debugging turned on
- * -free structure copy or use it to restore.
- * -do euler undo push.
+ * Returns -
+ * Nothing
*
*/
@@ -151,13 +157,12 @@ int BME_model_begin(BME_Mesh *bm){
}
void BME_model_end(BME_Mesh *bm){
- int meshok, totvert, totedge, totpoly, totloop;
+ int meshok, totvert, totedge, totpoly;
totvert = BLI_countlist(&(bm->verts));
totedge = BLI_countlist(&(bm->edges));
totpoly = BLI_countlist(&(bm->polys));
- totloop = BLI_countlist(&(bm->loops));
-
+
if(bm->vtar) MEM_freeN(bm->vtar);
if(bm->edar) MEM_freeN(bm->edar);
if(bm->lpar) MEM_freeN(bm->lpar);
@@ -167,10 +172,10 @@ void BME_model_end(BME_Mesh *bm){
bm->edar = NULL;
bm->lpar = NULL;
bm->plar = NULL;
- bm->vtarlen = bm->edarlen = bm->lparlen = bm->plarlen = 1024;
+ bm->vtarlen = bm->edarlen = bm->lparlen = bm->plarlen = 0;
- if(bm->totvert!=totvert || bm->totedge!=totedge || bm->totpoly!=totpoly || bm->totloop!=totloop)
+ if(bm->totvert!=totvert || bm->totedge!=totedge || bm->totpoly!=totpoly)
BME_error();
meshok = BME_validate_mesh(bm, 1);
@@ -194,7 +199,7 @@ void BME_model_end(BME_Mesh *bm){
*
* TODO
*
- * -Write a full mesh validation function for debugging purposes.
+ * -Make this only part of debug builds
*/
#define VHALT(halt) {BME_error(); if(halt) return 0;}
diff --git a/source/blender/blenkernel/intern/BME_structure.c b/source/blender/blenkernel/intern/BME_structure.c
index d283e1df5ca..cbf780c6467 100644
--- a/source/blender/blenkernel/intern/BME_structure.c
+++ b/source/blender/blenkernel/intern/BME_structure.c
@@ -43,6 +43,99 @@
#include "BLI_ghash.h"
#include "BKE_customdata.h"
+
+/*
+ Simple, fast memory allocator for allocating many elements of the same size.
+*/
+typedef struct BME_mempool_chunk{
+ struct BME_mempool_chunk *next, *prev;
+ void *data;
+}BME_mempool_chunk;
+
+/*this is just to make things prettier*/
+typedef struct BME_freenode{
+ struct BME_freenode *next;
+}BME_freenode;
+
+BME_mempool *BME_mempool_create(int esize, int tote, int pchunk)
+{ BME_mempool *pool = NULL;
+ BME_freenode *lasttail = NULL, *curnode = NULL;
+ int i,j, maxchunks;
+ char *addr;
+
+ /*allocate the pool structure*/
+ pool = MEM_mallocN(sizeof(BME_mempool),"memory pool");
+ pool->esize = esize;
+ pool->pchunk = pchunk;
+ pool->csize = esize * pchunk;
+ pool->chunks.first = pool->chunks.last = NULL;
+
+ maxchunks = tote / pchunk;
+
+ /*allocate the actual chunks*/
+ for(i=0; i < maxchunks; i++){
+ BME_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BME_mempool_chunk), "BME_Mempool Chunk");
+ mpchunk->next = mpchunk->prev = NULL;
+ mpchunk->data = MEM_mallocN(pool->csize, "BME Mempool Chunk Data");
+ BLI_addtail(&(pool->chunks), mpchunk);
+
+ if(i==0) pool->free = mpchunk->data; /*start of the list*/
+ /*loop through the allocated data, building the pointer structures*/
+ for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){
+ curnode = ((BME_freenode*)addr);
+ addr += pool->esize;
+ curnode->next = (BME_freenode*)addr;
+ }
+ /*final pointer in the previously allocated chunk is wrong.*/
+ if(lasttail) lasttail->next = mpchunk->data;
+ /*set the end of this chunks memory to the new tail for next iteration*/
+ lasttail = curnode;
+ }
+ /*terminate the list*/
+ curnode->next = NULL;
+ return pool;
+}
+
+void *BME_mempool_alloc(BME_mempool *pool){
+ void *retval=NULL;
+ BME_freenode *curnode=NULL;
+ char *addr=NULL;
+ int j;
+
+ if(!(pool->free)){
+ /*need to allocate a new chunk*/
+ BME_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BME_mempool_chunk), "BME_Mempool Chunk");
+ mpchunk->next = mpchunk->prev = NULL;
+ mpchunk->data = MEM_mallocN(pool->csize, "BME_Mempool Chunk Data");
+ BLI_addtail(&(pool->chunks), mpchunk);
+
+ pool->free = mpchunk->data; /*start of the list*/
+ for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){
+ curnode = ((BME_freenode*)addr);
+ addr += pool->esize;
+ curnode->next = (BME_freenode*)addr;
+ }
+ curnode->next = NULL; /*terminate the list*/
+ }
+
+ retval = pool->free;
+ pool->free = pool->free->next;
+ //memset(retval, 0, pool->esize);
+ return retval;
+}
+
+void BME_mempool_free(BME_mempool *pool, void *addr){ //doesnt protect against double frees, dont be stupid!
+ BME_freenode *newhead = addr;
+ newhead->next = pool->free;
+ pool->free = newhead;
+}
+void BME_mempool_destroy(BME_mempool *pool)
+{
+ BME_mempool_chunk *mpchunk=NULL;
+ for(mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) MEM_freeN(mpchunk->data);
+ BLI_freelistN(&(pool->chunks));
+ MEM_freeN(pool);
+}
/**
* MISC utility functions.
*
@@ -86,78 +179,98 @@ int BME_edge_swapverts(BME_Edge *e, BME_Vert *orig, BME_Vert *new){
BME_Vert *BME_addvertlist(BME_Mesh *bm, BME_Vert *example){
BME_Vert *v=NULL;
- v = MEM_callocN(sizeof(BME_Vert), "BME Vertex");
- BLI_addtail(&(bm->verts), v);
+ v = BME_mempool_alloc(bm->vpool);
+ v->next = v->prev = NULL;
v->EID = bm->nextv;
+ v->co[0] = v->co[1] = v->co[2] = 0.0f;
+ v->no[0] = v->no[1] = v->no[2] = 0.0f;
+ v->edge = NULL;
+ v->data = NULL;
+ v->eflag1 = v->eflag2 = v->tflag1 = v->tflag2 = 0;
+ v->flag = v->h = 0;
+ v->bweight = 0.0f;
+ BLI_addtail(&(bm->verts), v);
bm->nextv++;
bm->totvert++;
- if(example)
+ if(example){
VECCOPY(v->co,example->co);
- //if(example)
- // CustomData_em_copy_data(&bm->vdata, &bm->vdata, example->data, &v->data);
- //else
- // CustomData_em_set_default(&bm->vdata, &v->data);
+ BME_CD_copy_data(&bm->vdata, &bm->vdata, example->data, &v->data);
+ }
+ else
+ BME_CD_set_default(&bm->vdata, &v->data);
return v;
}
BME_Edge *BME_addedgelist(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge *example){
BME_Edge *e=NULL;
- e = MEM_callocN(sizeof(BME_Edge), "BME_Edge");
+ e = BME_mempool_alloc(bm->epool);
+ e->next = e->prev = NULL;
+ e->EID = bm->nexte;
e->v1 = v1;
e->v2 = v2;
+ e->d1.next = e->d1.prev = e->d2.next = e->d2.prev = NULL;
e->d1.data = e;
e->d2.data = e;
- e->EID = bm->nexte;
+ e->loop = NULL;
+ e->data = NULL;
+ e->eflag1 = e->eflag2 = e->tflag1 = e->tflag2 = 0;
+ e->flag = e->h = 0;
+ e->crease = e->bweight = 0.0f;
bm->nexte++;
bm->totedge++;
BLI_addtail(&(bm->edges), e);
- //if(example)
- // CustomData_em_copy_data(&bm->edata, &bm->edata, example->data, &e->data);
- //else
- // CustomData_em_set_default(&bm->edata, &e->data);
+ if(example)
+ BME_CD_copy_data(&bm->edata, &bm->edata, example->data, &e->data);
+ else
+ BME_CD_set_default(&bm->edata, &e->data);
return e;
}
BME_Loop *BME_create_loop(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Poly *f, BME_Loop *example){
- /*allocate a BME_Loop and add it to the loophash*/
BME_Loop *l=NULL;
- BME_CycleNode *loopnode = MEM_callocN(sizeof(BME_CycleNode),"BME Loop Reference");
- l = MEM_callocN(sizeof(BME_Loop), "BME_Loop");
+ l = BME_mempool_alloc(bm->lpool);
+ l->next = l->prev = NULL;
+ l->EID = bm->nextl;
+ l->radial.next = l->radial.prev = NULL;
l->radial.data = l;
l->v = v;
l->e = e;
l->f = f;
- l->EID = bm->nextl;
- l->gref = loopnode;
- loopnode->data = l;
- BLI_addtail(&(bm->loops),loopnode);
+ l->data = NULL;
+ l->eflag1 = l->eflag2 = l->tflag1 = l->tflag2 = 0;
+ l->flag = l->h = 0; //stupid waste!
bm->nextl++;
bm->totloop++;
-
-/* if(example)
- BME_CustomData_copy_data(&bm->ldata, &bm->ldata, example->data, &l->data);
+ if(example)
+ BME_CD_copy_data(&bm->ldata, &bm->ldata, example->data, &l->data);
else
- BME_CustomData_set_default(&bm->ldata, &l->data);
-*/
+ BME_CD_set_default(&bm->ldata, &l->data);
+
return l;
}
BME_Poly *BME_addpolylist(BME_Mesh *bm, BME_Poly *example){
BME_Poly *f = NULL;
- f= MEM_callocN(sizeof(BME_Poly),"BME_Poly");
- BLI_addtail(&(bm->polys),f);
+ f = BME_mempool_alloc(bm->ppool);
+ f->next = f->prev = NULL;
f->EID = bm->nextp;
+ f->loopbase = NULL;
+ f->len = 0;
+ f->data = NULL;
+ f->eflag1 = f->eflag2 = f->tflag1 = f->tflag2 = 0;
+ f->flag = f->h = f->mat_nr;
+ BLI_addtail(&(bm->polys),f);
bm->nextp++;
bm->totpoly++;
- //if(example)
- // CustomData_em_copy_data(&bm->pdata, &bm->pdata, example->data, &f->data);
- //else
- // CustomData_em_set_default(&bm->pdata, &f->data);
+ if(example)
+ BME_CD_copy_data(&bm->pdata, &bm->pdata, example->data, &f->data);
+ else
+ BME_CD_set_default(&bm->pdata, &f->data);
return f;
@@ -168,31 +281,24 @@ BME_Poly *BME_addpolylist(BME_Mesh *bm, BME_Poly *example){
*/
void BME_free_vert(BME_Mesh *bm, BME_Vert *v){
bm->totvert--;
- //CustomData_em_free_block(&bm->vdata, &v->data);
- MEM_freeN(v);
+ BME_CD_free_block(&bm->vdata, &v->data);
+ BME_mempool_free(bm->vpool, v);
}
void BME_free_edge(BME_Mesh *bm, BME_Edge *e){
bm->totedge--;
- //CustomData_em_free_block(&bm->edata, &e->data);
- MEM_freeN(e);
+ BME_CD_free_block(&bm->edata, &e->data);
+ BME_mempool_free(bm->epool, e);
}
void BME_free_poly(BME_Mesh *bm, BME_Poly *f){
bm->totpoly--;
- //CustomData_em_free_block(&bm->pdata, &f->data);
- MEM_freeN(f);
-}
-void BME_delete_loop(BME_Mesh *bm, BME_Loop *l){
- bm->totloop--;
- //CustomData_em_free_block(&bm->ldata, &l->data);
- MEM_freeN(l);
+ BME_CD_free_block(&bm->pdata, &f->data);
+ BME_mempool_free(bm->ppool, f);
}
void BME_free_loop(BME_Mesh *bm, BME_Loop *l){
- BME_CycleNode *loopref = l->gref;
- BLI_freelinkN(&(bm->loops),loopref);
- BME_delete_loop(bm,l);
+ bm->totloop--;
+ BME_CD_free_block(&bm->ldata, &l->data);
+ BME_mempool_free(bm->lpool, l);
}
-
-
/**
* BMESH CYCLES
*
diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c
index 90fa9793644..7ce967d1d22 100644
--- a/source/blender/blenkernel/intern/BME_tools.c
+++ b/source/blender/blenkernel/intern/BME_tools.c
@@ -811,7 +811,18 @@ static float BME_bevel_get_angle(BME_Mesh *bm, BME_Edge *e, BME_Vert *v) {
return Inpf(vec3,vec4);
}
-
+static int BME_face_sharededges(BME_Poly *f1, BME_Poly *f2){
+ BME_Loop *l;
+ int count = 0;
+
+ l = f1->loopbase;
+ do{
+ if(BME_radial_find_face(l->e,f2)) count++;
+ l = l->next;
+ }while(l != f1->loopbase);
+
+ return count;
+}
/**
* BME_bevel_initialize
*
@@ -990,6 +1001,17 @@ static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int defgrp_inde
/* face pass */
for (f=bm->polys.first; f; f=f->next) f->tflag1 = BME_BEVEL_ORIG;
+ /*clean up edges with 2 faces that share more than one edge*/
+ for (e=bm->edges.first; e; e=e->next){
+ if(e->tflag1 & BME_BEVEL_BEVEL){
+ int count = 0;
+ count = BME_face_sharededges(e->loop->f, ((BME_Loop*)e->loop->radial.next->data)->f);
+ if(count > 1){
+ e->tflag1 &= ~BME_BEVEL_BEVEL;
+ }
+ }
+ }
+
return bm;
}
@@ -1075,7 +1097,7 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options,
v = BME_bevel_wire(bm, v, value, res, options, td);
}
else if (res && ((v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG))) {
-
+ int count = 0;
/* first, make sure we're not sitting on an edge to be removed */
oe = v->edge;
e = BME_disk_nextedge(oe,v);
@@ -1089,6 +1111,7 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options,
/* look for original edges, and remove them */
oe = e;
while ( (e = BME_disk_next_edgeflag(oe, v, 0, BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) ) {
+ count++;
/* join the faces (we'll split them later) */
f = BME_JFKE_safe(bm,e->loop->f,((BME_Loop*)e->loop->radial.next->data)->f,e);
if (!f){
@@ -1096,6 +1119,9 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options,
}
}
+ /*need to do double check *before* you bevel to make sure that manifold edges are for two faces that share only *one* edge to make sure it doesnt hang here!*/
+
+
/* all original edges marked to be beveled have been removed;
* now we need to link up the edges for this "corner" */
len = BME_cycle_length(BME_disk_getpointer(v->edge, v));
diff --git a/source/blender/blenkernel/intern/bmesh_private.h b/source/blender/blenkernel/intern/bmesh_private.h
index ad90398bf66..4aa2a85b8b1 100644
--- a/source/blender/blenkernel/intern/bmesh_private.h
+++ b/source/blender/blenkernel/intern/bmesh_private.h
@@ -39,6 +39,11 @@
#include "BKE_bmesh.h"
+struct BME_mempool *BME_mempool_create(int esize, int tote, int pchunk);
+void BME_mempool_destroy(struct BME_mempool *pool);
+void *BME_mempool_alloc(struct BME_mempool *pool);
+void BME_mempool_free(struct BME_mempool *pool, void *address);
+
/*ALLOCATION/DEALLOCATION*/
struct BME_Vert *BME_addvertlist(struct BME_Mesh *bm, struct BME_Vert *example);
struct BME_Edge *BME_addedgelist(struct BME_Mesh *bm, struct BME_Vert *v1, struct BME_Vert *v2, struct BME_Edge *example);
@@ -49,7 +54,7 @@ void BME_free_vert(struct BME_Mesh *bm, struct BME_Vert *v);
void BME_free_edge(struct BME_Mesh *bm, struct BME_Edge *e);
void BME_free_poly(struct BME_Mesh *bm, struct BME_Poly *f);
void BME_free_loop(struct BME_Mesh *bm, struct BME_Loop *l);
-void BME_delete_loop(struct BME_Mesh *bm, struct BME_Loop *l);
+//void BME_delete_loop(struct BME_Mesh *bm, struct BME_Loop *l);
/*DOUBLE CIRCULAR LINKED LIST FUNCTIONS*/
void BME_cycle_append(void *h, void *nt);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 09a51bb37a4..6034b85e20f 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -45,6 +45,8 @@
#include "BKE_pointcache.h"
+#include "BLI_kdopbvh.h"
+
#ifdef _WIN32
void tstart ( void )
{}
@@ -151,13 +153,14 @@ void cloth_init ( ClothModifierData *clmd )
clmd->sim_parms->goalfrict = 0.0f;
}
-
-BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon)
+BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon)
{
- unsigned int i = 0;
- BVH *bvh=NULL;
+ int i;
+ BVHTree *bvhtree;
Cloth *cloth = clmd->clothObject;
- ClothVertex *verts = NULL;
+ ClothVertex *verts;
+ MFace *mfaces;
+ float co[12];
if(!clmd)
return NULL;
@@ -168,69 +171,171 @@ BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon)
return NULL;
verts = cloth->verts;
+ mfaces = cloth->mfaces;
// in the moment, return zero if no faces there
- if(!cloth->numfaces)
+ if(!cloth->numverts)
return NULL;
- bvh = MEM_callocN(sizeof(BVH), "BVH");
- if (bvh == NULL)
+ // create quadtree with k=26
+ bvhtree = BLI_bvhtree_new(cloth->numverts, epsilon, 4, 6);
+
+ // fill tree
+ for(i = 0; i < cloth->numverts; i++, verts++)
{
- printf("bvh: Out of memory.\n");
- return NULL;
+ VECCOPY(&co[0*3], verts->xold);
+
+ BLI_bvhtree_insert(bvhtree, i, co, 1);
}
- // springs = cloth->springs;
- // numsprings = cloth->numsprings;
+ // balance tree
+ BLI_bvhtree_balance(bvhtree);
+
+ return bvhtree;
+}
- bvh->epsilon = epsilon;
- bvh->numfaces = cloth->numfaces;
- bvh->mfaces = cloth->mfaces;
+BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon)
+{
+ int i;
+ BVHTree *bvhtree;
+ Cloth *cloth = clmd->clothObject;
+ ClothVertex *verts;
+ MFace *mfaces;
+ float co[12];
+
+ if(!clmd)
+ return NULL;
- bvh->numverts = cloth->numverts;
+ cloth = clmd->clothObject;
+
+ if(!cloth)
+ return NULL;
- bvh->current_x = MEM_callocN ( sizeof ( MVert ) * bvh->numverts, "bvh->current_x" );
+ verts = cloth->verts;
+ mfaces = cloth->mfaces;
- if (bvh->current_x == NULL)
- {
- printf("bvh: Out of memory.\n");
- MEM_freeN(bvh);
+ // in the moment, return zero if no faces there
+ if(!cloth->numfaces)
return NULL;
- }
- for(i = 0; i < bvh->numverts; i++)
+ // create quadtree with k=26
+ bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 26);
+
+ // fill tree
+ for(i = 0; i < cloth->numfaces; i++, mfaces++)
{
- VECCOPY(bvh->current_x[i].co, verts[i].tx);
+ VECCOPY(&co[0*3], verts[mfaces->v1].xold);
+ VECCOPY(&co[1*3], verts[mfaces->v2].xold);
+ VECCOPY(&co[2*3], verts[mfaces->v3].xold);
+
+ if(mfaces->v4)
+ VECCOPY(&co[3*3], verts[mfaces->v4].xold);
+
+ BLI_bvhtree_insert(bvhtree, i, co, (mfaces->v4 ? 4 : 3));
}
- bvh_build (bvh);
+ // balance tree
+ BLI_bvhtree_balance(bvhtree);
- return bvh;
+ return bvhtree;
}
-void bvh_update_from_cloth(ClothModifierData *clmd, int moving)
-{
+void bvhtree_update_from_cloth(ClothModifierData *clmd, int moving)
+{
unsigned int i = 0;
Cloth *cloth = clmd->clothObject;
- BVH *bvh = cloth->tree;
+ BVHTree *bvhtree = cloth->bvhtree;
ClothVertex *verts = cloth->verts;
+ MFace *mfaces;
+ float co[12], co_moving[12];
+ int ret = 0;
- if(!bvh)
+ if(!bvhtree)
return;
- if(cloth->numverts!=bvh->numverts)
- return;
+ mfaces = cloth->mfaces;
- if(cloth->verts)
+ // update vertex position in bvh tree
+ if(verts && mfaces)
{
- for(i = 0; i < bvh->numverts; i++)
+ for(i = 0; i < cloth->numfaces; i++, mfaces++)
{
- VECCOPY(bvh->current_x[i].co, verts[i].tx);
- VECCOPY(bvh->current_xold[i].co, verts[i].txold);
+ VECCOPY(&co[0*3], verts[mfaces->v1].txold);
+ VECCOPY(&co[1*3], verts[mfaces->v2].txold);
+ VECCOPY(&co[2*3], verts[mfaces->v3].txold);
+
+ if(mfaces->v4)
+ VECCOPY(&co[3*3], verts[mfaces->v4].txold);
+
+ // copy new locations into array
+ if(moving)
+ {
+ // update moving positions
+ VECCOPY(&co_moving[0*3], verts[mfaces->v1].tx);
+ VECCOPY(&co_moving[1*3], verts[mfaces->v2].tx);
+ VECCOPY(&co_moving[2*3], verts[mfaces->v3].tx);
+
+ if(mfaces->v4)
+ VECCOPY(&co_moving[3*3], verts[mfaces->v4].tx);
+
+ ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, (mfaces->v4 ? 4 : 3));
+ }
+ else
+ {
+ ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, (mfaces->v4 ? 4 : 3));
+ }
+
+ // check if tree is already full
+ if(!ret)
+ break;
}
+
+ BLI_bvhtree_update_tree(bvhtree);
}
+}
+
+void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
+{
+ unsigned int i = 0;
+ Cloth *cloth = clmd->clothObject;
+ BVHTree *bvhtree = cloth->bvhselftree;
+ ClothVertex *verts = cloth->verts;
+ MFace *mfaces;
+ float co[12], co_moving[12];
+ int ret = 0;
+
+ if(!bvhtree)
+ return;
- bvh_update(bvh, moving);
+ mfaces = cloth->mfaces;
+
+ // update vertex position in bvh tree
+ if(verts && mfaces)
+ {
+ for(i = 0; i < cloth->numverts; i++, verts++)
+ {
+ VECCOPY(&co[0*3], verts->txold);
+
+ // copy new locations into array
+ if(moving)
+ {
+ // update moving positions
+ VECCOPY(&co_moving[0*3], verts->tx);
+
+ ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, 1);
+ }
+ else
+ {
+ ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, 1);
+ }
+
+ // check if tree is already full
+ if(!ret)
+ break;
+ }
+
+ BLI_bvhtree_update_tree(bvhtree);
+ }
}
int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
@@ -541,8 +646,11 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd )
cloth->numsprings = 0;
// free BVH collision tree
- if ( cloth->tree )
- bvh_free ( ( BVH * ) cloth->tree );
+ if ( cloth->bvhtree )
+ BLI_bvhtree_free ( cloth->bvhtree );
+
+ if ( cloth->bvhselftree )
+ BLI_bvhtree_free ( cloth->bvhselftree );
// we save our faces for collision objects
if ( cloth->mfaces )
@@ -611,8 +719,11 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd )
cloth->numsprings = 0;
// free BVH collision tree
- if ( cloth->tree )
- bvh_free ( ( BVH * ) cloth->tree );
+ if ( cloth->bvhtree )
+ BLI_bvhtree_free ( cloth->bvhtree );
+
+ if ( cloth->bvhselftree )
+ BLI_bvhtree_free ( cloth->bvhselftree );
// we save our faces for collision objects
if ( cloth->mfaces )
@@ -751,6 +862,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
ClothVertex *verts = NULL;
float tnull[3] = {0,0,0};
Cloth *cloth = NULL;
+ float maxdist = 0;
// If we have a clothObject, free it.
if ( clmd->clothObject != NULL )
@@ -810,6 +922,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
VECCOPY ( verts->xold, verts->x );
VECCOPY ( verts->xconst, verts->x );
VECCOPY ( verts->txold, verts->x );
+ VECCOPY ( verts->tx, verts->x );
VecMulf ( verts->v, 0.0f );
verts->impulse_count = 0;
@@ -819,8 +932,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
// apply / set vertex groups
// has to be happen before springs are build!
cloth_apply_vgroup (clmd, dm);
-
-
+
if ( !cloth_build_springs ( clmd, dm ) )
{
cloth_free_modifier ( ob, clmd );
@@ -845,12 +957,18 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
if(!first)
implicit_set_positions(clmd);
- clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon );
+ clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon );
+
+ for(i = 0; i < dm->getNumVerts(dm); i++)
+ {
+ maxdist = MAX2(maxdist, clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len*2.0));
+ }
+
+ clmd->clothObject->bvhselftree = bvhselftree_build_from_cloth ( clmd, maxdist );
return 1;
}
-
static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
{
unsigned int numverts = dm->getNumVerts ( dm );
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index e244ccca306..7f41ca033d3 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -41,7 +41,6 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-#include "BKE_cloth.h"
#include "BKE_modifier.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
@@ -49,6 +48,10 @@
#include "Bullet-C-Api.h"
+#include "BLI_kdopbvh.h"
+#include "BKE_collision.h"
+
+
/***********************************
Collision modifier code start
***********************************/
@@ -66,58 +69,80 @@ void collision_move_object ( CollisionModifierData *collmd, float step, float pr
VECADDS ( collmd->current_xnew[i].co, collmd->x[i].co, tv, step );
VECSUB ( collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co );
}
- bvh_update_from_mvert ( collmd->bvh, collmd->current_x, collmd->numverts, collmd->current_xnew, 1 );
+ bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
}
-/* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */
-BVH *bvh_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon )
+BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon )
{
- BVH *bvh=NULL;
-
- bvh = MEM_callocN ( sizeof ( BVH ), "BVH" );
- if ( bvh == NULL )
- {
- printf ( "bvh: Out of memory.\n" );
- return NULL;
- }
+ BVHTree *tree;
+ float co[12];
+ int i;
+ MFace *tface = mfaces;
- // in the moment, return zero if no faces there
- if ( !numfaces )
- return NULL;
+ tree = BLI_bvhtree_new ( numfaces*2, epsilon, 4, 26 );
- bvh->epsilon = epsilon;
- bvh->numfaces = numfaces;
- bvh->mfaces = mfaces;
-
- // we have no faces, we save seperate points
- if ( !mfaces )
+ // fill tree
+ for ( i = 0; i < numfaces; i++, tface++ )
{
- bvh->numfaces = numverts;
- }
+ VECCOPY ( &co[0*3], x[tface->v1].co );
+ VECCOPY ( &co[1*3], x[tface->v2].co );
+ VECCOPY ( &co[2*3], x[tface->v3].co );
+ if ( tface->v4 )
+ VECCOPY ( &co[3*3], x[tface->v4].co );
- bvh->numverts = numverts;
- bvh->current_x = MEM_dupallocN ( x );
+ BLI_bvhtree_insert ( tree, i, co, ( mfaces->v4 ? 4 : 3 ) );
+ }
- bvh_build ( bvh );
+ // balance tree
+ BLI_bvhtree_balance ( tree );
- return bvh;
+ return tree;
}
-void bvh_update_from_mvert ( BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving )
+void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving )
{
- if ( !bvh )
- return;
+ int i;
+ MFace *mfaces = faces;
+ float co[12], co_moving[12];
+ int ret = 0;
- if ( numverts!=bvh->numverts )
+ if ( !bvhtree )
return;
if ( x )
- memcpy ( bvh->current_xold, x, sizeof ( MVert ) * numverts );
+ {
+ for ( i = 0; i < numfaces; i++, mfaces++ )
+ {
+ VECCOPY ( &co[0*3], x[mfaces->v1].co );
+ VECCOPY ( &co[1*3], x[mfaces->v2].co );
+ VECCOPY ( &co[2*3], x[mfaces->v3].co );
+ if ( mfaces->v4 )
+ VECCOPY ( &co[3*3], x[mfaces->v4].co );
+
+ // copy new locations into array
+ if ( moving && xnew )
+ {
+ // update moving positions
+ VECCOPY ( &co_moving[0*3], xnew[mfaces->v1].co );
+ VECCOPY ( &co_moving[1*3], xnew[mfaces->v2].co );
+ VECCOPY ( &co_moving[2*3], xnew[mfaces->v3].co );
+ if ( mfaces->v4 )
+ VECCOPY ( &co_moving[3*3], xnew[mfaces->v4].co );
+
+ ret = BLI_bvhtree_update_node ( bvhtree, i, co, co_moving, ( mfaces->v4 ? 4 : 3 ) );
+ }
+ else
+ {
+ ret = BLI_bvhtree_update_node ( bvhtree, i, co, NULL, ( mfaces->v4 ? 4 : 3 ) );
+ }
- if ( xnew )
- memcpy ( bvh->current_x, xnew, sizeof ( MVert ) * numverts );
+ // check if tree is already full
+ if ( !ret )
+ break;
+ }
- bvh_update ( bvh, moving );
+ BLI_bvhtree_update_tree ( bvhtree );
+ }
}
/***********************************
@@ -125,47 +150,48 @@ Collision modifier code end
***********************************/
/**
- * gsl_poly_solve_cubic -
- *
- * copied from SOLVE_CUBIC.C --> GSL
- */
+* gsl_poly_solve_cubic -
+*
+* copied from SOLVE_CUBIC.C --> GSL
+*/
-/* DG: debug hint! don't forget that all functions were "fabs", "sinf", etc before */
-#define mySWAP(a,b) { float tmp = b ; b = a ; a = tmp ; }
+#define mySWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0)
-int gsl_poly_solve_cubic ( float a, float b, float c, float *x0, float *x1, float *x2 )
+int
+gsl_poly_solve_cubic (double a, double b, double c,
+ double *x0, double *x1, double *x2)
{
- float q = ( a * a - 3 * b );
- float r = ( 2 * a * a * a - 9 * a * b + 27 * c );
+ double q = (a * a - 3 * b);
+ double r = (2 * a * a * a - 9 * a * b + 27 * c);
- float Q = q / 9;
- float R = r / 54;
+ double Q = q / 9;
+ double R = r / 54;
- float Q3 = Q * Q * Q;
- float R2 = R * R;
+ double Q3 = Q * Q * Q;
+ double R2 = R * R;
- float CR2 = 729 * r * r;
- float CQ3 = 2916 * q * q * q;
+ double CR2 = 729 * r * r;
+ double CQ3 = 2916 * q * q * q;
- if ( R == 0 && Q == 0 )
+ if (R == 0 && Q == 0)
{
*x0 = - a / 3 ;
*x1 = - a / 3 ;
*x2 = - a / 3 ;
return 3 ;
}
- else if ( CR2 == CQ3 )
+ else if (CR2 == CQ3)
{
/* this test is actually R2 == Q3, written in a form suitable
- for exact computation with integers */
+ for exact computation with integers */
- /* Due to finite precision some float roots may be missed, and
- considered to be a pair of complex roots z = x +/- epsilon i
- close to the real axis. */
+ /* Due to finite precision some double roots may be missed, and
+ considered to be a pair of complex roots z = x +/- epsilon i
+ close to the real axis. */
- float sqrtQ = sqrt ( Q );
+ double sqrtQ = sqrt (Q);
- if ( R > 0 )
+ if (R > 0)
{
*x0 = -2 * sqrtQ - a / 3;
*x1 = sqrtQ - a / 3;
@@ -179,72 +205,88 @@ int gsl_poly_solve_cubic ( float a, float b, float c, float *x0, float *x1, floa
}
return 3 ;
}
- else if ( CR2 < CQ3 ) /* equivalent to R2 < Q3 */
+ else if (CR2 < CQ3) /* equivalent to R2 < Q3 */
{
- float sqrtQ = sqrt ( Q );
- float sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
- float theta = acos ( R / sqrtQ3 );
- float norm = -2 * sqrtQ;
- *x0 = norm * cos ( theta / 3 ) - a / 3;
- *x1 = norm * cos ( ( theta + 2.0 * M_PI ) / 3 ) - a / 3;
- *x2 = norm * cos ( ( theta - 2.0 * M_PI ) / 3 ) - a / 3;
+ double sqrtQ = sqrt (Q);
+ double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
+ double theta = acos (R / sqrtQ3);
+ double norm = -2 * sqrtQ;
+ *x0 = norm * cos (theta / 3) - a / 3;
+ *x1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3;
+ *x2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3;
/* Sort *x0, *x1, *x2 into increasing order */
- if ( *x0 > *x1 )
- mySWAP ( *x0, *x1 ) ;
+ if (*x0 > *x1)
+ mySWAP(*x0, *x1) ;
- if ( *x1 > *x2 )
+ if (*x1 > *x2)
{
- mySWAP ( *x1, *x2 ) ;
+ mySWAP(*x1, *x2) ;
- if ( *x0 > *x1 )
- mySWAP ( *x0, *x1 ) ;
+ if (*x0 > *x1)
+ mySWAP(*x0, *x1) ;
}
return 3;
}
else
{
- float sgnR = ( R >= 0 ? 1 : -1 );
- float A = -sgnR * pow ( ABS ( R ) + sqrt ( R2 - Q3 ), 1.0/3.0 );
- float B = Q / A ;
+ double sgnR = (R >= 0 ? 1 : -1);
+ double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0/3.0);
+ double B = Q / A ;
*x0 = A + B - a / 3;
return 1;
}
}
+
/**
- * gsl_poly_solve_quadratic
- *
- * copied from GSL
- */
-int gsl_poly_solve_quadratic ( float a, float b, float c, float *x0, float *x1 )
+* gsl_poly_solve_quadratic
+*
+* copied from GSL
+*/
+int
+gsl_poly_solve_quadratic (double a, double b, double c,
+ double *x0, double *x1)
{
- float disc = b * b - 4 * a * c;
+ double disc = b * b - 4 * a * c;
- if ( disc > 0 )
+ if (a == 0) /* Handle linear case */
{
- if ( b == 0 )
+ if (b == 0)
+ {
+ return 0;
+ }
+ else
{
- float r = ABS ( 0.5 * sqrt ( disc ) / a );
+ *x0 = -c / b;
+ return 1;
+ };
+ }
+
+ if (disc > 0)
+ {
+ if (b == 0)
+ {
+ double r = fabs (0.5 * sqrt (disc) / a);
*x0 = -r;
*x1 = r;
}
else
{
- float sgnb = ( b > 0 ? 1 : -1 );
- float temp = -0.5 * ( b + sgnb * sqrt ( disc ) );
- float r1 = temp / a ;
- float r2 = c / temp ;
+ double sgnb = (b > 0 ? 1 : -1);
+ double temp = -0.5 * (b + sgnb * sqrt (disc));
+ double r1 = temp / a ;
+ double r2 = c / temp ;
- if ( r1 < r2 )
+ if (r1 < r2)
{
*x0 = r1 ;
*x1 = r2 ;
- }
- else
+ }
+ else
{
*x0 = r2 ;
*x1 = r1 ;
@@ -252,7 +294,7 @@ int gsl_poly_solve_quadratic ( float a, float b, float c, float *x0, float *x1
}
return 2;
}
- else if ( disc == 0 )
+ else if (disc == 0)
{
*x0 = -0.5 * b / a ;
*x1 = -0.5 * b / a ;
@@ -266,79 +308,88 @@ int gsl_poly_solve_quadratic ( float a, float b, float c, float *x0, float *x1
-/*
- * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation"
- * page 4, left column
- */
-int cloth_get_collision_time ( float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3] )
+/*
+* See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation"
+* page 4, left column
+*/
+int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] )
{
int num_sols = 0;
- float g = -a[2] * c[1] * e[0] + a[1] * c[2] * e[0] +
- a[2] * c[0] * e[1] - a[0] * c[2] * e[1] -
- a[1] * c[0] * e[2] + a[0] * c[1] * e[2];
-
- float h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] +
- a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] +
- a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] +
- b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] -
- a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] -
- a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2];
-
- float i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] +
- b[2] * d[0] * e[1] - b[0] * d[2] * e[1] -
- b[1] * d[0] * e[2] + b[0] * d[1] * e[2] -
- b[2] * c[1] * f[0] + b[1] * c[2] * f[0] -
- a[2] * d[1] * f[0] + a[1] * d[2] * f[0] +
- b[2] * c[0] * f[1] - b[0] * c[2] * f[1] +
- a[2] * d[0] * f[1] - a[0] * d[2] * f[1] -
- b[1] * c[0] * f[2] + b[0] * c[1] * f[2] -
- a[1] * d[0] * f[2] + a[0] * d[1] * f[2];
-
- float j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] +
- b[2] * d[0] * f[1] - b[0] * d[2] * f[1] -
- b[1] * d[0] * f[2] + b[0] * d[1] * f[2];
-
+ // x^0 - checked
+ double g = a[0] * c[1] * e[2] - a[0] * c[2] * e[1] +
+ a[1] * c[2] * e[0] - a[1] * c[0] * e[2] +
+ a[2] * c[0] * e[1] - a[2] * c[1] * e[0];
+
+ // x^1
+ double h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] +
+ a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] +
+ a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] +
+ b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] -
+ a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] -
+ a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2];
+
+ // x^2
+ double i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] +
+ b[2] * d[0] * e[1] - b[0] * d[2] * e[1] -
+ b[1] * d[0] * e[2] + b[0] * d[1] * e[2] -
+ b[2] * c[1] * f[0] + b[1] * c[2] * f[0] -
+ a[2] * d[1] * f[0] + a[1] * d[2] * f[0] +
+ b[2] * c[0] * f[1] - b[0] * c[2] * f[1] +
+ a[2] * d[0] * f[1] - a[0] * d[2] * f[1] -
+ b[1] * c[0] * f[2] + b[0] * c[1] * f[2] -
+ a[1] * d[0] * f[2] + a[0] * d[1] * f[2];
+
+ // x^3 - checked
+ double j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] +
+ b[2] * d[0] * f[1] - b[0] * d[2] * f[1] -
+ b[1] * d[0] * f[2] + b[0] * d[1] * f[2];
+
+ /*
+ printf("r1: %lf\n", a[0] * c[1] * e[2] - a[0] * c[2] * e[1]);
+ printf("r2: %lf\n", a[1] * c[2] * e[0] - a[1] * c[0] * e[2]);
+ printf("r3: %lf\n", a[2] * c[0] * e[1] - a[2] * c[1] * e[0]);
+
+ printf("x1 x: %f, y: %f, z: %f\n", a[0], a[1], a[2]);
+ printf("x2 x: %f, y: %f, z: %f\n", c[0], c[1], c[2]);
+ printf("x3 x: %f, y: %f, z: %f\n", e[0], e[1], e[2]);
+
+ printf("v1 x: %f, y: %f, z: %f\n", b[0], b[1], b[2]);
+ printf("v2 x: %f, y: %f, z: %f\n", d[0], d[1], d[2]);
+ printf("v3 x: %f, y: %f, z: %f\n", f[0], f[1], f[2]);
+
+ printf("t^3: %lf, t^2: %lf, t^1: %lf, t^0: %lf\n", j, i, h, g);
+
+*/
// Solve cubic equation to determine times t1, t2, t3, when the collision will occur.
- if ( ABS ( j ) > ALMOST_ZERO )
+ if ( ABS ( j ) > DBL_EPSILON )
{
i /= j;
h /= j;
g /= j;
-
num_sols = gsl_poly_solve_cubic ( i, h, g, &solution[0], &solution[1], &solution[2] );
}
- else if ( ABS ( i ) > ALMOST_ZERO )
+ else
{
num_sols = gsl_poly_solve_quadratic ( i, h, g, &solution[0], &solution[1] );
solution[2] = -1.0;
}
- else if ( ABS ( h ) > ALMOST_ZERO )
- {
- solution[0] = -g / h;
- solution[1] = solution[2] = -1.0;
- num_sols = 1;
- }
- else if ( ABS ( g ) > ALMOST_ZERO )
- {
- solution[0] = 0;
- solution[1] = solution[2] = -1.0;
- num_sols = 1;
- }
+
+ // printf("num_sols: %d, sol1: %lf, sol2: %lf, sol3: %lf\n", num_sols, solution[0], solution[1], solution[2]);
// Discard negative solutions
- if ( ( num_sols >= 1 ) && ( solution[0] < 0 ) )
+ if ( ( num_sols >= 1 ) && ( solution[0] < DBL_EPSILON ) )
{
--num_sols;
solution[0] = solution[num_sols];
}
- if ( ( num_sols >= 2 ) && ( solution[1] < 0 ) )
+ if ( ( num_sols >= 2 ) && ( solution[1] < DBL_EPSILON ) )
{
--num_sols;
solution[1] = solution[num_sols];
}
- if ( ( num_sols == 3 ) && ( solution[2] < 0 ) )
+ if ( ( num_sols == 3 ) && ( solution[2] < DBL_EPSILON ) )
{
--num_sols;
}
@@ -374,6 +425,7 @@ int cloth_get_collision_time ( float a[3], float b[3], float c[3], float d[3], f
return num_sols;
}
+
// w3 is not perfect
void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 )
{
@@ -419,38 +471,37 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float
VECADDMUL ( to, v3, w3 );
}
-int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd )
+
+int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
{
int result = 0;
- LinkNode *search = NULL;
- CollPair *collpair = NULL;
Cloth *cloth1;
float w1, w2, w3, u1, u2, u3;
float v1[3], v2[3], relativeVelocity[3];
float magrelVel;
- float epsilon2 = collmd->bvh->epsilon;
+ float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
cloth1 = clmd->clothObject;
- search = clmd->coll_parms->collision_list;
-
- while ( search )
+ for ( ; collpair != collision_end; collpair++ )
{
- collpair = search->link;
+ // only handle static collisions here
+ if ( collpair->flag & COLLISION_IN_FUTURE )
+ continue;
// compute barycentric coordinates for both collision points
collision_compute_barycentric ( collpair->pa,
- cloth1->verts[collpair->ap1].txold,
- cloth1->verts[collpair->ap2].txold,
- cloth1->verts[collpair->ap3].txold,
- &w1, &w2, &w3 );
+ cloth1->verts[collpair->ap1].txold,
+ cloth1->verts[collpair->ap2].txold,
+ cloth1->verts[collpair->ap3].txold,
+ &w1, &w2, &w3 );
// was: txold
collision_compute_barycentric ( collpair->pb,
- collmd->current_x[collpair->bp1].co,
- collmd->current_x[collpair->bp2].co,
- collmd->current_x[collpair->bp3].co,
- &u1, &u2, &u3 );
+ collmd->current_x[collpair->bp1].co,
+ collmd->current_x[collpair->bp2].co,
+ collmd->current_x[collpair->bp3].co,
+ &u1, &u2, &u3 );
// Calculate relative "velocity".
collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
@@ -530,70 +581,50 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier
result = 1;
}
-
- search = search->next;
}
-
-
return result;
}
-int cloth_collision_response_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd )
-{
- return 1;
-}
-
-
-int cloth_collision_response_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd )
-{
- return 1;
-}
-
-void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 )
+//Determines collisions on overlap, collisions are writen to collpair[i] and collision+number_collision_found is returned
+CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair )
{
ClothModifierData *clmd = ( ClothModifierData * ) md1;
CollisionModifierData *collmd = ( CollisionModifierData * ) md2;
- CollPair *collpair = NULL;
- Cloth *cloth1=NULL;
- MFace *face1=NULL, *face2=NULL;
- ClothVertex *verts1=NULL;
+ MFace *face1=NULL, *face2 = NULL;
+ ClothVertex *verts1 = clmd->clothObject->verts;
double distance = 0;
- float epsilon = clmd->coll_parms->epsilon;
- float epsilon2 = ( ( CollisionModifierData * ) md2 )->bvh->epsilon;
- unsigned int i = 0;
+ float epsilon1 = clmd->coll_parms->epsilon;
+ float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
+ int i;
+
+ face1 = & ( clmd->clothObject->mfaces[overlap->indexA] );
+ face2 = & ( collmd->mfaces[overlap->indexB] );
+ // check all 4 possible collisions
for ( i = 0; i < 4; i++ )
{
- collpair = ( CollPair * ) MEM_callocN ( sizeof ( CollPair ), "cloth coll pair" );
-
- cloth1 = clmd->clothObject;
-
- verts1 = cloth1->verts;
-
- face1 = & ( cloth1->mfaces[tree1->tri_index] );
- face2 = & ( collmd->mfaces[tree2->tri_index] );
-
- // check all possible pairs of triangles
if ( i == 0 )
{
+ // fill faceA
collpair->ap1 = face1->v1;
collpair->ap2 = face1->v2;
collpair->ap3 = face1->v3;
+ // fill faceB
collpair->bp1 = face2->v1;
collpair->bp2 = face2->v2;
collpair->bp3 = face2->v3;
-
}
-
- if ( i == 1 )
+ else if ( i == 1 )
{
if ( face1->v4 )
{
- collpair->ap1 = face1->v3;
+ // fill faceA
+ collpair->ap1 = face1->v1;
collpair->ap2 = face1->v4;
- collpair->ap3 = face1->v1;
+ collpair->ap3 = face1->v3;
+ // fill faceB
collpair->bp1 = face2->v1;
collpair->bp2 = face2->v2;
collpair->bp3 = face2->v3;
@@ -601,386 +632,704 @@ void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTre
else
i++;
}
-
if ( i == 2 )
{
if ( face2->v4 )
{
+ // fill faceA
collpair->ap1 = face1->v1;
collpair->ap2 = face1->v2;
collpair->ap3 = face1->v3;
- collpair->bp1 = face2->v3;
+ // fill faceB
+ collpair->bp1 = face2->v1;
collpair->bp2 = face2->v4;
- collpair->bp3 = face2->v1;
+ collpair->bp3 = face2->v3;
}
else
- i+=2;
+ break;
}
-
- if ( i == 3 )
+ else if ( i == 3 )
{
- if ( ( face1->v4 ) && ( face2->v4 ) )
+ if ( face1->v4 && face2->v4 )
{
- collpair->ap1 = face1->v3;
+ // fill faceA
+ collpair->ap1 = face1->v1;
collpair->ap2 = face1->v4;
- collpair->ap3 = face1->v1;
+ collpair->ap3 = face1->v3;
- collpair->bp1 = face2->v3;
+ // fill faceB
+ collpair->bp1 = face2->v1;
collpair->bp2 = face2->v4;
- collpair->bp3 = face2->v1;
+ collpair->bp3 = face2->v3;
}
else
- i++;
+ break;
}
- // calc SIPcode (?)
-
- if ( i < 4 )
- {
- // calc distance + normal
#ifdef WITH_BULLET
- distance = plNearestPoints (
- verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector );
+ // calc distance + normal
+ distance = plNearestPoints (
+ verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector );
#else
- // just be sure that we don't add anything
- distance = 2.0 * ( epsilon + epsilon2 + ALMOST_ZERO );
+ // just be sure that we don't add anything
+ distance = 2.0 * ( epsilon1 + epsilon2 + ALMOST_ZERO );
#endif
- if ( distance <= ( epsilon + epsilon2 + ALMOST_ZERO ) )
+
+ if ( distance <= ( epsilon1 + epsilon2 + ALMOST_ZERO ) )
+ {
+ VECCOPY ( collpair->normal, collpair->vector );
+ Normalize ( collpair->normal );
+
+ collpair->distance = distance;
+ collpair->flag = 0;
+ collpair++;
+ }/*
+ else
+ {
+ float w1, w2, w3, u1, u2, u3;
+ float v1[3], v2[3], relativeVelocity[3];
+
+ // calc relative velocity
+
+ // compute barycentric coordinates for both collision points
+ collision_compute_barycentric ( collpair->pa,
+ verts1[collpair->ap1].txold,
+ verts1[collpair->ap2].txold,
+ verts1[collpair->ap3].txold,
+ &w1, &w2, &w3 );
+
+ // was: txold
+ collision_compute_barycentric ( collpair->pb,
+ collmd->current_x[collpair->bp1].co,
+ collmd->current_x[collpair->bp2].co,
+ collmd->current_x[collpair->bp3].co,
+ &u1, &u2, &u3 );
+
+ // Calculate relative "velocity".
+ collision_interpolateOnTriangle ( v1, verts1[collpair->ap1].tv, verts1[collpair->ap2].tv, verts1[collpair->ap3].tv, w1, w2, w3 );
+
+ collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 );
+
+ VECSUB ( relativeVelocity, v2, v1 );
+
+ if(sqrt(INPR(relativeVelocity, relativeVelocity)) >= distance)
{
- // printf("dist: %f\n", (float)distance);
+ // check for collision in the future
+ collpair->flag |= COLLISION_IN_FUTURE;
+ collpair++;
+ }
+ }*/
+ }
+ return collpair;
+}
- // collpair->face1 = tree1->tri_index;
- // collpair->face2 = tree2->tri_index;
+int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
+{
+ int result = 0;
+ Cloth *cloth1;
+ float w1, w2, w3, u1, u2, u3;
+ float v1[3], v2[3], relativeVelocity[3];
+ float magrelVel;
- VECCOPY ( collpair->normal, collpair->vector );
- Normalize ( collpair->normal );
+ cloth1 = clmd->clothObject;
- collpair->distance = distance;
- BLI_linklist_prepend ( &clmd->coll_parms->collision_list, collpair );
+ for ( ; collpair != collision_end; collpair++ )
+ {
+ // compute barycentric coordinates for both collision points
+ collision_compute_barycentric ( collpair->pa,
+ cloth1->verts[collpair->ap1].txold,
+ cloth1->verts[collpair->ap2].txold,
+ cloth1->verts[collpair->ap3].txold,
+ &w1, &w2, &w3 );
+
+ // was: txold
+ collision_compute_barycentric ( collpair->pb,
+ collmd->current_x[collpair->bp1].co,
+ collmd->current_x[collpair->bp2].co,
+ collmd->current_x[collpair->bp3].co,
+ &u1, &u2, &u3 );
+ // Calculate relative "velocity".
+ collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
+
+ collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 );
+
+ VECSUB ( relativeVelocity, v2, v1 );
+
+ // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal').
+ magrelVel = INPR ( relativeVelocity, collpair->normal );
+
+ // printf("magrelVel: %f\n", magrelVel);
+
+ // Calculate masses of points.
+ // TODO
+
+ // If v_n_mag < 0 the edges are approaching each other.
+ if ( magrelVel > ALMOST_ZERO )
+ {
+ // Calculate Impulse magnitude to stop all motion in normal direction.
+ float magtangent = 0;
+ double impulse = 0.0;
+ float vrel_t_pre[3];
+ float temp[3];
+
+ // calculate tangential velocity
+ VECCOPY ( temp, collpair->normal );
+ VecMulf ( temp, magrelVel );
+ VECSUB ( vrel_t_pre, relativeVelocity, temp );
+
+ // Decrease in magnitude of relative tangential velocity due to coulomb friction
+ // in original formula "magrelVel" should be the "change of relative velocity in normal direction"
+ magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) );
+
+ // Apply friction impulse.
+ if ( magtangent > ALMOST_ZERO )
+ {
+ Normalize ( vrel_t_pre );
+
+ impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );
+ VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse );
+ VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse );
+ VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse );
}
- else
+
+ // Apply velocity stopping impulse
+ // I_c = m * v_N / 2.0
+ // no 2.0 * magrelVel normally, but looks nicer DG
+ impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );
+
+ VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse );
+ cloth1->verts[collpair->ap1].impulse_count++;
+
+ VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse );
+ cloth1->verts[collpair->ap2].impulse_count++;
+
+ VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse );
+ cloth1->verts[collpair->ap3].impulse_count++;
+
+ // Apply repulse impulse if distance too short
+ // I_r = -min(dt*kd, m(0,1d/dt - v_n))
+ /*
+ d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance;
+ if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) )
{
- MEM_freeN ( collpair );
+ repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel );
+
+ // stay on the safe side and clamp repulse
+ if ( impulse > ALMOST_ZERO )
+ repulse = MIN2 ( repulse, 5.0*impulse );
+ repulse = MAX2 ( impulse, repulse );
+
+ impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25
+ VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse );
+ VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse );
+ VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse );
}
- }
- else
- {
- MEM_freeN ( collpair );
+ */
+ result = 1;
}
}
+ return result;
}
-int cloth_are_edges_adjacent ( ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair )
+static float projectPointOntoLine(float *p, float *a, float *b)
{
- Cloth *cloth1 = NULL, *cloth2 = NULL;
- ClothVertex *verts1 = NULL, *verts2 = NULL;
- float temp[3];
-
- cloth1 = clmd->clothObject;
- cloth2 = coll_clmd->clothObject;
+ float ba[3], pa[3];
+ VECSUB(ba, b, a);
+ VECSUB(pa, p, a);
+ return INPR(pa, ba) / INPR(ba, ba);
+}
- verts1 = cloth1->verts;
- verts2 = cloth2->verts;
+static void calculateEENormal(float *np1, float *np2, float *np3, float *np4,float *out_normal)
+{
+ float line1[3], line2[3];
+ float length;
- VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold );
- if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
- return 1;
+ VECSUB(line1, np2, np1);
+ VECSUB(line2, np3, np1);
- VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold );
- if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
- return 1;
+ // printf("l1: %f, l1: %f, l2: %f, l2: %f\n", line1[0], line1[1], line2[0], line2[1]);
- VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold );
- if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
- return 1;
+ Crossf(out_normal, line1, line2);
- VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold );
- if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
- return 1;
+
- return 0;
+ length = Normalize(out_normal);
+ if (length <= FLT_EPSILON)
+ { // lines are collinear
+ VECSUB(out_normal, np2, np1);
+ Normalize(out_normal);
+ }
}
-void cloth_collision_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 )
+static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, float *w1, float *w2)
{
- EdgeCollPair edgecollpair;
- Cloth *cloth1=NULL, *cloth2=NULL;
- MFace *face1=NULL, *face2=NULL;
- ClothVertex *verts1=NULL, *verts2=NULL;
- unsigned int i = 0, j = 0, k = 0;
- int numsolutions = 0;
- float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
+ float temp[3], temp2[3];
+
+ double a, b, c, e, f;
- cloth1 = clmd->clothObject;
- cloth2 = coll_clmd->clothObject;
+ VECSUB(temp, x2, x1);
+ a = INPR(temp, temp);
- verts1 = cloth1->verts;
- verts2 = cloth2->verts;
+ VECSUB(temp2, x4, x3);
+ b = -INPR(temp, temp2);
+
+ c = INPR(temp2, temp2);
- face1 = & ( cloth1->mfaces[tree1->tri_index] );
- face2 = & ( cloth2->mfaces[tree2->tri_index] );
+ VECSUB(temp2, x3, x1);
+ e = INPR(temp, temp2);
- for ( i = 0; i < 5; i++ )
+ VECSUB(temp, x4, x3);
+ f = -INPR(temp, temp2);
+
+ *w1 = (e * c - b * f) / (a * c - b * b);
+ *w2 = (f - b * *w1) / c;
+
+}
+
+// calculates the distance of 2 edges
+float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal)
+{
+ float line1[3], line2[3], cross[3];
+ float length;
+ float temp[3], temp2[3];
+ float dist_a1, dist_a2;
+
+ VECSUB(line1, np12, np11);
+ VECSUB(line2, np22, np21);
+
+ Crossf(cross, line1, line2);
+ length = INPR(cross, cross);
+
+ if (length < FLT_EPSILON)
{
- if ( i == 0 )
- {
- edgecollpair.p11 = face1->v1;
- edgecollpair.p12 = face1->v2;
- }
- else if ( i == 1 )
+ *out_a2 = projectPointOntoLine(np11, np21, np22);
+ if ((*out_a2 >= -FLT_EPSILON) && (*out_a2 <= 1.0 + FLT_EPSILON))
{
- edgecollpair.p11 = face1->v2;
- edgecollpair.p12 = face1->v3;
+ *out_a1 = 0;
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+ VECSUB(temp, np22, np21);
+ VecMulf(temp, *out_a2);
+ VECADD(temp2, temp, np21);
+ VECADD(temp2, temp2, np11);
+ return INPR(temp2, temp2);
}
- else if ( i == 2 )
- {
- if ( face1->v4 )
+
+ CLAMP(*out_a2, 0.0, 1.0);
+ if (*out_a2 > .5)
+ { // == 1.0
+ *out_a1 = projectPointOntoLine(np22, np11, np12);
+ if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON))
{
- edgecollpair.p11 = face1->v3;
- edgecollpair.p12 = face1->v4;
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+
+ // return (np22 - (np11 + (np12 - np11) * out_a1)).lengthSquared();
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(temp2, temp, np11);
+ VECSUB(temp2, np22, temp2);
+ return INPR(temp2, temp2);
}
- else
+ }
+ else
+ { // == 0.0
+ *out_a1 = projectPointOntoLine(np21, np11, np12);
+ if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON))
{
- edgecollpair.p11 = face1->v3;
- edgecollpair.p12 = face1->v1;
- i+=5; // get out of here after this edge pair is handled
+ calculateEENormal(np11, np11, np21, np22, out_normal);
+
+ // return (np21 - (np11 + (np12 - np11) * out_a1)).lengthSquared();
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(temp2, temp, np11);
+ VECSUB(temp2, np21, temp2);
+ return INPR(temp2, temp2);
}
}
- else if ( i == 3 )
+
+ CLAMP(*out_a1, 0.0, 1.0);
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+ if(*out_a1 > .5)
{
- if ( face1->v4 )
+ if(*out_a2 > .5)
{
- edgecollpair.p11 = face1->v4;
- edgecollpair.p12 = face1->v1;
+ VECSUB(temp, np12, np22);
}
else
- continue;
+ {
+ VECSUB(temp, np12, np21);
+ }
}
else
{
- edgecollpair.p11 = face1->v3;
- edgecollpair.p12 = face1->v1;
- }
-
-
- for ( j = 0; j < 5; j++ )
- {
- if ( j == 0 )
+ if(*out_a2 > .5)
{
- edgecollpair.p21 = face2->v1;
- edgecollpair.p22 = face2->v2;
- }
- else if ( j == 1 )
- {
- edgecollpair.p21 = face2->v2;
- edgecollpair.p22 = face2->v3;
- }
- else if ( j == 2 )
- {
- if ( face2->v4 )
- {
- edgecollpair.p21 = face2->v3;
- edgecollpair.p22 = face2->v4;
- }
- else
- {
- edgecollpair.p21 = face2->v3;
- edgecollpair.p22 = face2->v1;
- }
- }
- else if ( j == 3 )
- {
- if ( face2->v4 )
- {
- edgecollpair.p21 = face2->v4;
- edgecollpair.p22 = face2->v1;
- }
- else
- continue;
+ VECSUB(temp, np11, np22);
}
else
{
- edgecollpair.p21 = face2->v3;
- edgecollpair.p22 = face2->v1;
+ VECSUB(temp, np11, np21);
}
+ }
+ return INPR(temp, temp);
+ }
+ else
+ {
+
+ // If the lines aren't parallel (but coplanar) they have to intersect
- if ( !cloth_are_edges_adjacent ( clmd, coll_clmd, &edgecollpair ) )
- {
- VECSUB ( a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold );
- VECSUB ( b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v );
- VECSUB ( c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold );
- VECSUB ( d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v );
- VECSUB ( e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold );
- VECSUB ( f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v );
-
- numsolutions = cloth_get_collision_time ( a, b, c, d, e, f, solution );
-
- for ( k = 0; k < numsolutions; k++ )
- {
- if ( ( solution[k] >= 0.0 ) && ( solution[k] <= 1.0 ) )
- {
- //float out_collisionTime = solution[k];
-
- // TODO: check for collisions
+ findClosestPointsEE(np11, np12, np21, np22, out_a1, out_a2);
- // TODO: put into (edge) collision list
+ // If both points are on the finite edges, we're done.
+ if (*out_a1 >= 0.0 && *out_a1 <= 1.0 && *out_a2 >= 0.0 && *out_a2 <= 1.0)
+ {
+ float p1[3], p2[3];
+
+ // p1= np11 + (np12 - np11) * out_a1;
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(p1, np11, temp);
+
+ // p2 = np21 + (np22 - np21) * out_a2;
+ VECSUB(temp, np22, np21);
+ VecMulf(temp, *out_a2);
+ VECADD(p2, np21, temp);
+
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+ VECSUB(temp, p1, p2);
+ return INPR(temp, temp);
+ }
- // printf("Moving edge found!\n");
- }
- }
- }
+
+ /*
+ * Clamp both points to the finite edges.
+ * The one that moves most during clamping is one part of the solution.
+ */
+ dist_a1 = *out_a1;
+ CLAMP(dist_a1, 0.0, 1.0);
+ dist_a2 = *out_a2;
+ CLAMP(dist_a2, 0.0, 1.0);
+
+ // Now project the "most clamped" point on the other line.
+ if (dist_a1 > dist_a2)
+ {
+ /* keep out_a1 */
+ float p1[3];
+
+ // p1 = np11 + (np12 - np11) * out_a1;
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(p1, np11, temp);
+
+ *out_a2 = projectPointOntoLine(p1, np21, np22);
+ CLAMP(*out_a2, 0.0, 1.0);
+
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+
+ // return (p1 - (np21 + (np22 - np21) * out_a2)).lengthSquared();
+ VECSUB(temp, np22, np21);
+ VecMulf(temp, *out_a2);
+ VECADD(temp, temp, np21);
+ VECSUB(temp, p1, temp);
+ return INPR(temp, temp);
+ }
+ else
+ {
+ /* keep out_a2 */
+ float p2[3];
+
+ // p2 = np21 + (np22 - np21) * out_a2;
+ VECSUB(temp, np22, np21);
+ VecMulf(temp, *out_a2);
+ VECADD(p2, np21, temp);
+
+ *out_a1 = projectPointOntoLine(p2, np11, np12);
+ CLAMP(*out_a1, 0.0, 1.0);
+
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+
+ // return ((np11 + (np12 - np11) * out_a1) - p2).lengthSquared();
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(temp, temp, np11);
+ VECSUB(temp, temp, p2);
+ return INPR(temp, temp);
}
}
+
+ printf("Error in edgedge_distance: end of function\n");
+ return 0;
}
-void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 )
+int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair )
{
- CollPair collpair;
- Cloth *cloth1=NULL, *cloth2=NULL;
- MFace *face1=NULL, *face2=NULL;
- ClothVertex *verts1=NULL, *verts2=NULL;
- unsigned int i = 0, j = 0, k = 0;
+ EdgeCollPair edgecollpair;
+ Cloth *cloth1=NULL;
+ ClothVertex *verts1=NULL;
+ unsigned int i = 0, k = 0;
int numsolutions = 0;
- float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
+ double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3];
+ double solution[3], solution2[3];
+ MVert *verts2 = collmd->current_x; // old x
+ MVert *velocity2 = collmd->current_v; // velocity
+ float distance = 0;
+ float triA[3][3], triB[3][3];
+ int result = 0;
- for ( i = 0; i < 2; i++ )
+ cloth1 = clmd->clothObject;
+ verts1 = cloth1->verts;
+
+ for(i = 0; i < 9; i++)
{
- cloth1 = clmd->clothObject;
- cloth2 = coll_clmd->clothObject;
+ // 9 edge - edge possibilities
- verts1 = cloth1->verts;
- verts2 = cloth2->verts;
+ if(i == 0) // cloth edge: 1-2; coll edge: 1-2
+ {
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap2;
- face1 = & ( cloth1->mfaces[tree1->tri_index] );
- face2 = & ( cloth2->mfaces[tree2->tri_index] );
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp2;
+ }
+ else if(i == 1) // cloth edge: 1-2; coll edge: 2-3
+ {
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap2;
- // check all possible pairs of triangles
- if ( i == 0 )
+ edgecollpair.p21 = collpair->bp2;
+ edgecollpair.p22 = collpair->bp3;
+ }
+ else if(i == 2) // cloth edge: 1-2; coll edge: 1-3
{
- collpair.ap1 = face1->v1;
- collpair.ap2 = face1->v2;
- collpair.ap3 = face1->v3;
-
- collpair.pointsb[0] = face2->v1;
- collpair.pointsb[1] = face2->v2;
- collpair.pointsb[2] = face2->v3;
- collpair.pointsb[3] = face2->v4;
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap2;
+
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp3;
}
+ else if(i == 3) // cloth edge: 2-3; coll edge: 1-2
+ {
+ edgecollpair.p11 = collpair->ap2;
+ edgecollpair.p12 = collpair->ap3;
- if ( i == 1 )
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp2;
+ }
+ else if(i == 4) // cloth edge: 2-3; coll edge: 2-3
{
- if ( face1->v4 )
- {
- collpair.ap1 = face1->v3;
- collpair.ap2 = face1->v4;
- collpair.ap3 = face1->v1;
-
- collpair.pointsb[0] = face2->v1;
- collpair.pointsb[1] = face2->v2;
- collpair.pointsb[2] = face2->v3;
- collpair.pointsb[3] = face2->v4;
- }
- else
- i++;
+ edgecollpair.p11 = collpair->ap2;
+ edgecollpair.p12 = collpair->ap3;
+
+ edgecollpair.p21 = collpair->bp2;
+ edgecollpair.p22 = collpair->bp3;
}
+ else if(i == 5) // cloth edge: 2-3; coll edge: 1-3
+ {
+ edgecollpair.p11 = collpair->ap2;
+ edgecollpair.p12 = collpair->ap3;
- // calc SIPcode (?)
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp3;
+ }
+ else if(i ==6) // cloth edge: 1-3; coll edge: 1-2
+ {
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap3;
- if ( i < 2 )
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp2;
+ }
+ else if(i ==7) // cloth edge: 1-3; coll edge: 2-3
{
- VECSUB ( a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold );
- VECSUB ( b, verts1[collpair.ap2].v, verts1[collpair.ap1].v );
- VECSUB ( c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold );
- VECSUB ( d, verts1[collpair.ap3].v, verts1[collpair.ap1].v );
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap3;
- for ( j = 0; j < 4; j++ )
- {
- if ( ( j==3 ) && ! ( face2->v4 ) )
- break;
+ edgecollpair.p21 = collpair->bp2;
+ edgecollpair.p22 = collpair->bp3;
+ }
+ else if(i == 8) // cloth edge: 1-3; coll edge: 1-3
+ {
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap3;
+
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp3;
+ }
+ /*
+ if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 16))
+ printf("Ahier!\n");
+ if((edgecollpair.p11 == 16) && (edgecollpair.p12 == 3))
+ printf("Ahier!\n");
+ */
+
+ // if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) )
+ {
+ // always put coll points in p21/p22
+ VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold );
+ VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv );
- VECSUB ( e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold );
- VECSUB ( f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v );
+ VECSUB ( x2, verts2[edgecollpair.p21].co, verts1[edgecollpair.p11].txold );
+ VECSUB ( v2, velocity2[edgecollpair.p21].co, verts1[edgecollpair.p11].tv );
- numsolutions = cloth_get_collision_time ( a, b, c, d, e, f, solution );
+ VECSUB ( x3, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold );
+ VECSUB ( v3, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].tv );
- for ( k = 0; k < numsolutions; k++ )
+ numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution );
+
+ if((edgecollpair.p11 == 3 && edgecollpair.p12==16)|| (edgecollpair.p11==16 && edgecollpair.p12==3))
+ {
+ if(edgecollpair.p21==6 || edgecollpair.p22 == 6)
{
- if ( ( solution[k] >= 0.0 ) && ( solution[k] <= 1.0 ) )
+ printf("dist: %f, sol[k]: %lf, sol2[k]: %lf\n", distance, solution[k], solution2[k]);
+ printf("a1: %f, a2: %f, b1: %f, b2: %f\n", x1[0], x2[0], x3[0], v1[0]);
+ printf("b21: %d, b22: %d\n", edgecollpair.p21, edgecollpair.p22);
+ }
+ }
+
+ for ( k = 0; k < numsolutions; k++ )
+ {
+ // printf("sol %d: %lf\n", k, solution[k]);
+ if ( ( solution[k] >= ALMOST_ZERO ) && ( solution[k] <= 1.0 ) && ( solution[k] > ALMOST_ZERO))
+ {
+ float a,b;
+ float out_normal[3];
+ float distance;
+ float impulse = 0;
+ float I_mag;
+
+ // move verts
+ VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, solution[k]);
+ VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, solution[k]);
+
+ VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, solution[k]);
+ VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, solution[k]);
+
+ // TODO: check for collisions
+ distance = edgedge_distance(triA[0], triA[1], triB[0], triB[1], &a, &b, out_normal);
+
+ if ((distance <= clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO) && (INPR(out_normal, out_normal) > 0))
{
- //float out_collisionTime = solution[k];
+ float vrel_1_to_2[3], temp[3], temp2[3], out_normalVelocity;
+ float desiredVn;
+
+ VECCOPY(vrel_1_to_2, verts1[edgecollpair.p11].tv);
+ VecMulf(vrel_1_to_2, 1.0 - a);
+ VECCOPY(temp, verts1[edgecollpair.p12].tv);
+ VecMulf(temp, a);
- // TODO: check for collisions
+ VECADD(vrel_1_to_2, vrel_1_to_2, temp);
- // TODO: put into (point-face) collision list
+ VECCOPY(temp, verts1[edgecollpair.p21].tv);
+ VecMulf(temp, 1.0 - b);
+ VECCOPY(temp2, verts1[edgecollpair.p22].tv);
+ VecMulf(temp2, b);
+ VECADD(temp, temp, temp2);
- // printf("Moving found!\n");
+ VECSUB(vrel_1_to_2, vrel_1_to_2, temp);
+ out_normalVelocity = INPR(vrel_1_to_2, out_normal);
+/*
+ // this correction results in wrong normals sometimes?
+ if(out_normalVelocity < 0.0)
+ {
+ out_normalVelocity*= -1.0;
+ VecMulf(out_normal, -1.0);
+ }
+*/
+ /* Inelastic repulsion impulse. */
+
+ // Calculate which normal velocity we need.
+ desiredVn = (out_normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(distance)) - ALMOST_ZERO);
+
+ // Now calculate what impulse we need to reach that velocity.
+ I_mag = (out_normalVelocity - desiredVn) / 2.0; // / (1/m1 + 1/m2);
+
+ // Finally apply that impulse.
+ impulse = (2.0 * -I_mag) / (a*a + (1.0-a)*(1.0-a) + b*b + (1.0-b)*(1.0-b));
+
+ VECADDMUL ( verts1[edgecollpair.p11].impulse, out_normal, (1.0-a) * impulse );
+ verts1[edgecollpair.p11].impulse_count++;
+
+ VECADDMUL ( verts1[edgecollpair.p12].impulse, out_normal, a * impulse );
+ verts1[edgecollpair.p12].impulse_count++;
+
+ // return true;
+ result = 1;
+ break;
}
- }
+ else
+ {
+ // missing from collision.hpp
+ }
+ // mintime = MIN2(mintime, (float)solution[k]);
- // TODO: check borders for collisions
+ break;
+ }
}
-
}
}
+ return result;
}
-void cloth_collision_moving ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 )
+int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
{
- // TODO: check for adjacent
- cloth_collision_moving_edges ( clmd, coll_clmd, tree1, tree2 );
-
- cloth_collision_moving_tris ( clmd, coll_clmd, tree1, tree2 );
- cloth_collision_moving_tris ( coll_clmd, clmd, tree2, tree1 );
-}
+ Cloth *cloth1;
+ cloth1 = clmd->clothObject;
-void cloth_free_collision_list ( ClothModifierData *clmd )
-{
- // free collision list
- if ( clmd->coll_parms->collision_list )
+ for ( ; collpair != collision_end; collpair++ )
{
- LinkNode *search = clmd->coll_parms->collision_list;
- while ( search )
- {
- CollPair *coll_pair = search->link;
-
- MEM_freeN ( coll_pair );
- search = search->next;
- }
- BLI_linklist_free ( clmd->coll_parms->collision_list,NULL );
+ // only handle moving collisions here
+ if (!( collpair->flag & COLLISION_IN_FUTURE ))
+ continue;
- clmd->coll_parms->collision_list = NULL;
+ cloth_collision_moving_edges ( clmd, collmd, collpair);
+ // cloth_collision_moving_tris ( clmd, collmd, collpair);
}
+
+ return 1;
}
int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt )
{
Cloth *cloth = clmd->clothObject;
- BVH *cloth_bvh= ( BVH * ) cloth->tree;
+ BVHTree *cloth_bvh= ( BVHTree * ) cloth->bvhtree;
long i=0, j = 0, numfaces = 0, numverts = 0;
ClothVertex *verts = NULL;
+ CollPair *collisions = NULL, *collisions_index = NULL;
int ret = 0;
- unsigned int result = 0;
+ int result = 0;
float tnull[3] = {0,0,0};
+ BVHTreeOverlap *overlap = NULL;
+
numfaces = clmd->clothObject->numfaces;
numverts = clmd->clothObject->numverts;
verts = cloth->verts;
- if ( collmd->bvh )
+ if ( collmd->bvhtree )
{
/* get pointer to bounding volume hierarchy */
- BVH *coll_bvh = collmd->bvh;
+ BVHTree *coll_bvh = collmd->bvhtree;
/* move object to position (step) in time */
collision_move_object ( collmd, step + dt, step );
/* search for overlapping collision pairs */
- bvh_traverse ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0 );
+ overlap = BLI_bvhtree_overlap ( cloth_bvh, coll_bvh, &result );
+
+ collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * result*4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision
+ collisions_index = collisions;
+
+ for ( i = 0; i < result; i++ )
+ {
+ collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, collisions_index );
+ }
+
+ if ( overlap )
+ MEM_freeN ( overlap );
}
else
{
@@ -994,29 +1343,50 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData
{
result = 0;
- if ( collmd->bvh )
- result += cloth_collision_response_static ( clmd, collmd );
+ if ( collmd->bvhtree )
+ {
+ result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index );
- // apply impulses in parallel
- if ( result )
- for ( i = 0; i < numverts; i++ )
+ // apply impulses in parallel
+ if ( result )
{
- // calculate "velocities" (just xnew = xold + v; no dt in v)
- if ( verts[i].impulse_count )
+ for ( i = 0; i < numverts; i++ )
{
- VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
- VECCOPY ( verts[i].impulse, tnull );
- verts[i].impulse_count = 0;
+ // calculate "velocities" (just xnew = xold + v; no dt in v)
+ if ( verts[i].impulse_count )
+ {
+ VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
+ VECCOPY ( verts[i].impulse, tnull );
+ verts[i].impulse_count = 0;
- ret++;
+ ret++;
+ }
}
}
+/*
+ result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index );
+
+ // apply impulses in parallel
+ if ( result )
+ {
+ for ( i = 0; i < numverts; i++ )
+ {
+ // calculate "velocities" (just xnew = xold + v; no dt in v)
+ if ( verts[i].impulse_count )
+ {
+ VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
+ VECCOPY ( verts[i].impulse, tnull );
+ verts[i].impulse_count = 0;
- if ( !result )
- break;
+ ret++;
+ }
+ }
+ }
+*/
+ }
}
- cloth_free_collision_list ( clmd );
+ if ( collisions ) MEM_freeN ( collisions );
return ret;
}
@@ -1028,22 +1398,22 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
CollisionModifierData *collmd=NULL;
Cloth *cloth=NULL;
Object *coll_ob=NULL;
- BVH *cloth_bvh=NULL;
- long i=0, j = 0, numfaces = 0, numverts = 0;
- unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output;
+ BVHTree *cloth_bvh=NULL;
+ long i=0, j = 0, k = 0, l = 0, numfaces = 0, numverts = 0;
+ int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output;
ClothVertex *verts = NULL;
- int ret = 0;
+ int ret = 0, ret2 = 0;
ClothModifierData *tclmd;
- int collisions = 0, count = 0;
+ int collisions = 0;
- if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->tree ) )
+ if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) )
{
return 0;
}
cloth = clmd->clothObject;
verts = cloth->verts;
- cloth_bvh = ( BVH * ) cloth->tree;
+ cloth_bvh = ( BVHTree * ) cloth->bvhtree;
numfaces = clmd->clothObject->numfaces;
numverts = clmd->clothObject->numverts;
@@ -1052,12 +1422,13 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
////////////////////////////////////////////////////////////
// update cloth bvh
- bvh_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function)
+ bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function)
+ bvhselftree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function)
do
{
result = 0;
- clmd->coll_parms->collision_list = NULL;
+ ret2 = 0;
// check all collision objects
for ( base = G.scene->base.first; base; base = base->next )
@@ -1086,6 +1457,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
continue;
ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt );
+ ret2 += ret;
}
}
}
@@ -1096,6 +1468,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
continue;
ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt );
+ ret2 += ret;
}
}
rounds++;
@@ -1126,78 +1499,90 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
////////////////////////////////////////////////////////////
if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF )
{
- collisions = 1;
- verts = cloth->verts; // needed for openMP
-
- for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ )
+ for(l = 0; l < clmd->coll_parms->self_loop_count; l++)
{
- if ( collisions )
+ // TODO: add coll quality rounds again
+ BVHTreeOverlap *overlap = NULL;
+
+ collisions = 1;
+ verts = cloth->verts; // needed for openMP
+
+ numfaces = clmd->clothObject->numfaces;
+ numverts = clmd->clothObject->numverts;
+
+ verts = cloth->verts;
+
+ if ( cloth->bvhselftree )
{
- collisions = 0;
-#pragma omp parallel for private(i,j, collisions) shared(verts, ret)
- for ( i = 0; i < cloth->numverts; i++ )
+ // search for overlapping collision pairs
+ overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result );
+
+ // #pragma omp parallel for private(k, i, j) schedule(static)
+ for ( k = 0; k < result; k++ )
{
- for ( j = i + 1; j < cloth->numverts; j++ )
+ float temp[3];
+ float length = 0;
+ float mindistance;
+
+ i = overlap[k].indexA;
+ j = overlap[k].indexB;
+
+ mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
+
+ if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
{
- float temp[3];
- float length = 0;
- float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
-
- if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+ if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+ && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
{
- if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
- && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
- {
- continue;
- }
+ continue;
}
-
- VECSUB ( temp, verts[i].tx, verts[j].tx );
-
- if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
-
- // check for adjacent points (i must be smaller j)
- if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) )
+ }
+
+ VECSUB ( temp, verts[i].tx, verts[j].tx );
+
+ if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
+
+ // check for adjacent points (i must be smaller j)
+ if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) )
+ {
+ continue;
+ }
+
+ length = Normalize ( temp );
+
+ if ( length < mindistance )
+ {
+ float correction = mindistance - length;
+
+ if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
{
- continue;
+ VecMulf ( temp, -correction );
+ VECADD ( verts[j].tx, verts[j].tx, temp );
}
-
- length = Normalize ( temp );
-
- if ( length < mindistance )
+ else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
{
- float correction = mindistance - length;
-
- if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
- {
- VecMulf ( temp, -correction );
- VECADD ( verts[j].tx, verts[j].tx, temp );
- }
- else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
- {
- VecMulf ( temp, correction );
- VECADD ( verts[i].tx, verts[i].tx, temp );
- }
- else
- {
- VecMulf ( temp, -correction*0.5 );
- VECADD ( verts[j].tx, verts[j].tx, temp );
-
- VECSUB ( verts[i].tx, verts[i].tx, temp );
- }
-
- collisions = 1;
-
- if ( !ret )
- {
-#pragma omp critical
- {
- ret = 1;
- }
- }
+ VecMulf ( temp, correction );
+ VECADD ( verts[i].tx, verts[i].tx, temp );
}
+ else
+ {
+ VecMulf ( temp, -correction*0.5 );
+ VECADD ( verts[j].tx, verts[j].tx, temp );
+
+ VECSUB ( verts[i].tx, verts[i].tx, temp );
+ }
+ ret = 1;
+ ret2 += ret;
+ }
+ else
+ {
+ // check for approximated time collisions
}
}
+
+ if ( overlap )
+ MEM_freeN ( overlap );
+
}
}
////////////////////////////////////////////////////////////
@@ -1205,18 +1590,20 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
////////////////////////////////////////////////////////////
// SELFCOLLISIONS: update velocities
////////////////////////////////////////////////////////////
- if ( ret )
+ if ( ret2 )
{
for ( i = 0; i < cloth->numverts; i++ )
{
- if ( ! ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
+ if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
+ {
VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold );
+ }
}
}
////////////////////////////////////////////////////////////
}
}
- while ( result && ( clmd->coll_parms->loop_count>rounds ) );
+ while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
return MIN2 ( ret, 1 );
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index f60e39769a2..068501780bc 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1882,7 +1882,7 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT
{
bPythonConstraint *data= con->data;
- if (VALID_CONS_TARGET(ct)) {
+ if ((G.f & G_DOSCRIPTLINKS) && VALID_CONS_TARGET(ct)) {
/* special exception for curves - depsgraph issues */
if (ct->tar->type == OB_CURVE) {
Curve *cu= ct->tar->data;
@@ -1906,6 +1906,8 @@ static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targ
{
bPythonConstraint *data= con->data;
+ if ((G.f & G_DOSCRIPTLINKS)==0) return;
+
/* currently removed, until I this can be re-implemented for multiple targets */
#if 0
/* Firstly, run the 'driver' function which has direct access to the objects involved
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index d02a7c0ab9e..396bdda9c10 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -348,9 +348,9 @@ void freeNurb(Nurb *nu)
if(nu->bp) MEM_freeN(nu->bp);
nu->bp= 0;
if(nu->knotsu) MEM_freeN(nu->knotsu);
- nu->knotsu= 0;
+ nu->knotsu= NULL;
if(nu->knotsv) MEM_freeN(nu->knotsv);
- nu->knotsv= 0;
+ nu->knotsv= NULL;
/* if(nu->trim.first) freeNurblist(&(nu->trim)); */
MEM_freeN(nu);
@@ -393,7 +393,7 @@ Nurb *duplicateNurb(Nurb *nu)
(BPoint*)MEM_mallocN((len)* sizeof(BPoint),"duplicateNurb3");
memcpy(newnu->bp, nu->bp, len*sizeof(BPoint));
- newnu->knotsu=newnu->knotsv= 0;
+ newnu->knotsu= newnu->knotsv= NULL;
if(nu->knotsu) {
len= KNOTSU(nu);
@@ -506,6 +506,7 @@ static void calcknots(float *knots, short aantal, short order, short type)
}
}
else if(type==2) {
+ /* Warning, the order MUST be 2 or 4, if this is not enforced, the displist will be corrupt */
if(order==4) {
k= 0.34;
for(a=0;a<t;a++) {
@@ -520,6 +521,9 @@ static void calcknots(float *knots, short aantal, short order, short type)
knots[a]= (float)floor(k);
}
}
+ else {
+ printf("bez nurb curve order is not 3 or 4, should never happen\n");
+ }
}
}
@@ -529,7 +533,8 @@ static void makecyclicknots(float *knots, short pnts, short order)
int a, b, order2, c;
if(knots==0) return;
- order2=order-1;
+
+ order2=order-1;
/* do first long rows (order -1), remove identical knots at endpoints */
if(order>2) {
@@ -549,26 +554,35 @@ static void makecyclicknots(float *knots, short pnts, short order)
}
-void makeknots(Nurb *nu, short uv, short type) /* 0: uniform, 1: endpoints, 2: bezier */
+/* type - 0: uniform, 1: endpoints, 2: bezier, note, cyclic nurbs are always uniform */
+void makeknots(Nurb *nu, short uv, short type)
{
if( (nu->type & 7)==CU_NURBS ) {
- if(uv & 1) {
+ if(uv == 1) {
if(nu->knotsu) MEM_freeN(nu->knotsu);
- if(nu->pntsu>1) {
+ if(check_valid_nurb_u(nu)) {
nu->knotsu= MEM_callocN(4+sizeof(float)*KNOTSU(nu), "makeknots");
- calcknots(nu->knotsu, nu->pntsu, nu->orderu, type);
- if(nu->flagu & 1) makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
+ if(nu->flagu & CU_CYCLIC) {
+ calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0); /* cyclic should be uniform */
+ makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
+ } else {
+ calcknots(nu->knotsu, nu->pntsu, nu->orderu, type);
+ }
}
- else nu->knotsu= 0;
- }
- if(uv & 2) {
+ else nu->knotsu= NULL;
+
+ } else if(uv == 2) {
if(nu->knotsv) MEM_freeN(nu->knotsv);
- if(nu->pntsv>1) {
+ if(check_valid_nurb_v(nu)) {
nu->knotsv= MEM_callocN(4+sizeof(float)*KNOTSV(nu), "makeknots");
- calcknots(nu->knotsv, nu->pntsv, nu->orderv, type);
- if(nu->flagv & 1) makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
+ if(nu->flagv & CU_CYCLIC) {
+ calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0); /* cyclic should be uniform */
+ makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
+ } else {
+ calcknots(nu->knotsv, nu->pntsv, nu->orderv, type);
+ }
}
- else nu->knotsv= 0;
+ else nu->knotsv= NULL;
}
}
}
@@ -645,7 +659,7 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride)
int i, j, iofs, jofs, cycl, len, resolu, resolv;
int istart, iend, jsta, jen, *jstart, *jend, ratcomp;
- if(nu->knotsu==0 || nu->knotsv==0) return;
+ if(nu->knotsu==NULL || nu->knotsv==NULL) return;
if(nu->orderu>nu->pntsu) return;
if(nu->orderv>nu->pntsv) return;
if(data==0) return;
@@ -679,24 +693,24 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride)
fp= nu->knotsu;
ustart= fp[nu->orderu-1];
- if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1];
+ if(nu->flagu & CU_CYCLIC) uend= fp[nu->pntsu+nu->orderu-1];
else uend= fp[nu->pntsu];
- ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1));
+ ustep= (uend-ustart)/(resolu-1+(nu->flagu & CU_CYCLIC));
basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbfaces3");
fp= nu->knotsv;
vstart= fp[nu->orderv-1];
- if(nu->flagv & 1) vend= fp[nu->pntsv+nu->orderv-1];
+ if(nu->flagv & CU_CYCLIC) vend= fp[nu->pntsv+nu->orderv-1];
else vend= fp[nu->pntsv];
- vstep= (vend-vstart)/(resolv-1+(nu->flagv & 1));
+ vstep= (vend-vstart)/(resolv-1+(nu->flagv & CU_CYCLIC));
len= KNOTSV(nu);
basisv= (float *)MEM_mallocN(sizeof(float)*len*resolv, "makeNurbfaces3");
jstart= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces4");
jend= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces5");
/* precalculation of basisv and jstart,jend */
- if(nu->flagv & 1) cycl= nu->orderv-1;
+ if(nu->flagv & CU_CYCLIC) cycl= nu->orderv-1;
else cycl= 0;
v= vstart;
basis= basisv;
@@ -706,7 +720,7 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride)
v+= vstep;
}
- if(nu->flagu & 1) cycl= nu->orderu-1;
+ if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1;
else cycl= 0;
in= data;
u= ustart;
@@ -803,7 +817,7 @@ void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim)
float *basisu, *sum, *fp, *in;
int i, len, istart, iend, cycl;
- if(nu->knotsu==0) return;
+ if(nu->knotsu==NULL) return;
if(nu->orderu>nu->pntsu) return;
if(data==0) return;
@@ -820,12 +834,12 @@ void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim)
fp= nu->knotsu;
ustart= fp[nu->orderu-1];
- if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1];
+ if(nu->flagu & CU_CYCLIC) uend= fp[nu->pntsu+nu->orderu-1];
else uend= fp[nu->pntsu];
- ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1));
+ ustep= (uend-ustart)/(resolu-1+(nu->flagu & CU_CYCLIC));
basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbcurve3");
- if(nu->flagu & 1) cycl= nu->orderu-1;
+ if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1;
else cycl= 0;
in= data;
@@ -1425,14 +1439,14 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *
/* returns a point */
if(prevbezt==nu->bezt) {
- if(nu->flagu & 1) pprev= last;
+ if(nu->flagu & CU_CYCLIC) pprev= last;
else pprev= prevbezt;
}
else pprev= prevbezt-1;
/* next point */
if(bezt==last) {
- if(nu->flagu & 1) next= nu->bezt;
+ if(nu->flagu & CU_CYCLIC) next= nu->bezt;
else next= bezt;
}
else next= bezt+1;
@@ -1478,7 +1492,7 @@ void makeBevelList(Object *ob)
while(nu) {
/* check we are a single point? also check we are not a surface and that the orderu is sane,
* enforced in the UI but can go wrong possibly */
- if(nu->pntsu<2 || ((nu->type & 7)==CU_NURBS && nu->pntsu < nu->orderu)) {
+ if(!check_valid_nurb_u(nu)) {
bl= MEM_callocN(sizeof(BevList)+1*sizeof(BevPoint), "makeBevelList");
BLI_addtail(&(cu->bev), bl);
bl->nr= 0;
@@ -1493,7 +1507,7 @@ void makeBevelList(Object *ob)
bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
BLI_addtail(&(cu->bev), bl);
- if(nu->flagu & 1) bl->poly= 0;
+ if(nu->flagu & CU_CYCLIC) bl->poly= 0;
else bl->poly= -1;
bl->nr= len;
bl->flag= 0;
@@ -1512,17 +1526,17 @@ void makeBevelList(Object *ob)
}
else if((nu->type & 7)==CU_BEZIER) {
- len= resolu*(nu->pntsu+ (nu->flagu & 1) -1)+1; /* in case last point is not cyclic */
+ len= resolu*(nu->pntsu+ (nu->flagu & CU_CYCLIC) -1)+1; /* in case last point is not cyclic */
bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
BLI_addtail(&(cu->bev), bl);
- if(nu->flagu & 1) bl->poly= 0;
+ if(nu->flagu & CU_CYCLIC) bl->poly= 0;
else bl->poly= -1;
bevp= (BevPoint *)(bl+1);
a= nu->pntsu-1;
bezt= nu->bezt;
- if(nu->flagu & 1) {
+ if(nu->flagu & CU_CYCLIC) {
a++;
prevbezt= nu->bezt+(nu->pntsu-1);
}
@@ -1595,7 +1609,7 @@ void makeBevelList(Object *ob)
MEM_freeN(data);
MEM_freeN(data_a);
- if((nu->flagu & 1)==0) { /* not cyclic: endpoint */
+ if((nu->flagu & CU_CYCLIC)==0) { /* not cyclic: endpoint */
bevp->x= prevbezt->vec[1][0];
bevp->y= prevbezt->vec[1][1];
bevp->z= prevbezt->vec[1][2];
@@ -1611,7 +1625,7 @@ void makeBevelList(Object *ob)
BLI_addtail(&(cu->bev), bl);
bl->nr= len;
bl->flag= 0;
- if(nu->flagu & 1) bl->poly= 0;
+ if(nu->flagu & CU_CYCLIC) bl->poly= 0;
else bl->poly= -1;
bevp= (BevPoint *)(bl+1);
@@ -2209,7 +2223,7 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */
a= nu->pntsu;
bezt= nu->bezt;
- if(nu->flagu & 1) prev= bezt+(a-1);
+ if(nu->flagu & CU_CYCLIC) prev= bezt+(a-1);
else prev= 0;
next= bezt+1;
@@ -2217,7 +2231,7 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */
calchandleNurb(bezt, prev, next, 0);
prev= bezt;
if(a==1) {
- if(nu->flagu & 1) next= nu->bezt;
+ if(nu->flagu & CU_CYCLIC) next= nu->bezt;
else next= 0;
}
else next++;
@@ -2608,3 +2622,63 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
}
}
}
+
+int check_valid_nurb_u( struct Nurb *nu )
+{
+ if (nu==NULL) return 0;
+ if (nu->pntsu <= 1) return 0;
+ if ((nu->type & 7)!=CU_NURBS) return 1; /* not a nurb, lets assume its valid */
+
+ if (nu->pntsu < nu->orderu) return 0;
+ if (((nu->flag & CU_CYCLIC)==0) && ((nu->flagu>>1) & 2)) { /* Bezier U Endpoints */
+ if (nu->orderu==4) {
+ if (nu->pntsu < 5) return 0; /* bezier with 4 orderu needs 5 points */
+ } else if (nu->orderu != 3) return 0; /* order must be 3 or 4 */
+ }
+ return 1;
+}
+int check_valid_nurb_v( struct Nurb *nu)
+{
+ if (nu==NULL) return 0;
+ if (nu->pntsv <= 1) return 0;
+ if ((nu->type & 7)!=CU_NURBS) return 1; /* not a nurb, lets assume its valid */
+
+ if (nu->pntsv < nu->orderv) return 0;
+ if (((nu->flag & CU_CYCLIC)==0) && ((nu->flagv>>1) & 2)) { /* Bezier V Endpoints */
+ if (nu->orderv==4) {
+ if (nu->pntsv < 5) return 0; /* bezier with 4 orderu needs 5 points */
+ } else if (nu->orderv != 3) return 0; /* order must be 3 or 4 */
+ }
+ return 1;
+}
+
+int clamp_nurb_order_u( struct Nurb *nu )
+{
+ int change = 0;
+ if(nu->pntsu<nu->orderu) {
+ nu->orderu= nu->pntsu;
+ change= 1;
+ }
+ if(((nu->flag & CU_CYCLIC)==0) && (nu->flagu>>1)&2) {
+ CLAMP(nu->orderu, 3,4);
+ change= 1;
+ }
+ return change;
+}
+
+int clamp_nurb_order_v( struct Nurb *nu)
+{
+ int change = 0;
+ if(nu->pntsv<nu->orderv) {
+ nu->orderv= nu->pntsv;
+ change= 1;
+ }
+ if(((nu->flag & CU_CYCLIC)==0) && (nu->flagv>>1)&2) {
+ CLAMP(nu->orderv, 3,4);
+ change= 1;
+ }
+ return change;
+}
+
+
+
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index aa436441056..298e4b81d5b 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -783,7 +783,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
else
resolu= nu->resolu;
- if(nu->pntsu<2 || ((nu->type & 7)==CU_NURBS && nu->pntsu < nu->orderu));
+ if(!check_valid_nurb_u(nu));
else if((nu->type & 7)==CU_BEZIER) {
/* count */
@@ -816,7 +816,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
data= dl->verts;
- if(nu->flagu & 1) {
+ if(nu->flagu & CU_CYCLIC) {
dl->type= DL_POLY;
a= nu->pntsu;
}
@@ -863,7 +863,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
dl->charidx = nu->charidx;
data= dl->verts;
- if(nu->flagu & 1) dl->type= DL_POLY;
+ if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
else dl->type= DL_SEGM;
makeNurbcurve(nu, data, resolu, 3);
}
@@ -878,7 +878,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
dl->charidx = nu->charidx;
data= dl->verts;
- if(nu->flagu & 1) dl->type= DL_POLY;
+ if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
else dl->type= DL_SEGM;
a= len;
@@ -1330,7 +1330,7 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender)
dl->rt= nu->flag;
data= dl->verts;
- if(nu->flagu & 1) dl->type= DL_POLY;
+ if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
else dl->type= DL_SEGM;
makeNurbcurve(nu, data, nu->resolu, 3);
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 09c93962990..52275e507dd 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -440,7 +440,7 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i
if (nu2 == NULL) return;
nu2->resolu= cu->resolu;
nu2->bezt = NULL;
- nu2->knotsu = nu2->knotsv = 0;
+ nu2->knotsu = nu2->knotsv = NULL;
nu2->flag= 0;
nu2->charidx = charidx+1000;
if (mat_nr > 0) nu2->mat_nr= mat_nr-1;
@@ -529,7 +529,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
memcpy(nu2, nu1, sizeof(struct Nurb));
nu2->resolu= cu->resolu;
nu2->bp = 0;
- nu2->knotsu = nu2->knotsv = 0;
+ nu2->knotsu = nu2->knotsv = NULL;
nu2->flag= CU_SMOOTH;
nu2->charidx = charidx;
if (info->mat_nr) {
diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c
deleted file mode 100644
index 3189fe960ad..00000000000
--- a/source/blender/blenkernel/intern/kdop.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/* kdop.c
-*
-*
-* ***** BEGIN GPL LICENSE BLOCK *****
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License
-* as published by the Free Software Foundation; either version 2
-* of the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 *****
-*/
-
-#include "MEM_guardedalloc.h"
-
-#include "BKE_cloth.h"
-
-#include "DNA_cloth_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_deform.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_effect.h"
-#include "BKE_global.h"
-#include "BKE_object.h"
-#include "BKE_modifier.h"
-#include "BKE_utildefines.h"
-
-#ifdef _OPENMP
-#include <omp.h>
-#endif
-
-
-////////////////////////////////////////////////////////////////////////
-// Additional fastened appending function
-// It uses the link to the last inserted node as start value
-// for searching the end of the list
-// NEW: in compare to the original function, this one returns
-// the reference to the last inserted node
-////////////////////////////////////////////////////////////////////////
-LinkNode *BLI_linklist_append_fast(LinkNode **listp, void *ptr) {
- LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
- LinkNode *node = *listp;
-
- nlink->link = ptr;
- nlink->next = NULL;
-
- if(node == NULL){
- *listp = nlink;
- } else {
- while(node->next != NULL){
- node = node->next;
- }
- node->next = nlink;
- }
- return nlink;
-}
-
-
-
-////////////////////////////////////////////////////////////////////////
-// Bounding Volume Hierarchy Definition
-//
-// Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below
-// Notes: You have to choose the type at compile time ITM
-// Notes: You can choose the tree type --> binary, quad, octree, choose below
-////////////////////////////////////////////////////////////////////////
-
-static float KDOP_AXES[13][3] =
-{ {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0},
-{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0},
-{0, 1.0, -1.0}
-};
-
-///////////// choose bounding volume here! /////////////
-
-#define KDOP_26
-
-
-
-#ifdef KDOP_26
-#define KDOP_END 13
-#define KDOP_START 0
-#endif
-
-#ifdef KDOP_18
-#define KDOP_END 13
-#define KDOP_START 7
-#endif
-
-#ifdef KDOP_14
-#define KDOP_END 7
-#define KDOP_START 0
-#endif
-
-// this is basicly some AABB
-#ifdef KDOP_8
-#define KDOP_END 4
-#define KDOP_START 0
-#endif
-
-// this is basicly some OBB
-#ifdef KDOP_6
-#define KDOP_END 3
-#define KDOP_START 0
-#endif
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-// Introsort
-// with permission deriven from the following Java code:
-// http://ralphunden.net/content/tutorials/a-guide-to-introsort/
-// and he derived it from the SUN STL
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-static int size_threshold = 16;
-/*
-* Common methods for all algorithms
-*/
-DO_INLINE void bvh_exchange(CollisionTree **a, int i, int j)
-{
- CollisionTree *t=a[i];
- a[i]=a[j];
- a[j]=t;
-}
-DO_INLINE int floor_lg(int a)
-{
- return (int)(floor(log(a)/log(2)));
-}
-
-/*
-* Insertion sort algorithm
-*/
-void bvh_insertionsort(CollisionTree **a, int lo, int hi, int axis)
-{
- int i,j;
- CollisionTree *t;
- for (i=lo; i < hi; i++)
- {
- j=i;
- t = a[i];
- while((j!=lo) && (t->bv[axis] < (a[j-1])->bv[axis]))
- {
- a[j] = a[j-1];
- j--;
- }
- a[j] = t;
- }
-}
-
-static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree * x, int axis)
-{
- int i=lo, j=hi;
- while (1)
- {
- while ((a[i])->bv[axis] < x->bv[axis]) i++;
- j=j-1;
- while (x->bv[axis] < (a[j])->bv[axis]) j=j-1;
- if(!(i < j))
- return i;
- bvh_exchange(a, i,j);
- i++;
- }
-}
-
-/*
-* Heapsort algorithm
-*/
-static void bvh_downheap(CollisionTree **a, int i, int n, int lo, int axis)
-{
- CollisionTree * d = a[lo+i-1];
- int child;
- while (i<=n/2)
- {
- child = 2*i;
- if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis]))
- {
- child++;
- }
- if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break;
- a[lo+i-1] = a[lo+child-1];
- i = child;
- }
- a[lo+i-1] = d;
-}
-
-static void bvh_heapsort(CollisionTree **a, int lo, int hi, int axis)
-{
- int n = hi-lo, i;
- for (i=n/2; i>=1; i=i-1)
- {
- bvh_downheap(a, i,n,lo, axis);
- }
- for (i=n; i>1; i=i-1)
- {
- bvh_exchange(a, lo,lo+i-1);
- bvh_downheap(a, 1,i-1,lo, axis);
- }
-}
-
-static CollisionTree *bvh_medianof3(CollisionTree **a, int lo, int mid, int hi, int axis) // returns Sortable
-{
- if ((a[mid])->bv[axis] < (a[lo])->bv[axis])
- {
- if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
- return a[mid];
- else
- {
- if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
- return a[hi];
- else
- return a[lo];
- }
- }
- else
- {
- if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
- {
- if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
- return a[lo];
- else
- return a[hi];
- }
- else
- return a[mid];
- }
-}
-/*
-* Quicksort algorithm modified for Introsort
-*/
-void bvh_introsort_loop (CollisionTree **a, int lo, int hi, int depth_limit, int axis)
-{
- int p;
-
- while (hi-lo > size_threshold)
- {
- if (depth_limit == 0)
- {
- bvh_heapsort(a, lo, hi, axis);
- return;
- }
- depth_limit=depth_limit-1;
- p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis);
- bvh_introsort_loop(a, p, hi, depth_limit, axis);
- hi=p;
- }
-}
-
-DO_INLINE void bvh_sort(CollisionTree **a0, int begin, int end, int axis)
-{
- if (begin < end)
- {
- CollisionTree **a=a0;
- bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
- bvh_insertionsort(a, begin, end, axis);
- }
-}
-DO_INLINE void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis)
-{
- bvh_sort(face_list, start, end, axis);
-}
-////////////////////////////////////////////////////////////////////////////////////////////////
-void bvh_free(BVH * bvh)
-{
- LinkNode *search = NULL;
- CollisionTree *tree = NULL;
-
- if (bvh)
- {
-
- search = bvh->tree;
-
- while(search)
- {
- LinkNode *next= search->next;
- tree = search->link;
-
- MEM_freeN(tree);
-
- search = next;
- }
-
- BLI_linklist_free(bvh->tree,NULL);
- bvh->tree = NULL;
-
- if(bvh->current_x)
- MEM_freeN(bvh->current_x);
- if(bvh->current_xold)
- MEM_freeN(bvh->current_xold);
-
- MEM_freeN(bvh);
- bvh = NULL;
- }
-}
-
-// only supports x,y,z axis in the moment
-// but we should use a plain and simple function here for speed sake
-DO_INLINE int bvh_largest_axis(float *bv)
-{
- float middle_point[3];
-
- middle_point[0] = (bv[1]) - (bv[0]); // x axis
- middle_point[1] = (bv[3]) - (bv[2]); // y axis
- middle_point[2] = (bv[5]) - (bv[4]); // z axis
- if (middle_point[0] > middle_point[1])
- {
- if (middle_point[0] > middle_point[2])
- return 1; // max x axis
- else
- return 5; // max z axis
- }
- else
- {
- if (middle_point[1] > middle_point[2])
- return 3; // max y axis
- else
- return 5; // max z axis
- }
-}
-
-// depends on the fact that the BVH's for each face is already build
-DO_INLINE void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
-{
- float newmin,newmax;
- int i, j;
-
- if(numfaces >0)
- {
- // for all Axes.
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- bv[(2 * i)] = (tri [0])->bv[(2 * i)];
- bv[(2 * i) + 1] = (tri [0])->bv[(2 * i) + 1];
- }
- }
-
- for (j = 0; j < numfaces; j++)
- {
- // for all Axes.
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- newmin = (tri [j])->bv[(2 * i)];
- if ((newmin < bv[(2 * i)]))
- {
- bv[(2 * i)] = newmin;
- }
-
- newmax = (tri [j])->bv[(2 * i) + 1];
- if ((newmax > bv[(2 * i) + 1]))
- {
- bv[(2 * i) + 1] = newmax;
- }
- }
- }
-}
-
-DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv, CollisionTree *tree)
-{
- MFace *tempMFace = bvh->mfaces;
- float *tempBV = bv;
- float newminmax;
- int i, j, k;
-
- for (j = 0; j < numfaces; j++)
- {
- tempMFace = bvh->mfaces + (tri [j])->tri_index;
- // 3 or 4 vertices per face.
- for (k = 0; k < 4; k++)
- {
- int temp = 0;
- // If this is a triangle.
- if (k == 3 && !tempMFace->v4)
- continue;
- // TODO: other name for "temp" this gets all vertices of a face
- if (k == 0)
- temp = tempMFace->v1;
- else if (k == 1)
- temp = tempMFace->v2;
- else if (k == 2)
- temp = tempMFace->v3;
- else if (k == 3)
- temp = tempMFace->v4;
- // for all Axes.
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- newminmax = INPR(bvh->current_xold[temp].co, KDOP_AXES[i]);
- if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
- tempBV[(2 * i)] = newminmax;
- if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
- tempBV[(2 * i) + 1] = newminmax;
- }
- }
-
- /* calculate normal of this face */
- /* (code copied from cdderivedmesh.c) */
- /*
- if(tempMFace->v4)
- CalcNormFloat4(bvh->current_xold[tempMFace->v1].co, bvh->current_xold[tempMFace->v2].co,
- bvh->current_xold[tempMFace->v3].co, bvh->current_xold[tempMFace->v4].co, tree->normal);
- else
- CalcNormFloat(bvh->current_xold[tempMFace->v1].co, bvh->current_xold[tempMFace->v2].co,
- bvh->current_xold[tempMFace->v3].co, tree->normal);
-
- tree->alpha = 0;
- */
- }
-}
-
-DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv, CollisionTree *tree)
-{
- MFace *tempMFace = bvh->mfaces;
- float *tempBV = bv;
- float newminmax;
- int i, j, k;
-
- /* TODO: calculate normals */
-
- for (j = 0; j < numfaces; j++)
- {
- tempMFace = bvh->mfaces + (tri [j])->tri_index;
- // 3 or 4 vertices per face.
- for (k = 0; k < 4; k++)
- {
- int temp = 0;
- // If this is a triangle.
- if (k == 3 && !tempMFace->v4)
- continue;
- // TODO: other name for "temp" this gets all vertices of a face
- if (k == 0)
- temp = tempMFace->v1;
- else if (k == 1)
- temp = tempMFace->v2;
- else if (k == 2)
- temp = tempMFace->v3;
- else if (k == 3)
- temp = tempMFace->v4;
- // for all Axes.
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- newminmax = INPR(bvh->current_xold[temp].co, KDOP_AXES[i]);
- if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
- tempBV[(2 * i)] = newminmax;
- if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
- tempBV[(2 * i) + 1] = newminmax;
-
- newminmax = INPR(bvh->current_x[temp].co, KDOP_AXES[i]);
- if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
- tempBV[(2 * i)] = newminmax;
- if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
- tempBV[(2 * i) + 1] = newminmax;
- }
- }
- }
-}
-
-static void bvh_div_env_node(BVH *bvh, CollisionTree *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink)
-{
- int i = 0;
- CollisionTree *newtree = NULL;
- int laxis = 0, max_nodes=4;
- unsigned int tstart, tend;
- LinkNode *nlink1 = nlink;
- LinkNode *tnlink;
- tree->traversed = 0;
- // Determine which axis to split along
- laxis = bvh_largest_axis(tree->bv);
-
- // Sort along longest axis
- if(laxis!=lastaxis)
- bvh_sort_along_axis(face_list, start, end, laxis);
-
- // maximum is 4 since we have a quad tree
- max_nodes = MIN2((end-start + 1 ),4);
-
- for (i = 0; i < max_nodes; i++)
- {
- tree->count_nodes++;
-
- if(end-start+1 > 4)
- {
- int quarter = ((float)((float)(end - start + 1) / 4.0f));
- tstart = start + i * quarter;
- tend = tstart + quarter - 1;
-
- // be sure that we get all faces
- if(i==3)
- {
- tend = end;
- }
- }
- else
- {
- tend = tstart = start + i;
- }
-
- // Build tree until 4 node left.
- if ((tend-tstart + 1 ) > 1)
- {
- newtree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
- tnlink = BLI_linklist_append_fast(&nlink1->next, newtree);
-
- newtree->nodes[0] = newtree->nodes[1] = newtree->nodes[2] = newtree->nodes[3] = NULL;
- newtree->count_nodes = 0;
- newtree->parent = tree;
- newtree->isleaf = 0;
-
- tree->nodes[i] = newtree;
-
- nlink1 = tnlink;
-
- bvh_calc_DOP_hull_from_faces(bvh, &face_list[tstart], tend-tstart + 1, tree->nodes[i]->bv);
-
- bvh_div_env_node(bvh, tree->nodes[i], face_list, tstart, tend, laxis, nlink1);
- }
- else // ok, we have 1 left for this node
- {
- CollisionTree *tnode = face_list[tstart];
- tree->nodes[i] = tnode;
- tree->nodes[i]->parent = tree;
- }
- }
- return;
-}
-
-/* function cannot be directly called - needs alloced bvh */
-void bvh_build (BVH *bvh)
-{
- unsigned int i = 0, j = 0, k = 0;
- CollisionTree **face_list=NULL;
- CollisionTree *tree=NULL;
- LinkNode *nlink = NULL;
-
- bvh->flags = 0;
- bvh->leaf_tree = NULL;
- bvh->leaf_root = NULL;
- bvh->tree = NULL;
-
- if(!bvh->current_x)
- {
- bvh_free(bvh);
- return;
- }
-
- bvh->current_xold = MEM_dupallocN(bvh->current_x);
-
- tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
-
- if (tree == NULL)
- {
- printf("bvh_build: Out of memory for nodes.\n");
- bvh_free(bvh);
- return;
- }
-
- BLI_linklist_append(&bvh->tree, tree);
-
- nlink = bvh->tree;
-
- bvh->root = bvh->tree->link;
- bvh->root->isleaf = 0;
- bvh->root->parent = NULL;
- bvh->root->nodes[0] = bvh->root->nodes[1] = bvh->root->nodes[1] = bvh->root->nodes[3] = NULL;
-
- if(bvh->numfaces<=1)
- {
- bvh->root->tri_index = 0; // Why that? --> only one face there
- bvh->root->isleaf = 1;
- bvh->root->traversed = 0;
- bvh->root->count_nodes = 0;
- bvh->leaf_root = bvh->root;
- bvh->leaf_tree = bvh->root;
- bvh->root->nextLeaf = NULL;
- bvh->root->prevLeaf = NULL;
- }
- else
- {
- // create face boxes
- face_list = MEM_callocN (bvh->numfaces * sizeof (CollisionTree *), "CollisionTree");
- if (face_list == NULL)
- {
- printf("bvh_build: Out of memory for face_list.\n");
- bvh_free(bvh);
- return;
- }
-
- // create face boxes
- for(i = 0, k = 0; i < bvh->numfaces; i++)
- {
- LinkNode *tnlink;
-
- tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
- // TODO: check succesfull alloc
-
- tnlink = BLI_linklist_append_fast(&nlink->next, tree);
-
- face_list[i] = tree;
- tree->tri_index = i;
- tree->isleaf = 1;
- tree->nextLeaf = NULL;
- tree->prevLeaf = bvh->leaf_tree;
- tree->parent = NULL;
- tree->count_nodes = 0;
-
- if(i==0)
- {
- bvh->leaf_tree = bvh->leaf_root = tree;
- }
- else
- {
- bvh->leaf_tree->nextLeaf = tree;
- bvh->leaf_tree = bvh->leaf_tree->nextLeaf;
- }
-
- tree->nodes[0] = tree->nodes[1] = tree->nodes[2] = tree->nodes[3] = NULL;
-
- bvh_calc_DOP_hull_static(bvh, &face_list[i], 1, tree->bv, tree);
-
- // inflate the bv with some epsilon
- for (j = KDOP_START; j < KDOP_END; j++)
- {
- tree->bv[(2 * j)] -= bvh->epsilon; // minimum
- tree->bv[(2 * j) + 1] += bvh->epsilon; // maximum
- }
-
- nlink = tnlink;
- }
-
- // build root bvh
- bvh_calc_DOP_hull_from_faces(bvh, face_list, bvh->numfaces, bvh->root->bv);
-
- // This is the traversal function.
- bvh_div_env_node(bvh, bvh->root, face_list, 0, bvh->numfaces-1, 0, nlink);
- if (face_list)
- MEM_freeN(face_list);
-
- }
-
-}
-
-// bvh_overlap - is it possbile for 2 bv's to collide ?
-DO_INLINE int bvh_overlap(float *bv1, float *bv2)
-{
- int i = 0;
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- // Minimum test.
- if (bv1[(2 * i)] > bv2[(2 * i) + 1])
- {
- return 0;
- }
- // Maxiumum test.
- if (bv2[(2 * i)] > bv1[(2 * i) + 1])
- {
- return 0;
- }
- }
-
- return 1;
-}
-
-// bvh_overlap_self - is it possbile for 2 bv's to selfcollide ?
-DO_INLINE int bvh_overlap_self(CollisionTree * tree1, CollisionTree * tree2)
-{
- // printf("overlap: %f, q: %f\n", (saacos(INPR(tree1->normal, tree2->normal)) / 2.0)+MAX2(tree1->alpha, tree2->alpha), saacos(INPR(tree1->normal, tree2->normal)));
-
- if((saacos(INPR(tree1->normal, tree2->normal)) / 2.0)+MAX2(tree1->alpha, tree2->alpha) > M_PI)
- {
- return 1;
- }
- else
- return 0;
-}
-
-/**
- * bvh_traverse - traverse two bvh trees looking for potential collisions.
- *
- * max collisions are n*n collisions --> every triangle collide with
- * every other triangle that doesn't require any realloc, but uses
- * much memory
- */
-int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision)
-{
- int i = 0, ret=0, overlap = 0;
-
- /*
- // Shouldn't be possible
- if(!tree1 || !tree2)
- {
- printf("Error: no tree there\n");
- return 0;
-}
- */
-
- if(selfcollision)
- overlap = bvh_overlap_self(tree1, tree2);
- else
- overlap = bvh_overlap(tree1->bv, tree2->bv);
-
- if (overlap)
- {
- // Check if this node in the first tree is a leaf
- if (tree1->isleaf)
- {
- // Check if this node in the second tree a leaf
- if (tree2->isleaf)
- {
- // Provide the collision response.
-
- if(collision_response)
- collision_response (md1, md2, tree1, tree2);
- return 1;
- }
- else
- {
- // Process the quad tree.
- for (i = 0; i < 4; i++)
- {
- // Only traverse nodes that exist.
- if (tree2->nodes[i] && bvh_traverse (md1, md2, tree1, tree2->nodes[i], step, collision_response, selfcollision))
- ret = 1;
- }
- }
- }
- else
- {
- // Process the quad tree.
- for (i = 0; i < 4; i++)
- {
- // Only traverse nodes that exist.
- if (tree1->nodes [i] && bvh_traverse (md1, md2, tree1->nodes[i], tree2, step, collision_response, selfcollision))
- ret = 1;
- }
- }
- }
-
- return ret;
-}
-// bottom up update of bvh tree:
-// join the 4 children here
-void bvh_join(CollisionTree *tree)
-{
- int i = 0, j = 0;
- float max = 0;
-
- if (!tree)
- return;
-
- for (i = 0; i < 4; i++)
- {
- if (tree->nodes[i])
- {
- for (j = KDOP_START; j < KDOP_END; j++)
- {
- // update minimum
- if ((tree->nodes[i]->bv[(2 * j)] < tree->bv[(2 * j)]) || (i == 0))
- {
- tree->bv[(2 * j)] = tree->nodes[i]->bv[(2 * j)];
- }
- // update maximum
- if ((tree->nodes[i]->bv[(2 * j) + 1] > tree->bv[(2 * j) + 1])|| (i == 0))
- {
- tree->bv[(2 * j) + 1] = tree->nodes[i]->bv[(2 * j) + 1];
- }
- }
-
- /* for selfcollisions */
- /*
- if(!i)
- {
- tree->alpha = tree->nodes[i]->alpha;
- VECCOPY(tree->normal, tree->nodes[i]->normal);
- }
- else
- {
- tree->alpha += saacos(INPR(tree->normal, tree->nodes[i]->normal)) / 2.0;
- VECADD(tree->normal, tree->normal, tree->nodes[i]->normal);
- VecMulf(tree->normal, 0.5);
- max = MAX2(max, tree->nodes[i]->alpha);
- }
- */
-
- }
- else
- break;
- }
-
- tree->alpha += max;
-}
-
-// update static bvh
-/* you have to update the bvh position before calling this function */
-void bvh_update(BVH * bvh, int moving)
-{
- CollisionTree *leaf, *parent;
- int traversecheck = 1; // if this is zero we don't go further
- unsigned int j = 0;
-
- for (leaf = bvh->leaf_root; leaf; leaf = leaf->nextLeaf)
- {
- traversecheck = 1;
- if ((leaf->parent) && (leaf->parent->traversed == leaf->parent->count_nodes))
- {
- leaf->parent->traversed = 0;
- }
- if(!moving)
- bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv, leaf);
- else
- bvh_calc_DOP_hull_moving(bvh, &leaf, 1, leaf->bv, leaf);
-
- // inflate the bv with some epsilon
- for (j = KDOP_START; j < KDOP_END; j++)
- {
- leaf->bv[(2 * j)] -= bvh->epsilon; // minimum
- leaf->bv[(2 * j) + 1] += bvh->epsilon; // maximum
- }
-
- for (parent = leaf->parent; parent; parent = parent->parent)
- {
- if (traversecheck)
- {
- parent->traversed++; // we tried to go up in hierarchy
- if (parent->traversed < parent->count_nodes)
- {
- traversecheck = 0;
-
- if (parent->parent)
- {
- if (parent->parent->traversed == parent->parent->count_nodes)
- {
- parent->parent->traversed = 0;
- }
- }
- break; // we do not need to check further
- }
- else
- {
- bvh_join(parent);
- }
- }
-
- }
- }
-}
-
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index e9f89d6f264..ab3f01f6c6e 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -43,6 +43,7 @@
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
+#include "BLI_kdopbvh.h"
#include "BLI_kdtree.h"
#include "BLI_linklist.h"
#include "BLI_rand.h"
@@ -76,6 +77,7 @@
#include "BKE_anim.h"
#include "BKE_bad_level_calls.h"
#include "BKE_cloth.h"
+#include "BKE_collision.h"
#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
@@ -2736,6 +2738,7 @@ static DerivedMesh *bevelModifier_applyModifier(
{
DerivedMesh *result;
BME_Mesh *bm;
+
/*bDeformGroup *def;*/
int /*i,*/ options, defgrp_index = -1;
BevelModifierData *bmd = (BevelModifierData*) md;
@@ -2754,8 +2757,7 @@ static DerivedMesh *bevelModifier_applyModifier(
//~ }
//~ }
- bm = BME_make_mesh();
- bm = BME_derivedmesh_to_bmesh(derivedData, bm);
+ bm = BME_derivedmesh_to_bmesh(derivedData);
BME_bevel(bm,bmd->value,bmd->res,options,defgrp_index,bmd->bevel_angle,NULL);
result = BME_bmesh_to_derivedmesh(bm,derivedData);
BME_free_mesh(bm);
@@ -5193,7 +5195,7 @@ static void collisionModifier_initData(ModifierData *md)
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
- collmd->bvh = NULL;
+ collmd->bvhtree = NULL;
}
static void collisionModifier_freeData(ModifierData *md)
@@ -5202,8 +5204,8 @@ static void collisionModifier_freeData(ModifierData *md)
if (collmd)
{
- if(collmd->bvh)
- bvh_free(collmd->bvh);
+ if(collmd->bvhtree)
+ BLI_bvhtree_free(collmd->bvhtree);
if(collmd->x)
MEM_freeN(collmd->x);
if(collmd->xnew)
@@ -5214,7 +5216,6 @@ static void collisionModifier_freeData(ModifierData *md)
MEM_freeN(collmd->current_xnew);
if(collmd->current_v)
MEM_freeN(collmd->current_v);
-
if(collmd->mfaces)
MEM_freeN(collmd->mfaces);
@@ -5225,7 +5226,7 @@ static void collisionModifier_freeData(ModifierData *md)
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
- collmd->bvh = NULL;
+ collmd->bvhtree = NULL;
collmd->mfaces = NULL;
}
}
@@ -5293,9 +5294,8 @@ static void collisionModifier_deformVerts(
collmd->mfaces = dm->dupFaceArray(dm);
collmd->numfaces = dm->getNumFaces(dm);
- // TODO: epsilon
// create bounding box hierarchy
- collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
collmd->time = current_time;
}
@@ -5318,25 +5318,25 @@ static void collisionModifier_deformVerts(
memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
/* check if GUI setting has changed for bvh */
- if(collmd->bvh)
+ if(collmd->bvhtree)
{
- if(ob->pd->pdef_sboft != collmd->bvh->epsilon)
+ if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree))
{
- bvh_free(collmd->bvh);
- collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
+ BLI_bvhtree_free(collmd->bvhtree);
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
}
}
- /* happens on file load (ONLY when i decomment changes in readfile.c */
- if(!collmd->bvh)
+ /* happens on file load (ONLY when i decomment changes in readfile.c) */
+ if(!collmd->bvhtree)
{
- collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
}
else
{
// recalc static bounding boxes
- bvh_update_from_mvert(collmd->bvh, collmd->current_x, numverts, NULL, 0);
+ bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
}
collmd->time = current_time;
@@ -6485,12 +6485,14 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
MFace *mf=0;
MVert *dupvert=0;
ParticleSettings *part=psmd->psys->part;
- ParticleData *pa, *pars=psmd->psys->particles;
+ ParticleData *pa=NULL, *pars=psmd->psys->particles;
ParticleKey state;
+ EdgeHash *vertpahash;
+ EdgeHashIterator *ehi;
float *vertco=0, imat[4][4];
float loc0[3], nor[3];
float timestep, cfra;
- int *facepa=emd->facepa, *vertpa=0;
+ int *facepa=emd->facepa;
int totdup=0,totvert=0,totface=0,totpart=0;
int i, j, v, mindex=0;
@@ -6505,34 +6507,36 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
else
cfra=bsystem_time(ob,(float)G.scene->r.cfra,0.0);
- /* table for vertice <-> particle relations (row totpart+1 is for yet unexploded verts) */
- vertpa = MEM_callocN(sizeof(int)*(totpart+1)*totvert, "explode_vertpatab");
- for(i=0; i<(totpart+1)*totvert; i++)
- vertpa[i] = -1;
+ /* hash table for vertice <-> particle relations */
+ vertpahash= BLI_edgehash_new();
for (i=0; i<totface; i++) {
+ /* do mindex + totvert to ensure the vertex index to be the first
+ * with BLI_edgehashIterator_getKey */
if(facepa[i]==totpart || cfra <= (pars+facepa[i])->time)
- mindex = totpart*totvert;
+ mindex = totvert+totpart;
else
- mindex = facepa[i]*totvert;
+ mindex = totvert+facepa[i];
mf=CDDM_get_face(dm,i);
- /*set face vertices to exist in particle group*/
- vertpa[mindex+mf->v1] = 1;
- vertpa[mindex+mf->v2] = 1;
- vertpa[mindex+mf->v3] = 1;
+ /* set face vertices to exist in particle group */
+ BLI_edgehash_insert(vertpahash, mf->v1, mindex, NULL);
+ BLI_edgehash_insert(vertpahash, mf->v2, mindex, NULL);
+ BLI_edgehash_insert(vertpahash, mf->v3, mindex, NULL);
if(mf->v4)
- vertpa[mindex+mf->v4] = 1;
+ BLI_edgehash_insert(vertpahash, mf->v4, mindex, NULL);
}
- /*make new vertice indexes & count total vertices after duplication*/
- for(i=0; i<(totpart+1)*totvert; i++){
- if(vertpa[i] != -1)
- vertpa[i] = totdup++;
+ /* make new vertice indexes & count total vertices after duplication */
+ ehi= BLI_edgehashIterator_new(vertpahash);
+ for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup));
+ totdup++;
}
+ BLI_edgehashIterator_free(ehi);
- /*the final duplicated vertices*/
+ /* the final duplicated vertices */
explode= CDDM_from_template(dm, totdup, 0,totface);
dupvert= CDDM_get_verts(explode);
@@ -6541,45 +6545,49 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
psmd->psys->lattice = psys_get_lattice(ob, psmd->psys);
- /*duplicate & displace vertices*/
- for(i=0, pa=pars; i<=totpart; i++, pa++){
- if(i!=totpart){
+ /* duplicate & displace vertices */
+ ehi= BLI_edgehashIterator_new(vertpahash);
+ for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ MVert source;
+ MVert *dest;
+
+ /* get particle + vertex from hash */
+ BLI_edgehashIterator_getKey(ehi, &j, &i);
+ i -= totvert;
+ v= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
+
+ dm->getVert(dm, j, &source);
+ dest = CDDM_get_vert(explode,v);
+
+ DM_copy_vert_data(dm,explode,j,v,1);
+ *dest = source;
+
+ if(i!=totpart) {
+ /* get particle */
+ pa= pars+i;
+
+ /* get particle state */
psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,loc0,nor,0,0,0,0);
Mat4MulVecfl(ob->obmat,loc0);
state.time=cfra;
psys_get_particle_state(ob,psmd->psys,i,&state,1);
- }
-
- for(j=0; j<totvert; j++){
- v=vertpa[i*totvert+j];
- if(v != -1) {
- MVert source;
- MVert *dest;
-
- dm->getVert(dm, j, &source);
- dest = CDDM_get_vert(explode,v);
-
- DM_copy_vert_data(dm,explode,j,v,1);
- *dest = source;
- if(i!=totpart){
- vertco=CDDM_get_vert(explode,v)->co;
-
- Mat4MulVecfl(ob->obmat,vertco);
+ vertco=CDDM_get_vert(explode,v)->co;
+
+ Mat4MulVecfl(ob->obmat,vertco);
- VECSUB(vertco,vertco,loc0);
+ VECSUB(vertco,vertco,loc0);
- /* apply rotation, size & location */
- QuatMulVecf(state.rot,vertco);
- VecMulf(vertco,pa->size);
- VECADD(vertco,vertco,state.co);
+ /* apply rotation, size & location */
+ QuatMulVecf(state.rot,vertco);
+ VecMulf(vertco,pa->size);
+ VECADD(vertco,vertco,state.co);
- Mat4MulVecfl(imat,vertco);
- }
- }
+ Mat4MulVecfl(imat,vertco);
}
}
+ BLI_edgehashIterator_free(ehi);
/*map new vertices to faces*/
for (i=0; i<totface; i++) {
@@ -6601,15 +6609,15 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
orig_v4 = source.v4;
if(facepa[i]!=totpart && cfra <= pa->time)
- mindex = totpart*totvert;
+ mindex = totvert+totpart;
else
- mindex = facepa[i]*totvert;
+ mindex = totvert+facepa[i];
- source.v1 = vertpa[mindex+source.v1];
- source.v2 = vertpa[mindex+source.v2];
- source.v3 = vertpa[mindex+source.v3];
+ source.v1 = edgesplit_get(vertpahash, source.v1, mindex);
+ source.v2 = edgesplit_get(vertpahash, source.v2, mindex);
+ source.v3 = edgesplit_get(vertpahash, source.v3, mindex);
if(source.v4)
- source.v4 = vertpa[mindex+source.v4];
+ source.v4 = edgesplit_get(vertpahash, source.v4, mindex);
DM_copy_face_data(dm,explode,i,i,1);
@@ -6618,9 +6626,10 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
test_index_face(mf, &explode->faceData, i, (mf->v4 ? 4 : 3));
}
+ MEM_printmemlist_stats();
/* cleanup */
- if(vertpa) MEM_freeN(vertpa);
+ BLI_edgehash_free(vertpahash, NULL);
/* finalization */
CDDM_calc_edges(explode);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index ab1bc5a2265..4f901ba7216 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1614,7 +1614,7 @@ static void give_parvert(Object *par, int nr, float *vec)
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->keyindex==nr) {
- memcpy(vec, eve->co, 12);
+ memcpy(vec, eve->co, sizeof(float)*3);
break;
}
}
@@ -1652,18 +1652,20 @@ static void give_parvert(Object *par, int nr, float *vec)
Curve *cu;
BPoint *bp;
BezTriple *bezt;
+ int found= 0;
cu= par->data;
nu= cu->nurb.first;
if(par==G.obedit) nu= editNurb.first;
count= 0;
- while(nu) {
+ while(nu && !found) {
if((nu->type & 7)==CU_BEZIER) {
bezt= nu->bezt;
a= nu->pntsu;
while(a--) {
if(count==nr) {
+ found= 1;
VECCOPY(vec, bezt->vec[1]);
break;
}
@@ -1676,7 +1678,8 @@ static void give_parvert(Object *par, int nr, float *vec)
a= nu->pntsu*nu->pntsv;
while(a--) {
if(count==nr) {
- memcpy(vec, bp->vec, 12);
+ found= 1;
+ memcpy(vec, bp->vec, sizeof(float)*3);
break;
}
count++;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 7b727528b3d..57ecffbb796 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -185,8 +185,8 @@ static int ptcache_path(PTCacheID *pid, char *filename)
file[i-6] = '\0';
sprintf(filename, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
- BLI_add_slash(filename);
BLI_convertstringcode(filename, blendfilename);
+ BLI_add_slash(filename);
return strlen(filename);
}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 872f81ead63..876547042dc 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -2075,13 +2075,13 @@ void txt_backspace_char (Text *text)
return;
}
else if (text->curc==0) { /* Appending two lines */
- if (text->curl->prev) {
- text->curl= text->curl->prev;
- text->curc= text->curl->len;
-
- txt_combine_lines(text, text->curl, text->curl->next);
- txt_pop_sel(text);
- }
+ if (!text->curl->prev) return;
+
+ text->curl= text->curl->prev;
+ text->curc= text->curl->len;
+
+ txt_combine_lines(text, text->curl, text->curl->next);
+ txt_pop_sel(text);
}
else { /* Just backspacing a char */
int i= text->curc-1;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index c95e3d20442..64af8258f80 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -867,7 +867,7 @@ void end_ffmpeg(void)
fprintf(stderr, "Closing ffmpeg...\n");
- if (audio_stream) {
+ if (audio_stream && video_stream) {
write_audio_frames();
}
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
new file mode 100644
index 00000000000..b81ff0ee66f
--- /dev/null
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -0,0 +1,60 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel Genrich, Andre Pinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#ifndef BLI_KDOPBVH_H
+#define BLI_KDOPBVH_H
+
+#include <float.h>
+
+struct BVHTree;
+typedef struct BVHTree BVHTree;
+
+typedef struct BVHTreeOverlap {
+ int indexA;
+ int indexB;
+} BVHTreeOverlap;
+
+BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis);
+void BLI_bvhtree_free(BVHTree *tree);
+
+/* construct: first insert points, then call balance */
+int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints);
+void BLI_bvhtree_balance(BVHTree *tree);
+
+/* update: first update points/nodes, then call update_tree to refit the bounding volumes */
+int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints);
+void BLI_bvhtree_update_tree(BVHTree *tree);
+
+/* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */
+BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result);
+
+float BLI_bvhtree_getepsilon(BVHTree *tree);
+
+#endif // BLI_KDOPBVH_H
+
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
new file mode 100644
index 00000000000..a85883f6572
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -0,0 +1,810 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel Genrich, Andre Pinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "math.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_kdopbvh.h"
+#include "BLI_arithb.h"
+
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
+typedef struct BVHNode
+{
+ struct BVHNode **children; // max 8 children
+ struct BVHNode *parent; // needed for bottom - top update
+ float *bv; // Bounding volume of all nodes, max 13 axis
+ int index; /* face, edge, vertex index */
+ char totnode; // how many nodes are used, used for speedup
+ char traversed; // how many nodes already traversed until this level?
+ char main_axis;
+} BVHNode;
+
+struct BVHTree
+{
+ BVHNode **nodes;
+ BVHNode *nodearray; /* pre-alloc branch nodes */
+ BVHNode **nodechild; // pre-alloc childs for nodes
+ float *nodebv; // pre-alloc bounding-volumes for nodes
+ float epsilon; /* epslion is used for inflation of the k-dop */
+ int totleaf; // leafs
+ int totbranch;
+ char tree_type; // type of tree (4 => quadtree)
+ char axis; // kdop type (6 => OBB, 7 => AABB, ...)
+ char start_axis, stop_axis; // KDOP_AXES array indices according to axis
+};
+
+typedef struct BVHOverlapData
+{
+ BVHTree *tree1, *tree2;
+ BVHTreeOverlap *overlap;
+ int i, max_overlap; /* i is number of overlaps */
+} BVHOverlapData;
+////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+// Bounding Volume Hierarchy Definition
+//
+// Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below
+// Notes: You have to choose the type at compile time ITM
+// Notes: You can choose the tree type --> binary, quad, octree, choose below
+////////////////////////////////////////////////////////////////////////
+
+static float KDOP_AXES[13][3] =
+{ {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0},
+{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0},
+{0, 1.0, -1.0}
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// Introsort
+// with permission deriven from the following Java code:
+// http://ralphunden.net/content/tutorials/a-guide-to-introsort/
+// and he derived it from the SUN STL
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+static int size_threshold = 16;
+/*
+* Common methods for all algorithms
+*/
+static int floor_lg(int a)
+{
+ return (int)(floor(log(a)/log(2)));
+}
+
+/*
+* Insertion sort algorithm
+*/
+static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis)
+{
+ int i,j;
+ BVHNode *t;
+ for (i=lo; i < hi; i++)
+ {
+ j=i;
+ t = a[i];
+ while((j!=lo) && (t->bv[axis] < (a[j-1])->bv[axis]))
+ {
+ a[j] = a[j-1];
+ j--;
+ }
+ a[j] = t;
+ }
+}
+
+static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis)
+{
+ int i=lo, j=hi;
+ while (1)
+ {
+ while ((a[i])->bv[axis] < x->bv[axis]) i++;
+ j--;
+ while (x->bv[axis] < (a[j])->bv[axis]) j--;
+ if(!(i < j))
+ return i;
+ SWAP( BVHNode* , a[i], a[j]);
+ i++;
+ }
+}
+
+/*
+* Heapsort algorithm
+*/
+static void bvh_downheap(BVHNode **a, int i, int n, int lo, int axis)
+{
+ BVHNode * d = a[lo+i-1];
+ int child;
+ while (i<=n/2)
+ {
+ child = 2*i;
+ if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis]))
+ {
+ child++;
+ }
+ if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break;
+ a[lo+i-1] = a[lo+child-1];
+ i = child;
+ }
+ a[lo+i-1] = d;
+}
+
+static void bvh_heapsort(BVHNode **a, int lo, int hi, int axis)
+{
+ int n = hi-lo, i;
+ for (i=n/2; i>=1; i=i-1)
+ {
+ bvh_downheap(a, i,n,lo, axis);
+ }
+ for (i=n; i>1; i=i-1)
+ {
+ SWAP(BVHNode*, a[lo],a[lo+i-1]);
+ bvh_downheap(a, 1,i-1,lo, axis);
+ }
+}
+
+static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // returns Sortable
+{
+ if ((a[mid])->bv[axis] < (a[lo])->bv[axis])
+ {
+ if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
+ return a[mid];
+ else
+ {
+ if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
+ return a[hi];
+ else
+ return a[lo];
+ }
+ }
+ else
+ {
+ if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
+ {
+ if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
+ return a[lo];
+ else
+ return a[hi];
+ }
+ else
+ return a[mid];
+ }
+}
+/*
+* Quicksort algorithm modified for Introsort
+*/
+static void bvh_introsort_loop (BVHNode **a, int lo, int hi, int depth_limit, int axis)
+{
+ int p;
+
+ while (hi-lo > size_threshold)
+ {
+ if (depth_limit == 0)
+ {
+ bvh_heapsort(a, lo, hi, axis);
+ return;
+ }
+ depth_limit=depth_limit-1;
+ p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis);
+ bvh_introsort_loop(a, p, hi, depth_limit, axis);
+ hi=p;
+ }
+}
+
+static void sort(BVHNode **a0, int begin, int end, int axis)
+{
+ if (begin < end)
+ {
+ BVHNode **a=a0;
+ bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
+ bvh_insertionsort(a, begin, end, axis);
+ }
+}
+void sort_along_axis(BVHTree *tree, int start, int end, int axis)
+{
+ sort(tree->nodes, start, end, axis);
+}
+
+//after a call to this function you can expect one of:
+// every node to left of a[n] are smaller or equal to it
+// every node to the right of a[n] are greater or equal to it
+int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){
+ int begin = _begin, end = _end, cut;
+ while(end-begin > 3)
+ {
+ cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis );
+ if(cut <= n)
+ begin = cut;
+ else
+ end = cut;
+ }
+ bvh_insertionsort(a, begin, end, axis);
+
+ return n;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BLI_bvhtree_free(BVHTree *tree)
+{
+ if(tree)
+ {
+ MEM_freeN(tree->nodes);
+ MEM_freeN(tree->nodearray);
+ MEM_freeN(tree->nodebv);
+ MEM_freeN(tree->nodechild);
+ MEM_freeN(tree);
+ }
+}
+
+BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
+{
+ BVHTree *tree;
+ int numbranches=0, i;
+
+ // only support up to octree
+ if(tree_type > 8)
+ return NULL;
+
+ tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree");
+
+ if(tree)
+ {
+ tree->epsilon = epsilon;
+ tree->tree_type = tree_type;
+ tree->axis = axis;
+
+ if(axis == 26)
+ {
+ tree->start_axis = 0;
+ tree->stop_axis = 13;
+ }
+ else if(axis == 18)
+ {
+ tree->start_axis = 7;
+ tree->stop_axis = 13;
+ }
+ else if(axis == 14)
+ {
+ tree->start_axis = 0;
+ tree->stop_axis = 7;
+ }
+ else if(axis == 8) // AABB
+ {
+ tree->start_axis = 0;
+ tree->stop_axis = 4;
+ }
+ else if(axis == 6) // OBB
+ {
+ tree->start_axis = 0;
+ tree->stop_axis = 3;
+ }
+ else
+ {
+ MEM_freeN(tree);
+ return NULL;
+ }
+
+
+ // calculate max number of branches, our bvh kdop is "almost perfect"
+ for(i = 1; i <= (int)ceil((float)((float)log(maxsize)/(float)log(tree_type))); i++)
+ numbranches += (pow(tree_type, i) / tree_type);
+
+ tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*(numbranches+maxsize + tree_type), "BVHNodes");
+
+ if(!tree->nodes)
+ {
+ MEM_freeN(tree);
+ return NULL;
+ }
+
+ tree->nodebv = (float*)MEM_callocN(sizeof(float)* axis * (numbranches+maxsize + tree_type), "BVHNodeBV");
+ if(!tree->nodebv)
+ {
+ MEM_freeN(tree->nodes);
+ MEM_freeN(tree);
+ }
+
+ tree->nodechild = (BVHNode**)MEM_callocN(sizeof(BVHNode*) * tree_type * (numbranches+maxsize + tree_type), "BVHNodeBV");
+ if(!tree->nodechild)
+ {
+ MEM_freeN(tree->nodebv);
+ MEM_freeN(tree->nodes);
+ MEM_freeN(tree);
+ }
+
+ tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)*(numbranches+maxsize + tree_type), "BVHNodeArray");
+
+ if(!tree->nodearray)
+ {
+ MEM_freeN(tree->nodechild);
+ MEM_freeN(tree->nodebv);
+ MEM_freeN(tree->nodes);
+ MEM_freeN(tree);
+ return NULL;
+ }
+
+ //link the dynamic bv and child links
+ for(i=0; i< numbranches+maxsize + tree_type; i++)
+ {
+ tree->nodearray[i].bv = tree->nodebv + i * axis;
+ tree->nodearray[i].children = tree->nodechild + i * tree_type;
+ }
+
+ }
+
+ return tree;
+}
+
+
+static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving)
+{
+ float newminmax;
+ int i, k;
+
+ // don't init boudings for the moving case
+ if(!moving)
+ {
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ node->bv[2*i] = FLT_MAX;
+ node->bv[2*i + 1] = -FLT_MAX;
+ }
+ }
+
+ for(k = 0; k < numpoints; k++)
+ {
+ // for all Axes.
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ newminmax = INPR(&co[k * 3], KDOP_AXES[i]);
+ if (newminmax < node->bv[2 * i])
+ node->bv[2 * i] = newminmax;
+ if (newminmax > node->bv[(2 * i) + 1])
+ node->bv[(2 * i) + 1] = newminmax;
+ }
+ }
+}
+
+// depends on the fact that the BVH's for each face is already build
+static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end)
+{
+ float newmin,newmax;
+ int i, j;
+ float *bv = node->bv;
+
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ bv[2*i] = FLT_MAX;
+ bv[2*i + 1] = -FLT_MAX;
+ }
+
+ for (j = start; j < end; j++)
+ {
+// for all Axes.
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ newmin = tree->nodes[j]->bv[(2 * i)];
+ if ((newmin < bv[(2 * i)]))
+ bv[(2 * i)] = newmin;
+
+ newmax = tree->nodes[j]->bv[(2 * i) + 1];
+ if ((newmax > bv[(2 * i) + 1]))
+ bv[(2 * i) + 1] = newmax;
+ }
+ }
+}
+
+int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints)
+{
+ BVHNode *node= NULL;
+ int i;
+
+ // insert should only possible as long as tree->totbranch is 0
+ if(tree->totbranch > 0)
+ return 0;
+
+ if(tree->totleaf+1 >= MEM_allocN_len(tree->nodes))
+ return 0;
+
+ // TODO check if have enough nodes in array
+
+ node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]);
+ tree->totleaf++;
+
+ create_kdop_hull(tree, node, co, numpoints, 0);
+
+ // inflate the bv with some epsilon
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ node->bv[(2 * i)] -= tree->epsilon; // minimum
+ node->bv[(2 * i) + 1] += tree->epsilon; // maximum
+ }
+
+ node->index= index;
+
+ return 1;
+}
+
+// only supports x,y,z axis in the moment
+// but we should use a plain and simple function here for speed sake
+static char get_largest_axis(float *bv)
+{
+ float middle_point[3];
+
+ middle_point[0] = (bv[1]) - (bv[0]); // x axis
+ middle_point[1] = (bv[3]) - (bv[2]); // y axis
+ middle_point[2] = (bv[5]) - (bv[4]); // z axis
+ if (middle_point[0] > middle_point[1])
+ {
+ if (middle_point[0] > middle_point[2])
+ return 1; // max x axis
+ else
+ return 5; // max z axis
+ }
+ else
+ {
+ if (middle_point[1] > middle_point[2])
+ return 3; // max y axis
+ else
+ return 5; // max z axis
+ }
+}
+
+static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char lastaxis)
+{
+ char laxis;
+ int i, tend;
+ BVHNode *tnode;
+ int slice = (end-start+tree->tree_type-1)/tree->tree_type; //division rounded up
+
+ // Determine which axis to split along
+ laxis = get_largest_axis(node->bv);
+
+ // split nodes along longest axis
+ for (i=0; start < end; start += slice, i++) //i counts the current child
+ {
+ tend = start + slice;
+
+ if(tend > end) tend = end;
+
+ if(tend-start == 1) // ok, we have 1 left for this node
+ {
+ node->children[i] = tree->nodes[start];
+ node->children[i]->parent = node;
+ }
+ else
+ {
+ tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]);
+ tree->totbranch++;
+ tnode->parent = node;
+
+ if(tend != end)
+ partition_nth_element(tree->nodes, start, end, tend, laxis);
+ refit_kdop_hull(tree, tnode, start, tend);
+ bvh_div_nodes(tree, tnode, start, tend, laxis);
+ }
+ node->totnode++;
+ }
+
+ return;
+}
+
+static void verify_tree(BVHTree *tree)
+{
+ int i, j, check = 0;
+
+ // check the pointer list
+ for(i = 0; i < tree->totleaf; i++)
+ {
+ if(tree->nodes[i]->parent == NULL)
+ printf("Leaf has no parent: %d\n", i);
+ else
+ {
+ for(j = 0; j < tree->tree_type; j++)
+ {
+ if(tree->nodes[i]->parent->children[j] == tree->nodes[i])
+ check = 1;
+ }
+ if(!check)
+ {
+ printf("Parent child relationship doesn't match: %d\n", i);
+ }
+ check = 0;
+ }
+ }
+
+ // check the leaf list
+ for(i = 0; i < tree->totleaf; i++)
+ {
+ if(tree->nodearray[i].parent == NULL)
+ printf("Leaf has no parent: %d\n", i);
+ else
+ {
+ for(j = 0; j < tree->tree_type; j++)
+ {
+ if(tree->nodearray[i].parent->children[j] == &tree->nodearray[i])
+ check = 1;
+ }
+ if(!check)
+ {
+ printf("Parent child relationship doesn't match: %d\n", i);
+ }
+ check = 0;
+ }
+ }
+
+ printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf);
+}
+
+void BLI_bvhtree_balance(BVHTree *tree)
+{
+ BVHNode *node;
+
+ if(tree->totleaf == 0)
+ return;
+
+ // create root node
+ node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]);
+ tree->totbranch++;
+
+ // refit root bvh node
+ refit_kdop_hull(tree, tree->nodes[tree->totleaf], 0, tree->totleaf);
+ // create + balance tree
+ bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf, 0);
+
+ // verify_tree(tree);
+}
+
+// overlap - is it possbile for 2 bv's to collide ?
+static int tree_overlap(float *bv1, float *bv2, int start_axis, int stop_axis)
+{
+ float *bv1_end = bv1 + (stop_axis<<1);
+
+ bv1 += start_axis<<1;
+ bv2 += start_axis<<1;
+
+ // test all axis if min + max overlap
+ for (; bv1 != bv1_end; bv1+=2, bv2+=2)
+ {
+ if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1)))
+ return 0;
+ }
+
+ return 1;
+}
+
+static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
+{
+ int j;
+
+ if(tree_overlap(node1->bv, node2->bv, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis)))
+ {
+ // check if node1 is a leaf
+ if(!node1->totnode)
+ {
+ // check if node2 is a leaf
+ if(!node2->totnode)
+ {
+
+ if(node1 == node2)
+ {
+ return;
+ }
+
+ if(data->i >= data->max_overlap)
+ {
+ // try to make alloc'ed memory bigger
+ data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap)*data->max_overlap*2);
+
+ if(!data->overlap)
+ {
+ printf("Out of Memory in traverse\n");
+ return;
+ }
+ data->max_overlap *= 2;
+ }
+
+ // both leafs, insert overlap!
+ data->overlap[data->i].indexA = node1->index;
+ data->overlap[data->i].indexB = node2->index;
+
+ data->i++;
+ }
+ else
+ {
+ for(j = 0; j < data->tree2->tree_type; j++)
+ {
+ if(node2->children[j])
+ traverse(data, node1, node2->children[j]);
+ }
+ }
+ }
+ else
+ {
+
+ for(j = 0; j < data->tree2->tree_type; j++)
+ {
+ if(node1->children[j])
+ traverse(data, node1->children[j], node2);
+ }
+ }
+ }
+ return;
+}
+
+BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result)
+{
+ int j, total = 0;
+ BVHTreeOverlap *overlap = NULL, *to = NULL;
+ BVHOverlapData **data;
+
+ // check for compatibility of both trees (can't compare 14-DOP with 18-DOP)
+ if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14))
+ return 0;
+
+ // fast check root nodes for collision before doing big splitting + traversal
+ if(!tree_overlap(tree1->nodes[tree1->totleaf]->bv, tree2->nodes[tree2->totleaf]->bv, MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis)))
+ return 0;
+
+ data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star");
+
+ for(j = 0; j < tree1->tree_type; j++)
+ {
+ data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData");
+
+ // init BVHOverlapData
+ data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap)*MAX2(tree1->totleaf, tree2->totleaf));
+ data[j]->tree1 = tree1;
+ data[j]->tree2 = tree2;
+ data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf);
+ data[j]->i = 0;
+ }
+
+#pragma omp parallel for private(j) schedule(static)
+ for(j = 0; j < MIN2(tree1->tree_type, tree1->nodes[tree1->totleaf]->totnode); j++)
+ {
+ traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
+ }
+
+ for(j = 0; j < tree1->tree_type; j++)
+ total += data[j]->i;
+
+ to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap)*total, "BVHTreeOverlap");
+
+ for(j = 0; j < tree1->tree_type; j++)
+ {
+ memcpy(to, data[j]->overlap, data[j]->i*sizeof(BVHTreeOverlap));
+ to+=data[j]->i;
+ }
+
+ for(j = 0; j < tree1->tree_type; j++)
+ {
+ free(data[j]->overlap);
+ MEM_freeN(data[j]);
+ }
+ MEM_freeN(data);
+
+ (*result) = total;
+ return overlap;
+}
+
+
+// bottom up update of bvh tree:
+// join the 4 children here
+static void node_join(BVHTree *tree, BVHNode *node)
+{
+ int i, j;
+
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ node->bv[2*i] = FLT_MAX;
+ node->bv[2*i + 1] = -FLT_MAX;
+ }
+
+ for (i = 0; i < tree->tree_type; i++)
+ {
+ if (node->children[i])
+ {
+ for (j = tree->start_axis; j < tree->stop_axis; j++)
+ {
+ // update minimum
+ if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)])
+ node->bv[(2 * j)] = node->children[i]->bv[(2 * j)];
+
+ // update maximum
+ if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1])
+ node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1];
+ }
+ }
+ else
+ break;
+ }
+}
+
+// call before BLI_bvhtree_update_tree()
+int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints)
+{
+ BVHNode *node= NULL;
+ int i = 0;
+
+ // check if index exists
+ if(index > tree->totleaf)
+ return 0;
+
+ node = tree->nodearray + index;
+
+ create_kdop_hull(tree, node, co, numpoints, 0);
+
+ if(co_moving)
+ create_kdop_hull(tree, node, co_moving, numpoints, 1);
+
+ // inflate the bv with some epsilon
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ node->bv[(2 * i)] -= tree->epsilon; // minimum
+ node->bv[(2 * i) + 1] += tree->epsilon; // maximum
+ }
+
+ return 1;
+}
+
+// call BLI_bvhtree_update_node() first for every node/point/triangle
+void BLI_bvhtree_update_tree(BVHTree *tree)
+{
+ BVHNode *leaf, *parent;
+
+ // reset tree traversing flag
+ for (leaf = tree->nodearray + tree->totleaf; leaf != tree->nodearray + tree->totleaf + tree->totbranch; leaf++)
+ leaf->traversed = 0;
+
+ for (leaf = tree->nodearray; leaf != tree->nodearray + tree->totleaf; leaf++)
+ {
+ for (parent = leaf->parent; parent; parent = parent->parent)
+ {
+ parent->traversed++; // we tried to go up in hierarchy
+ if (parent->traversed < parent->totnode)
+ break; // we do not need to check further
+ else
+ node_join(tree, parent);
+ }
+ }
+}
+
+float BLI_bvhtree_getepsilon(BVHTree *tree)
+{
+ return tree->epsilon;
+}
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index 464f97d294d..8b979f9ed23 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -150,7 +150,7 @@ void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd)
nu->type= CU_BEZIER+CU_2D;
nu->pntsu = onpoints[j];
nu->resolu= 8;
- nu->flagu= 1;
+ nu->flagu= CU_CYCLIC;
nu->bezt = bezt;
//individual curve loop, start-end
diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c
index 8cdc0601c7e..498c87cdef9 100644
--- a/source/blender/blenlib/intern/psfont.c
+++ b/source/blender/blenlib/intern/psfont.c
@@ -2017,7 +2017,7 @@ static VFontData *objfnt_to_vfontdata(objfnt *fnt)
nu->type= CU_BEZIER+CU_2D;
nu->pntsu = count;
nu->resolu= 8;
- nu->flagu= 1;
+ nu->flagu= CU_CYCLIC;
nu->bezt = bezt;
stop = 0;
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
index c85849b5ed4..848e45ccb1b 100644
--- a/source/blender/blenlib/intern/util.c
+++ b/source/blender/blenlib/intern/util.c
@@ -865,11 +865,8 @@ int BLI_strcaseeq(char *a, char *b) {
void BLI_cleanup_dir(const char *relabase, char *dir)
{
BLI_cleanup_file(relabase, dir);
-#ifdef WIN32
- strcat(dir, "\\");
-#else
- strcat(dir, "/");
-#endif
+ BLI_add_slash(dir);
+
}
void BLI_cleanup_file(const char *relabase, char *dir)
@@ -878,6 +875,13 @@ void BLI_cleanup_file(const char *relabase, char *dir)
char *start, *eind;
if (relabase) {
BLI_convertstringcode(dir, relabase);
+ } else {
+ if (dir[0]=='/' && dir[1]=='/') {
+ if (dir[2]== '\0') {
+ return; /* path is "//" - cant clean it */
+ }
+ dir = dir+2; /* skip the first // */
+ }
}
#ifdef WIN32
if(dir[0]=='.') { /* happens for example in FILE_MAIN */
@@ -1150,23 +1154,32 @@ int BLI_convertstringcode(char *path, const char *basepath)
BLI_char_switch(tmp, '\\', '/');
BLI_char_switch(base, '\\', '/');
+ /* Paths starting with // will get the blend file as their base,
+ * this isnt standard in any os but is uesed in blender all over the place */
if (tmp[0] == '/' && tmp[1] == '/') {
- char *filepart= BLI_strdup(tmp+2); /* skip code */
char *lslash= BLI_last_slash(base);
-
if (lslash) {
int baselen= (int) (lslash-base) + 1;
-
+ /* use path for for temp storage here, we copy back over it right away */
+ BLI_strncpy(path, tmp+2, FILE_MAX);
+
memcpy(tmp, base, baselen);
- strcpy(tmp+baselen, filepart);
+ strcpy(tmp+baselen, path);
+ strcpy(path, tmp);
} else {
- strcpy(tmp, filepart);
+ strcpy(path, tmp+2);
}
-
- MEM_freeN(filepart);
+ } else {
+ strcpy(path, tmp);
}
- strcpy(path, tmp);
+ if (path[0]!='\0') {
+ if ( path[strlen(path)-1]=='/') {
+ BLI_cleanup_dir(NULL, path);
+ } else {
+ BLI_cleanup_file(NULL, path);
+ }
+ }
#ifdef WIN32
/* skip first two chars, which in case of
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1cb8b10b087..7d0dd9e41c1 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -3108,7 +3108,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
- collmd->bvh = NULL;
+ collmd->bvhtree = NULL;
collmd->mfaces = NULL;
}
diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript
index f9e46b20d9a..7349f481731 100644
--- a/source/blender/imbuf/SConscript
+++ b/source/blender/imbuf/SConscript
@@ -27,6 +27,14 @@ if env['WITH_BF_FFMPEG'] == 1:
defs.append('WITH_FFMPEG')
incs += ' ' + env['BF_FFMPEG_INC']
+if env['WITH_BF_OPENJPEG'] == 1:
+ defs.append('WITH_OPENJPEG')
+ incs += ' ' + env['BF_OPENJPEG_INC']
+
+if env['WITH_BF_REDCODE'] == 1:
+ defs.append('WITH_REDCODE')
+ incs += ' ' + env['BF_REDCODE_INC']
+
if env['WITH_BF_QUICKTIME']==1:
incs += ' ' + env['BF_QUICKTIME_INC']
defs.append('WITH_QUICKTIME')
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index 4948ff11b4a..71d35949833 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -81,6 +81,10 @@
#include <ffmpeg/swscale.h>
#endif
+#ifdef WITH_REDCODE
+#include <redcode/format.h>
+#endif
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -116,6 +120,7 @@
#define ANIM_AVI (1 << 6)
#define ANIM_QTIME (1 << 7)
#define ANIM_FFMPEG (1 << 8)
+#define ANIM_REDCODE (1 << 9)
#define ANIM5_MMAP 0
#define ANIM5_MALLOC 1
@@ -184,6 +189,9 @@ struct anim {
int videoStream;
#endif
+#ifdef WITH_REDCODE
+ struct redcode_handle * redcodeCtx;
+#endif
};
#endif
diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c
index d2743b680d8..87d67f5263b 100644
--- a/source/blender/imbuf/intern/anim.c
+++ b/source/blender/imbuf/intern/anim.c
@@ -96,6 +96,11 @@
#endif
+#ifdef WITH_REDCODE
+#include <redcode/format.h>
+#include <redcode/codec.h>
+#endif
+
/****/
#ifdef __sgi
@@ -307,6 +312,9 @@ void IMB_free_anim_ibuf(struct anim * anim) {
#ifdef WITH_FFMPEG
static void free_anim_ffmpeg(struct anim * anim);
#endif
+#ifdef WITH_REDCODE
+static void free_anim_redcode(struct anim * anim);
+#endif
void IMB_free_anim(struct anim * anim) {
if (anim == NULL) {
@@ -325,6 +333,9 @@ void IMB_free_anim(struct anim * anim) {
#ifdef WITH_FFMPEG
free_anim_ffmpeg(anim);
#endif
+#ifdef WITH_REDCODE
+ free_anim_redcode(anim);
+#endif
free(anim);
}
@@ -830,6 +841,58 @@ static void free_anim_ffmpeg(struct anim * anim) {
#endif
+#ifdef WITH_REDCODE
+
+static int startredcode(struct anim * anim) {
+ anim->redcodeCtx = redcode_open(anim->name);
+ if (!anim->redcodeCtx) {
+ return -1;
+ }
+ anim->duration = redcode_get_length(anim->redcodeCtx);
+
+ return 0;
+}
+
+static ImBuf * redcode_fetchibuf(struct anim * anim, int position) {
+ struct ImBuf * ibuf;
+ struct redcode_frame * frame;
+ struct redcode_frame_raw * raw_frame;
+
+ if (!anim->redcodeCtx) {
+ return NULL;
+ }
+
+ frame = redcode_read_video_frame(anim->redcodeCtx, position);
+
+ if (!frame) {
+ return NULL;
+ }
+
+ raw_frame = redcode_decode_video_raw(frame, 1);
+
+ redcode_free_frame(frame);
+
+ if (!raw_frame) {
+ return NULL;
+ }
+
+ ibuf = IMB_allocImBuf(raw_frame->width * 2,
+ raw_frame->height * 2, 32, IB_rectfloat, 0);
+
+ redcode_decode_video_float(raw_frame, ibuf->rect_float, 1);
+
+ return ibuf;
+}
+
+static void free_anim_redcode(struct anim * anim) {
+ if (anim->redcodeCtx) {
+ redcode_close(anim->redcodeCtx);
+ anim->redcodeCtx = 0;
+ }
+ anim->duration = 0;
+}
+
+#endif
/* probeer volgende plaatje te lezen */
/* Geen plaatje, probeer dan volgende animatie te openen */
@@ -849,6 +912,10 @@ static struct ImBuf * anim_getnew(struct anim * anim) {
#ifdef WITH_FFMPEG
free_anim_ffmpeg(anim);
#endif
+#ifdef WITH_REDCODE
+ free_anim_redcode(anim);
+#endif
+
if (anim->curtype != 0) return (0);
anim->curtype = imb_get_anim_type(anim->name);
@@ -888,8 +955,13 @@ static struct ImBuf * anim_getnew(struct anim * anim) {
ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0, 0);
break;
#endif
+#ifdef WITH_REDCODE
+ case ANIM_REDCODE:
+ if (startredcode(anim)) return (0);
+ ibuf = IMB_allocImBuf (8, 8, 32, 0, 0);
+ break;
+#endif
}
-
return(ibuf);
}
@@ -970,6 +1042,12 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) {
if (ibuf) anim->curposition = position;
break;
#endif
+#ifdef WITH_REDCODE
+ case ANIM_REDCODE:
+ ibuf = redcode_fetchibuf(anim, position);
+ if (ibuf) anim->curposition = position;
+ break;
+#endif
}
if (ibuf) {
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 632a471ecd0..4f6730db1f1 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -321,6 +321,19 @@ static int isffmpeg (char *filename) {
}
#endif
+#ifdef WITH_REDCODE
+static int isredcode(char * filename)
+{
+ struct redcode_handle * h = redcode_open(filename);
+ if (!h) {
+ return 0;
+ }
+ redcode_close(h);
+ return 1;
+}
+
+#endif
+
int imb_get_anim_type(char * name) {
int type;
struct stat st;
@@ -355,6 +368,9 @@ int imb_get_anim_type(char * name) {
if (isffmpeg(name)) return (ANIM_FFMPEG);
# endif
#endif
+#ifdef WITH_REDCODE
+ if (isredcode(name)) return (ANIM_REDCODE);
+#endif
type = IMB_ispic(name);
if (type == ANIM) return (ANIM_ANIM5);
if (type) return(ANIM_SEQUENCE);
@@ -369,6 +385,7 @@ int IMB_isanim(char *filename) {
if( BLI_testextensie(filename, ".avi")
|| BLI_testextensie(filename, ".flc")
|| BLI_testextensie(filename, ".dv")
+ || BLI_testextensie(filename, ".r3d")
|| BLI_testextensie(filename, ".mov")
|| BLI_testextensie(filename, ".movie")
|| BLI_testextensie(filename, ".mv")) {
@@ -379,6 +396,7 @@ int IMB_isanim(char *filename) {
} else { // no quicktime
if( BLI_testextensie(filename, ".avi")
|| BLI_testextensie(filename, ".dv")
+ || BLI_testextensie(filename, ".r3d")
|| BLI_testextensie(filename, ".mv")) {
type = imb_get_anim_type(filename);
}
diff --git a/source/blender/include/BDR_editcurve.h b/source/blender/include/BDR_editcurve.h
index 9e25550ce04..4604359fcc9 100644
--- a/source/blender/include/BDR_editcurve.h
+++ b/source/blender/include/BDR_editcurve.h
@@ -37,6 +37,9 @@ struct BezTriple;
struct BPoint;
struct BezTripleNurb;
+void set_actNurb(struct Nurb *nu);
+struct Nurb * get_actNurb( void );
+
short isNurbsel(struct Nurb *nu);
int isNurbsel_count(struct Nurb *nu);
void printknots(void);
diff --git a/source/blender/include/BIF_editseq.h b/source/blender/include/BIF_editseq.h
index 0d1e792eb1c..b353e7bb45c 100644
--- a/source/blender/include/BIF_editseq.h
+++ b/source/blender/include/BIF_editseq.h
@@ -92,8 +92,8 @@ start and end are from the start and fixed length of the sequence.
int seq_tx_get_start(struct Sequence *seq);
int seq_tx_get_end(struct Sequence *seq);
-int seq_tx_get_final_left(struct Sequence *seq);
-int seq_tx_get_final_right(struct Sequence *seq);
+int seq_tx_get_final_left(struct Sequence *seq, int metaclip);
+int seq_tx_get_final_right(struct Sequence *seq, int metaclip);
void seq_tx_set_final_left(struct Sequence *seq, int i);
void seq_tx_set_final_right(struct Sequence *seq, int i);
diff --git a/source/blender/include/BSE_view.h b/source/blender/include/BSE_view.h
index 236f35f17c6..4b334fdd959 100644
--- a/source/blender/include/BSE_view.h
+++ b/source/blender/include/BSE_view.h
@@ -63,7 +63,9 @@ void window_to_3d(float *vec, short mx, short my);
void project_short(float *vec, short *adr);
void project_short_noclip(float *vec, short *adr);
void project_int(float *vec, int *adr);
+void project_int_noclip(float *vec, int *adr);
void project_float(float *vec, float *adr);
+void project_float_noclip(float *vec, float *adr);
int boundbox_clip(float obmat[][4], struct BoundBox *bb);
void fdrawline(float x1, float y1, float x2, float y2);
diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h
index 982a2f25df7..82adb1ac12a 100644
--- a/source/blender/include/transform.h
+++ b/source/blender/include/transform.h
@@ -515,6 +515,7 @@ int handleNDofInput(NDofInput *n, unsigned short event, short val);
int manageObjectSpace(int confirm, int set);
int manageMeshSpace(int confirm, int set);
+int manageBoneSpace(int confirm, int set);
/* Those two fill in mat and return non-zero on success */
int createSpaceNormal(float mat[3][3], float normal[3]);
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 61a8fc6649c..85bbb2fbaa7 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -391,7 +391,7 @@ typedef struct CollisionModifierData {
unsigned int numfaces;
int pad;
float time; /* cfra time of modifier */
- struct BVH *bvh; /* bounding volume hierarchy for this cloth object */
+ struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
} CollisionModifierData;
typedef enum {
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 7b1b979b777..aae8a697cbe 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -274,7 +274,7 @@ typedef struct RenderData {
/* Bake Render options */
short bake_osa, bake_filter, bake_mode, bake_flag;
- short bake_normal_space, bpad;
+ short bake_normal_space, bake_quad_split;
float bake_maxdist, bake_biasdist, bake_pad;
/* yafray: global panel params. TODO: move elsewhere */
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 9b837f9f988..83f4e633fa1 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -688,18 +688,18 @@ static int calculate_structlens(int firststruct)
/* 4-8 aligned/ */
if(sizeof(void *) == 4) {
if (len % 4) {
- printf("Align pointer error in struct: %s %s\n", types[structtype], cp);
+ printf("Align pointer error in struct (len4): %s %s\n", types[structtype], cp);
dna_error = 1;
}
} else {
if (len % 8) {
- printf("Align pointer error in struct: %s %s\n", types[structtype], cp);
+ printf("Align pointer error in struct (len8): %s %s\n", types[structtype], cp);
dna_error = 1;
}
}
if (alphalen % 8) {
- printf("Align pointer error in struct: %s %s\n", types[structtype],cp);
+ printf("Align pointer error in struct (alphalen8): %s %s\n", types[structtype],cp);
dna_error = 1;
}
@@ -748,13 +748,13 @@ static int calculate_structlens(int firststruct)
// has_pointer is set or alphalen != len
if (has_pointer || alphalen != len) {
if (alphalen % 8) {
- printf("Sizeerror in struct: %s (add %d bytes)\n", types[structtype], alphalen%8);
+ printf("Sizeerror 8 in struct: %s (add %d bytes)\n", types[structtype], alphalen%8);
dna_error = 1;
}
}
if(len % 4) {
- printf("Sizeerror in struct: %s (add %d bytes)\n", types[structtype], len%4);
+ printf("Sizeerror 4 in struct: %s (add %d bytes)\n", types[structtype], len%4);
dna_error = 1;
}
diff --git a/source/blender/nodes/intern/Makefile b/source/blender/nodes/intern/Makefile
index 12b3616df25..7cf2411ed84 100644
--- a/source/blender/nodes/intern/Makefile
+++ b/source/blender/nodes/intern/Makefile
@@ -35,8 +35,6 @@ include nan_compile.mk
CFLAGS += $(LEVEL_1_C_WARNINGS)
-CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
-CPPFLAGS += -I../../python
CPPFLAGS += -I../../blenkernel
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I../../makesdna
diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c
index 257203908b1..7c23c86d9ba 100644
--- a/source/blender/python/BPY_interface.c
+++ b/source/blender/python/BPY_interface.c
@@ -1259,15 +1259,16 @@ static int bpy_pydriver_create_dict(void)
/* If there's a Blender text called pydrivers.py, import it.
* Users can add their own functions to this module. */
- mod = importText("pydrivers"); /* can also use PyImport_Import() */
- if (mod) {
- PyDict_SetItemString(d, "pydrivers", mod);
- PyDict_SetItemString(d, "p", mod);
- Py_DECREF(mod);
+ if (G.f&G_DOSCRIPTLINKS) {
+ mod = importText("pydrivers"); /* can also use PyImport_Import() */
+ if (mod) {
+ PyDict_SetItemString(d, "pydrivers", mod);
+ PyDict_SetItemString(d, "p", mod);
+ Py_DECREF(mod);
+ } else {
+ PyErr_Clear();
+ }
}
- else
- PyErr_Clear();
-
/* short aliases for some Get() functions: */
/* ob(obname) == Blender.Object.Get(obname) */
@@ -1998,7 +1999,7 @@ float BPY_pydriver_eval(IpoDriver *driver)
int setitem_retval;
PyGILState_STATE gilstate;
- if (!driver) return result;
+ if (!driver || (G.f&G_DOSCRIPTLINKS)==0) return result;
expr = driver->name; /* the py expression to be evaluated */
if (!expr || expr[0]=='\0') return result;
@@ -2103,7 +2104,7 @@ int BPY_button_eval(char *expr, double *value)
if (!bpy_pydriver_Dict) {
if (bpy_pydriver_create_dict() != 0) {
fprintf(stderr,
- "Button Python Eval error: couldn't create Python dictionary");
+ "Button Python Eval error: couldn't create Python dictionary \n");
PyGILState_Release(gilstate);
return -1;
}
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index 6fce0864189..6b2e00f27de 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -952,7 +952,7 @@ static PyObject *Blender_GetPaths( PyObject * self, PyObject *args, PyObject *ke
if (absolute) {
BLI_bpathIterator_getPathExpanded( &bpi, filepath_expanded );
} else {
- BLI_bpathIterator_getPathExpanded( &bpi, filepath_expanded );
+ BLI_bpathIterator_getPath( &bpi, filepath_expanded );
}
st = PyString_FromString(filepath_expanded);
diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c
index 3d4546613be..047a035fb8b 100644
--- a/source/blender/python/api2_2x/Draw.c
+++ b/source/blender/python/api2_2x/Draw.c
@@ -613,6 +613,8 @@ static void exit_pydraw( SpaceScript * sc, short err )
PyErr_Print( );
script->flags = 0; /* mark script struct for deletion */
SCRIPT_SET_NULL(script);
+ script->scriptname[0] = '\0';
+ script->scriptarg[0] = '\0';
error_pyscript();
scrarea_queue_redraw( sc->area );
}
diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c
index 818c58109f3..c36213950b0 100644
--- a/source/blender/python/api2_2x/Material.c
+++ b/source/blender/python/api2_2x/Material.c
@@ -1179,7 +1179,7 @@ static PyGetSetDef BPy_Material_getseters[] = {
{"sssRadiusBlue",
(getter)Material_getSssRadius, (setter)Material_setSssRadius,
"Mean red scattering path length",
- (void *) 0},
+ (void *) 2},
{"sssIOR",
(getter)Material_getSssIOR, (setter)Material_setSssIOR,
"index of refraction",
@@ -1196,7 +1196,7 @@ static PyGetSetDef BPy_Material_getseters[] = {
(getter)Material_getSssTexScatter, (setter)Material_setSssTexScatter,
"Texture scattering factor",
NULL},
- {"sssFont",
+ {"sssFront",
(getter)Material_getSssFront, (setter)Material_setSssFront,
"Front scattering weight",
NULL},
diff --git a/source/blender/python/api2_2x/Node.c b/source/blender/python/api2_2x/Node.c
index 92529023b7e..792b2331508 100644
--- a/source/blender/python/api2_2x/Node.c
+++ b/source/blender/python/api2_2x/Node.c
@@ -848,7 +848,7 @@ static int Sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObj
if (PyInt_Check(pyidx)) {
idx = (int)PyInt_AsLong(pyidx);
- if (idx < 0 || idx >= Sockinmap_len(self))
+ if (idx < 0 || idx >= Sockoutmap_len(self))
return EXPP_ReturnIntError(PyExc_IndexError, "index out of range");
}
else if (PyString_Check(pyidx)) {
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index 82f99adcdb1..3db9664d47d 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -341,6 +341,7 @@ static int setupPI(Object* ob);
static PyObject *Object_getParticleSys( BPy_Object * self );
/* fixme Object_newParticleSys( self, default-partsys-name ) */
+static PyObject *Object_addVertexGroupsFromArmature( BPy_Object * self, PyObject * args);
static PyObject *Object_newParticleSys( BPy_Object * self );
static PyObject *Object_buildParts( BPy_Object * self );
static PyObject *Object_clearIpo( BPy_Object * self );
@@ -359,6 +360,8 @@ static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args );
static PyObject *Object_getParent( BPy_Object * self );
static PyObject *Object_getParentBoneName( BPy_Object * self );
static int Object_setParentBoneName( BPy_Object * self, PyObject * value );
+static PyObject *Object_getParentVertexIndex( BPy_Object * self );
+static int Object_setParentVertexIndex( BPy_Object * self, PyObject * value );
static PyObject *Object_getSize( BPy_Object * self, PyObject * args );
static PyObject *Object_getTimeOffset( BPy_Object * self );
static PyObject *Object_getTracked( BPy_Object * self );
@@ -475,6 +478,8 @@ static PyMethodDef BPy_Object_methods[] = {
"Return a list of particle systems"},
{"newParticleSystem", ( PyCFunction ) Object_newParticleSys, METH_NOARGS,
"Create and link a new particle system"},
+ {"addVertexGroupsFromArmature" , ( PyCFunction ) Object_addVertexGroupsFromArmature, METH_VARARGS,
+ "Add vertex groups from armature using the bone heat method"},
{"buildParts", ( PyCFunction ) Object_buildParts, METH_NOARGS,
"Recalcs particle system (if any), (depricated, will always return an empty list in version 2.46)"},
{"getIpo", ( PyCFunction ) Object_getIpo, METH_NOARGS,
@@ -1109,6 +1114,42 @@ PyObject *Object_newParticleSys( BPy_Object * self ){
return ParticleSys_CreatePyObject(rpsys,ob);
}
+/*****************************************************************************/
+/* attribute: addVertexGroupsFromArmature */
+/* Description: evaluate and add vertex groups to the current object */
+/* for each bone of the selected armature */
+/* Data: self Object, Bpy armature */
+/* Return: nothing */
+/*****************************************************************************/
+static PyObject *Object_addVertexGroupsFromArmature( BPy_Object * self, PyObject * args)
+{
+
+ Object *ob = self->object;
+ BPy_Object *arm;
+
+ if( ob->type != OB_MESH )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "Only useable on Mesh type Objects" );
+
+ if( G.obedit != NULL)
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "Not useable when inside edit mode" );
+
+ /* Check if the arguments passed to makeParent are valid. */
+ if( !PyArg_ParseTuple( args, "O!",&Object_Type, &arm ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "An armature object is expected." );
+
+ if( arm->object->type != OB_ARMATURE )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "An armature object is expected." );
+
+ add_verts_to_dgroups(ob, arm->object, 1, 0);
+ ob->recalc |= OB_RECALC_OB;
+
+ Py_RETURN_NONE;
+}
+
static PyObject *Object_buildParts( BPy_Object * self )
{
/* This is now handles by modifiers */
@@ -1452,6 +1493,92 @@ static int Object_setParentBoneName( BPy_Object * self, PyObject *value )
return 0;
}
+static PyObject *Object_getParentVertexIndex( BPy_Object * self )
+{
+ PyObject *pyls = NULL;
+
+ if( self->object->parent) {
+ if (self->object->partype==PARVERT1) {
+ pyls = PyList_New(1);
+ PyList_SET_ITEM( pyls, 0, PyInt_FromLong( self->object->par1 ));
+ return pyls;
+ } else if (self->object->partype==PARVERT3) {
+ pyls = PyList_New(3);
+ PyList_SET_ITEM( pyls, 0, PyInt_FromLong( self->object->par1 ));
+ PyList_SET_ITEM( pyls, 1, PyInt_FromLong( self->object->par2 ));
+ PyList_SET_ITEM( pyls, 2, PyInt_FromLong( self->object->par3 ));
+ return pyls;
+ }
+ }
+ return PyList_New(0);
+}
+
+static int Object_setParentVertexIndex( BPy_Object * self, PyObject *value )
+{
+ PyObject *item;
+ int val[3] = {0,0,0};
+ if( !self->object->parent) {
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "This object has no vertex parent, cant set the vertex parent indicies" );
+ }
+ if (self->object->partype==PARVERT1) {
+ if (PySequence_Length(value) != 1)
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "Vertex parented to 1 vertex, can only assign a sequence with 1 vertex parent index" );
+ item = PySequence_GetItem(value, 0);
+ if (item) {
+ val[0] = PyInt_AsLong(item);
+ Py_DECREF(item);
+ }
+ } else if (self->object->partype==PARVERT3) {
+ int i;
+ if (PySequence_Length(value) != 3)
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "Vertex parented to 3 verts, can only assign a sequence with 3 verts parent index" );
+
+ for (i=0; i<3; i++) {
+ item = PySequence_GetItem(value, i);
+ if (item) {
+ val[i] = PyInt_AsLong(item);
+ Py_DECREF(item);
+ }
+ }
+ } else {
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "This object has no vertex parent, cant set the vertex parent indicies" );
+ }
+
+ if (PyErr_Occurred()) {
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "This object has no vertex parent, cant set the vertex parent indicies" );
+ } else {
+ if (self->object->partype==PARVERT1) {
+ if (val[0] < 0) {
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "vertex index less then zero" );
+ }
+
+ self->object->par1 = val[0];
+ } else if (self->object->partype==PARVERT3) {
+ if (val[0]==val[1] || val[0]==val[2] || val[1]==val[2]) {
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "duplicate indicies in vertex parent assignment" );
+ }
+ if (val[0] < 0 || val[1] < 0 || val[2] < 0) {
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "vertex index less then zero" );
+ }
+
+ self->object->par1 = val[0];
+ self->object->par2 = val[1];
+ self->object->par3 = val[2];
+ }
+ }
+
+ return 0;
+}
+
+
static PyObject *Object_getSize( BPy_Object * self, PyObject * args )
{
char *space = "localspace"; /* default to local */
@@ -4877,6 +5004,10 @@ static PyGetSetDef BPy_Object_getseters[] = {
(getter)Object_getParentBoneName, (setter)Object_setParentBoneName,
"The object's parent object's sub name",
NULL},
+ {"parentVertexIndex",
+ (getter)Object_getParentVertexIndex, (setter)Object_setParentVertexIndex,
+ "Indicies used for vertex parents",
+ NULL},
{"track",
(getter)Object_getTracked, (setter)Object_setTracked,
"The object's tracked object",
diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c
index 15307cc2be5..f0a32db0623 100644
--- a/source/blender/python/api2_2x/Particle.c
+++ b/source/blender/python/api2_2x/Particle.c
@@ -828,7 +828,7 @@ static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ){
/* little hack to calculate hair steps in render mode */
psys->renderdata = (void*)(int)1;
- psys_cache_paths(ob, psys, cfra, 0);
+ psys_cache_paths(ob, psys, cfra, 1);
psys->renderdata = NULL;
diff --git a/source/blender/python/api2_2x/Scene.c b/source/blender/python/api2_2x/Scene.c
index 7ef351b1127..eba951b8813 100644
--- a/source/blender/python/api2_2x/Scene.c
+++ b/source/blender/python/api2_2x/Scene.c
@@ -1355,16 +1355,29 @@ static PyObject *SceneObSeq_item( BPy_SceneObSeq * self, int i )
for (base= scene->base.first; base && i!=index; base= base->next, index++) {}
/* selected */
else if (self->mode==EXPP_OBSEQ_SELECTED) {
- for (base= scene->base.first; base && i!=index; base= base->next)
- if (base->flag & SELECT)
- index++;
+ for (base= scene->base.first; base; base= base->next) {
+ if (base->flag & SELECT) {
+ if (i==index) {
+ break;
+ } else {
+ index++;
+ }
+ }
+ }
}
/* context */
else if (self->mode==EXPP_OBSEQ_CONTEXT) {
- if (G.vd)
- for (base= scene->base.first; base && i!=index; base= base->next)
- if TESTBASE(base)
- index++;
+ if (G.vd) {
+ for (base= scene->base.first; base; base= base->next) {
+ if (TESTBASE(base)) {
+ if (i==index) {
+ break;
+ } else {
+ index++;
+ }
+ }
+ }
+ }
}
if (!(base))
diff --git a/source/blender/python/api2_2x/Sys.c b/source/blender/python/api2_2x/Sys.c
index 3863cc12227..baae2220143 100644
--- a/source/blender/python/api2_2x/Sys.c
+++ b/source/blender/python/api2_2x/Sys.c
@@ -406,11 +406,12 @@ static PyObject *M_sys_cleanpath( PyObject * self, PyObject * value )
{
char *path = PyString_AsString(value);
char cleaned[FILE_MAXDIR + FILE_MAXFILE];
- int trailing_slash = 0;
+ int trailing_slash = 0, last;
if (!path)
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected string argument" );
- if (strstr(path, "/") || strstr(path, "\\")) {
+ last = strlen(path)-1;
+ if ((last >= 0) && ((path[last]=='/') || (path[last]=='\\'))) {
trailing_slash = 1;
}
BLI_strncpy(cleaned, path, FILE_MAXDIR + FILE_MAXFILE);
diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py
index 521be3b0cea..2e4850aeb14 100644
--- a/source/blender/python/api2_2x/doc/Object.py
+++ b/source/blender/python/api2_2x/doc/Object.py
@@ -389,6 +389,8 @@ class Object:
@ivar parentbonename: The string name of the parent bone (if defined).
This can be set to another bone in the armature if the object already has a bone parent.
@type parentbonename: string or None
+ @ivar parentVertexIndex: A list of vertex parent indicies, with a length of 0, 1 or 3. When there are 1 or 3 vertex parents, the indicies can be assigned to a sequence of the same length.
+ @type parentVertexIndex: list
@ivar protectFlags: The "transform locking" bitfield flags for the object.
See L{ProtectFlags} const dict for values.
@type protectFlags: int
@@ -651,6 +653,13 @@ class Object:
Link a new particle system (see Blender.Particle).
"""
+ def addVertexGroupsFromArmature(object):
+ """
+ Add vertex groups from armature using the bone heat method
+ This method can be only used with an Object of the type Mesh when NOT in edit mode.
+ @type object: a bpy armature
+ """
+
def buildParts():
"""
Recomputes the particle system. This method only applies to an Object of
diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c
index f54c2cd4e3b..b446af7efd4 100644
--- a/source/blender/python/api2_2x/sceneRender.c
+++ b/source/blender/python/api2_2x/sceneRender.c
@@ -478,9 +478,11 @@ PyObject *RenderData_Render( BPy_RenderData * self )
}
else { /* background mode (blender -b file.blend -P script) */
- Render *re= RE_NewRender("Render");
+ Render *re= RE_NewRender(G.scene->id.name);
- int end_frame = G.scene->r.efra; /* is of type short currently */
+
+
+ int end_frame = G.scene->r.efra;
if (G.scene != self->scene)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
@@ -490,7 +492,7 @@ PyObject *RenderData_Render( BPy_RenderData * self )
RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra);
- G.scene->r.efra = (short)end_frame;
+ G.scene->r.efra = end_frame;
}
Py_RETURN_NONE;
@@ -571,7 +573,7 @@ PyObject *RenderData_RenderAnim( BPy_RenderData * self )
set_scene( oldsce );
}
else { /* background mode (blender -b file.blend -P script) */
- Render *re= RE_NewRender("Render");
+ Render *re= RE_NewRender(G.scene->id.name);
if (G.scene != self->scene)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
@@ -2046,7 +2048,7 @@ static int RenderData_setIValueAttrClamp( BPy_RenderData *self, PyObject *value,
break;
case EXPP_RENDER_ATTR_BAKEMODE:
min = RE_BAKE_LIGHT;
- max = RE_BAKE_DISPLACEMENT;
+ max = RE_BAKE_SHADOW;
size = 'h';
param = &self->renderContext->bake_mode;
break;
@@ -3779,6 +3781,7 @@ static PyObject *M_Render_BakeModesDict( void )
PyConstant_Insert( d, "NORMALS", PyInt_FromLong( RE_BAKE_NORMALS ) );
PyConstant_Insert( d, "TEXTURE", PyInt_FromLong( RE_BAKE_TEXTURE ) );
PyConstant_Insert( d, "DISPLACEMENT", PyInt_FromLong( RE_BAKE_DISPLACEMENT ) );
+ PyConstant_Insert( d, "SHADOW", PyInt_FromLong( RE_BAKE_SHADOW ) );
}
return M;
}
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 66dc1dd5fef..64cf7fcb37b 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -220,6 +220,8 @@ void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize,
#define RE_BAKE_NORMALS 3
#define RE_BAKE_TEXTURE 4
#define RE_BAKE_DISPLACEMENT 5
+#define RE_BAKE_SHADOW 6
+
void RE_Database_Baking(struct Render *re, struct Scene *scene, int type, struct Object *actob);
void RE_DataBase_GetView(struct Render *re, float mat[][4]);
diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h
index aec1c69b3dc..8f429f7dd90 100644
--- a/source/blender/render/extern/include/RE_raytrace.h
+++ b/source/blender/render/extern/include/RE_raytrace.h
@@ -70,7 +70,7 @@ typedef struct Isect {
int ob_last;
short isect; /* which half of quad */
- short mode; /* RE_RAYSHADOW, RE_RAYMIRROR, RE_RAYSHADOW_TRA */
+ short mode; /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */
int lay; /* -1 default, set for layer lamps */
/* only used externally */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index d7e71b3e531..8414b6aefe3 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -499,6 +499,7 @@ typedef struct LampRen {
#define R_NEED_TANGENT 32
#define R_SKIP_MULTIRES 64
#define R_BAKE_TRACE 128
+#define R_BAKING 256
/* vlakren->flag (vlak = face in dutch) char!!! */
#define R_SMOOTH 1
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index dbade68ba1d..afe4c47a9a4 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -3935,7 +3935,7 @@ static void set_fullsample_flag(Render *re, ObjectRen *obr)
}
}
-static void check_non_flat_quads(ObjectRen *obr)
+static void check_non_flat_quads(ObjectRen *obr, int quad_flip)
{
VlakRen *vlr, *vlr1;
VertRen *v1, *v2, *v3, *v4;
@@ -3997,20 +3997,27 @@ static void check_non_flat_quads(ObjectRen *obr)
xn= nor[0]*vlr->n[0] + nor[1]*vlr->n[1] + nor[2]*vlr->n[2];
if(ABS(xn) < 0.999995 ) { // checked on noisy fractal grid
+
float d1, d2;
vlr1= RE_vlakren_copy(obr, vlr);
vlr1->flag |= R_FACE_SPLIT;
- /* split direction based on vnorms */
- CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, nor);
- d1= nor[0]*vlr->v1->n[0] + nor[1]*vlr->v1->n[1] + nor[2]*vlr->v1->n[2];
+ if (quad_flip==0) { /* nonzero quad_flip is used to force dividing one way */
+ /* split direction based on vnorms */
+ CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, nor);
+ d1= nor[0]*vlr->v1->n[0] + nor[1]*vlr->v1->n[1] + nor[2]*vlr->v1->n[2];
- CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, nor);
- d2= nor[0]*vlr->v2->n[0] + nor[1]*vlr->v2->n[1] + nor[2]*vlr->v2->n[2];
+ CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, nor);
+ d2= nor[0]*vlr->v2->n[0] + nor[1]*vlr->v2->n[1] + nor[2]*vlr->v2->n[2];
- if( fabs(d1) < fabs(d2) ) vlr->flag |= R_DIVIDE_24;
- else vlr->flag &= ~R_DIVIDE_24;
+ if( fabs(d1) < fabs(d2) ) vlr->flag |= R_DIVIDE_24;
+ else vlr->flag &= ~R_DIVIDE_24;
+ } else if (quad_flip==1) {
+ vlr->flag &= ~R_DIVIDE_24;
+ } else { /* quad_flip == 3 */
+ vlr->flag |= R_DIVIDE_24;
+ }
/* new vertex pointers */
if (vlr->flag & R_DIVIDE_24) {
@@ -4064,8 +4071,14 @@ static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset)
ob->smoothresh= 0.0;
if((re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW))
set_phong_threshold(obr);
-
- check_non_flat_quads(obr);
+
+ if (re->flag & R_BAKING) {
+ /* Baking lets us define a quad split order */
+ check_non_flat_quads(obr, re->r.bake_quad_split);
+ } else {
+ check_non_flat_quads(obr, 0);
+ }
+
set_fullsample_flag(re, obr);
/* compute bounding boxes for clipping */
@@ -5406,6 +5419,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
RE_BAKE_AO: for baking, no lamps, but all objects
RE_BAKE_TEXTURE:for baking, no lamps, only selected objects
RE_BAKE_DISPLACEMENT:for baking, no lamps, only selected objects
+ RE_BAKE_SHADOW: for baking, only shadows, but all objects
*/
void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
{
@@ -5421,6 +5435,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
RE_init_threadcount(re);
re->flag |= R_GLOB_NOPUNOFLIP;
+ re->flag |= R_BAKING;
re->excludeob= actob;
if(type == RE_BAKE_LIGHT)
re->flag |= R_SKIP_MULTIRES;
@@ -5435,6 +5450,10 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
re->r.mode &= ~R_RAYTRACE;
}
+ if(!actob && (type==RE_BAKE_SHADOW)) {
+ re->r.mode |= R_SHADOW;
+ }
+
/* setup render stuff */
re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
@@ -5472,7 +5491,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
set_node_shader_lamp_loop(shade_material_loop);
/* MAKE RENDER DATA */
- nolamps= !ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL);
+ nolamps= !ELEM3(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW);
onlyselected= ELEM3(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT);
database_init_objects(re, lay, nolamps, onlyselected, actob, 0);
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 73db5c4b0be..aa4e40739da 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -241,7 +241,7 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode)
/* append or set matrix depending on dupli */
if(obi->flag & R_DUPLI_TRANSFORMED) {
Mat4CpyMat4(tmpmat, obi->mat);
- Mat4MulMat4(obi->mat, tmat, tmpmat);
+ Mat4MulMat4(obi->mat, tmpmat, tmat);
}
else if(mode==1)
Mat4CpyMat4(obi->mat, tmat);
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index fb699f5b382..ebb52c49132 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -993,6 +993,7 @@ RenderStats *RE_GetStats(Render *re)
return &re->i;
}
+/* Note, when rendering from a scene, ALWAYS use G.scene->id.name, else compositing wont work */
Render *RE_NewRender(const char *name)
{
Render *re;
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 8fd07001bd1..1155d2ea817 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -1473,14 +1473,15 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys)
int tot;
float *vec;
- if(resol>16) resol= 16;
-
tot= 2*resol*resol;
if (type & WO_AORNDSMP) {
- static float sphere[2*3*256];
+ float *sphere;
int a;
+ // always returns table
+ sphere= threadsafe_table_sphere(0, thread, xs, ys, tot);
+
/* total random sampling. NOT THREADSAFE! (should be removed, is not useful) */
vec= sphere;
for (a=0; a<tot; a++, vec+=3) {
@@ -1495,7 +1496,8 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys)
float ang, *vec1;
int a;
- sphere= threadsafe_table_sphere(1, thread, xs, ys, tot); // returns table if xs and ys were equal to last call
+ // returns table if xs and ys were equal to last call
+ sphere= threadsafe_table_sphere(1, thread, xs, ys, tot);
if(sphere==NULL) {
sphere= threadsafe_table_sphere(0, thread, xs, ys, tot);
@@ -1663,7 +1665,7 @@ void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
float *vec, *nrm, div, bias, sh=0.0f;
float maxdist = R.wrld.aodist;
float dxyview[3];
- int j= -1, tot, actual=0, skyadded=0, aocolor;
+ int j= -1, tot, actual=0, skyadded=0, aocolor, resol= R.wrld.aosamp;
isec.faceorig= (RayFace*)shi->vlr;
isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
@@ -1690,14 +1692,16 @@ void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
if(shi->mat->mode & MA_ONLYSHADOW)
aocolor= WO_AOPLAIN;
- vec= sphere_sampler(R.wrld.aomode, R.wrld.aosamp, shi->thread, shi->xs, shi->ys);
+ if(resol>32) resol= 32;
+
+ vec= sphere_sampler(R.wrld.aomode, resol, shi->thread, shi->xs, shi->ys);
// warning: since we use full sphere now, and dotproduct is below, we do twice as much
- tot= 2*R.wrld.aosamp*R.wrld.aosamp;
+ tot= 2*resol*resol;
if(aocolor == WO_AOSKYTEX) {
- dxyview[0]= 1.0f/(float)R.wrld.aosamp;
- dxyview[1]= 1.0f/(float)R.wrld.aosamp;
+ dxyview[0]= 1.0f/(float)resol;
+ dxyview[1]= 1.0f/(float)resol;
dxyview[2]= 0.0f;
}
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index ff31ba8a6ee..dae7b0dcd88 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -2017,9 +2017,12 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
ambient_occlusion_to_diffuse(shi, shr.combined);
}
else {
+ if (bs->type==RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
+ shi->r = shi->g = shi->b = 1.0f;
+
shade_input_set_shade_texco(shi);
- if(!ELEM(bs->type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE))
+ if(!ELEM3(bs->type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_SHADOW))
shade_samples_do_AO(ssamp);
if(shi->mat->nodetree && shi->mat->use_nodes) {
@@ -2070,6 +2073,10 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
shr.combined[2]= shi->b;
shr.alpha = shi->alpha;
}
+ else if(bs->type==RE_BAKE_SHADOW) {
+ VECCOPY(shr.combined, shr.shad);
+ shr.alpha = shi->alpha;
+ }
}
if(bs->rect_float) {
@@ -2505,7 +2512,12 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob)
memset(&handles[a], 0, sizeof(BakeShade));
handles[a].ssamp.shi[0].lay= re->scene->lay;
- handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED;
+
+ if (type==RE_BAKE_SHADOW) {
+ handles[a].ssamp.shi[0].passflag= SCE_PASS_SHADOW;
+ } else {
+ handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED;
+ }
handles[a].ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
handles[a].ssamp.shi[0].thread= a;
handles[a].ssamp.tot= 1;
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 628726db563..6d668757d16 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -3081,7 +3081,6 @@ static void editing_panel_font_type(Object *ob, Curve *cu)
void do_curvebuts(unsigned short event)
{
- extern Nurb *lastnu;
extern ListBase editNurb; /* from editcurve */
Object *ob;
Curve *cu;
@@ -3115,13 +3114,15 @@ void do_curvebuts(unsigned short event)
if(isNurbsel(nu)) {
if((nu->type & 7)==CU_NURBS) {
if(event<B_UNIFV) {
- nu->flagu &= 1;
- nu->flagu += ((event-B_UNIFU)<<1);
+ nu->flagu &= CU_CYCLIC; /* disable all flags except for CU_CYCLIC */
+ nu->flagu |= ((event-B_UNIFU)<<1);
+ clamp_nurb_order_u(nu);
makeknots(nu, 1, nu->flagu>>1);
}
else if(nu->pntsv>1) {
- nu->flagv &= 1;
- nu->flagv += ((event-B_UNIFV)<<1);
+ nu->flagv &= CU_CYCLIC; /* disable all flags except for CU_CYCLIC */
+ nu->flagv |= ((event-B_UNIFV)<<1);
+ clamp_nurb_order_v(nu);
makeknots(nu, 2, nu->flagv>>1);
}
}
@@ -3157,15 +3158,13 @@ void do_curvebuts(unsigned short event)
break;
case B_SETORDER:
if(G.obedit) {
- nu= lastnu;
+ nu= get_actNurb();
if(nu && (nu->type & 7)==CU_NURBS ) {
- if(nu->orderu>nu->pntsu) {
- nu->orderu= nu->pntsu;
+ if(clamp_nurb_order_u(nu)) {
scrarea_queue_winredraw(curarea);
}
makeknots(nu, 1, nu->flagu>>1);
- if(nu->orderv>nu->pntsv) {
- nu->orderv= nu->pntsv;
+ if(clamp_nurb_order_v(nu)) {
scrarea_queue_winredraw(curarea);
}
makeknots(nu, 2, nu->flagv>>1);
@@ -3283,7 +3282,6 @@ static void editing_panel_curve_tools(Object *ob, Curve *cu)
{
Nurb *nu;
extern ListBase editNurb; /* from editcurve */
- extern Nurb *lastnu;
uiBlock *block;
short *sp;
@@ -3319,8 +3317,11 @@ static void editing_panel_curve_tools(Object *ob, Curve *cu)
uiBlockEndAlign(block);
if(ob==G.obedit) {
- nu= lastnu;
- if(nu==NULL) nu= lastnu= editNurb.first;
+ nu= get_actNurb();
+ if(nu==NULL && editNurb.first) {
+ nu= editNurb.first;
+ set_actNurb(nu);
+ }
if(nu) {
if (ob->type==OB_CURVE) {
uiDefBut(block, LABEL, 0, "Tilt",
diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c
index b98a8c58102..3797a92f16f 100644
--- a/source/blender/src/buttons_scene.c
+++ b/source/blender/src/buttons_scene.c
@@ -2150,6 +2150,10 @@ static void render_panel_bake(void)
"Normalized displacement value to fit the 'Dist' range"
);
}
+
+ uiDefButS(block, MENU, B_NOP, "Quad Split Order%t|Quad Split Auto%x0|Quad Split A (0,1,2) (0,2,3)%x1|Quad Split B (1,2,3) (1,3,0)%x2",
+ 10,10,190,20, &G.scene->r.bake_quad_split, 0, 0, 0, 0, "Method to divide quads (use A or B for external applications that use a fixed order)");
+
#if 0
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, R_BAKE_OSA, B_DIFF, "OSA", 10,120,190,20, &G.scene->r.bake_flag, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)");
@@ -2161,14 +2165,15 @@ static void render_panel_bake(void)
uiBlockBeginAlign(block);
uiDefButS(block, ROW,B_REDR,"Full Render", 210,170,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_ALL, 0, 0, "");
uiDefButS(block, ROW,B_REDR,"Ambient Occlusion",210,150,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_AO, 0, 0, "");
- uiDefButS(block, ROW,B_REDR,"Normals", 210,130,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_NORMALS, 0, 0, "");
- uiDefButS(block, ROW,B_REDR,"Textures", 210,110,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_TEXTURE, 0, 0, "");
- uiDefButS(block, ROW,B_REDR,"Displacement", 210,90,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_DISPLACEMENT, 0, 0, "");
+ uiDefButS(block, ROW,B_REDR,"Shadow", 210,130,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_SHADOW, 0, 0, "");
+ uiDefButS(block, ROW,B_REDR,"Normals", 210,110,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_NORMALS, 0, 0, "");
+ uiDefButS(block, ROW,B_REDR,"Textures", 210,90,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_TEXTURE, 0, 0, "");
+ uiDefButS(block, ROW,B_REDR,"Displacement", 210,70,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_DISPLACEMENT, 0, 0, "");
uiBlockEndAlign(block);
- uiDefButBitS(block, TOG, R_BAKE_CLEAR, B_DIFF, "Clear", 210,60,120,20,&G.scene->r.bake_flag, 0.0, 0, 0, 0, "Clear Images before baking");
+ uiDefButBitS(block, TOG, R_BAKE_CLEAR, B_DIFF, "Clear", 210,40,120,20,&G.scene->r.bake_flag, 0.0, 0, 0, 0, "Clear Images before baking");
- uiDefButS(block, NUM, B_DIFF,"Margin:", 210,30,120,20,&G.scene->r.bake_filter, 0.0, 32.0, 0, 0, "Amount of pixels to extend the baked result with, as post process filter");
+ uiDefButS(block, NUM, B_DIFF,"Margin:", 210,10,120,20,&G.scene->r.bake_filter, 0.0, 32.0, 0, 0, "Amount of pixels to extend the baked result with, as post process filter");
}
static void render_panel_simplify(void)
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index 045b98bb784..96ba8c71755 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -2885,7 +2885,7 @@ static int drawDispList(Base *base, int dt)
/* 5. start filling the arrays */
/* 6. draw the arrays */
/* 7. clean up */
-static void draw_new_particle_system(Base *base, ParticleSystem *psys)
+static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
{
View3D *v3d= G.vd;
Object *ob=base->object;
@@ -2902,7 +2902,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
- int select=ob->flag&SELECT;
+ int select=ob->flag&SELECT, create_cdata=0;
GLint polygonmode[2];
char val[32];
@@ -2956,8 +2956,10 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
if(select)
cpack(0xFFFFFF);
- else if((ma) && (part->draw&PART_DRAW_MAT_COL))
+ else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
glColor3f(ma->r,ma->g,ma->b);
+ create_cdata = 1;
+ }
else
cpack(0);
@@ -3065,19 +3067,25 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
if(draw_as!=PART_DRAW_CIRC){
switch(draw_as){
case PART_DRAW_AXIS:
- cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
- /* no break! */
case PART_DRAW_CROSS:
+ if(draw_as!=PART_DRAW_CROSS || create_cdata)
+ cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
break;
case PART_DRAW_LINE:
+ if(create_cdata)
+ cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata");
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
break;
case PART_DRAW_BB:
+ if(create_cdata)
+ cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata");
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
break;
default:
+ if(create_cdata)
+ cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata");
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
}
}
@@ -3102,9 +3110,17 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
pa_time=(cfra-pa->time)/pa->lifetime;
- if((part->flag&PART_ABS_TIME)==0 && part->ipo){
- calc_ipo(part->ipo, 100*pa_time);
- execute_ipo((ID *)part, part->ipo);
+ if((part->flag&PART_ABS_TIME)==0){
+ if(ma && ma->ipo){
+ /* correction for lifetime */
+ calc_ipo(ma->ipo, 100.0f*pa_time);
+ execute_ipo((ID *)ma, ma->ipo);
+ }
+ if(part->ipo) {
+ /* correction for lifetime */
+ calc_ipo(part->ipo, 100*pa_time);
+ execute_ipo((ID *)part, part->ipo);
+ }
}
pa_size=pa->size;
@@ -3121,9 +3137,17 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
pa_time=psys_get_child_time(psys,cpa,cfra);
- if((part->flag&PART_ABS_TIME)==0 && part->ipo){
- calc_ipo(part->ipo, 100*pa_time);
- execute_ipo((ID *)part, part->ipo);
+ if((part->flag&PART_ABS_TIME)==0) {
+ if(ma && ma->ipo){
+ /* correction for lifetime */
+ calc_ipo(ma->ipo, 100.0f*pa_time);
+ execute_ipo((ID *)ma, ma->ipo);
+ }
+ if(part->ipo) {
+ /* correction for lifetime */
+ calc_ipo(part->ipo, 100*pa_time);
+ execute_ipo((ID *)part, part->ipo);
+ }
}
pa_size=psys_get_child_size(psys,cpa,cfra,0);
@@ -3161,6 +3185,12 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
switch(draw_as){
case PART_DRAW_DOT:
+ if(cd) {
+ cd[0]=ma->r;
+ cd[1]=ma->g;
+ cd[2]=ma->b;
+ cd+=3;
+ }
if(vd){
VECCOPY(vd,state.co) vd+=3;
}
@@ -3181,7 +3211,15 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
VECCOPY(vec2,state.co);
}
- else VECSUB(vec2,state.co,vec);
+ else {
+ if(cd) {
+ cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma->r;
+ cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma->g;
+ cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma->b;
+ cd+=18;
+ }
+ VECSUB(vec2,state.co,vec);
+ }
VECADD(vec,state.co,vec);
VECCOPY(vd,vec); vd+=3;
@@ -3219,11 +3257,25 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
VecMulf(vec,VecLength(state.vel));
VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3;
VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3;
+ if(cd) {
+ cd[0]=cd[3]=ma->r;
+ cd[1]=cd[4]=ma->g;
+ cd[2]=cd[5]=ma->b;
+ cd+=3;
+ }
break;
case PART_DRAW_CIRC:
+ if(create_cdata)
+ glColor3f(ma->r,ma->g,ma->b);
drawcircball(GL_LINE_LOOP, state.co, pixsize, imat);
break;
case PART_DRAW_BB:
+ if(cd) {
+ cd[0]=cd[3]=cd[6]=cd[9]=ma->r;
+ cd[1]=cd[4]=cd[7]=cd[10]=ma->g;
+ cd[2]=cd[5]=cd[8]=cd[11]=ma->b;
+ cd+=12;
+ }
if(part->draw&PART_DRAW_BB_LOCK && part->bb_align==PART_BB_VIEW){
VECCOPY(xvec,bb_ob->obmat[0]);
Normalize(xvec);
@@ -3334,14 +3386,24 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
float *cd2=0,*cdata2=0;
glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnable(GL_LIGHTING);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
+ if(dt > OB_WIRE) {
+ glEnableClientState(GL_NORMAL_ARRAY);
- if(part->draw&PART_DRAW_MAT_COL)
- glEnableClientState(GL_COLOR_ARRAY);
+ if(part->draw&PART_DRAW_MAT_COL)
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ glEnable(GL_LIGHTING);
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ glEnable(GL_COLOR_MATERIAL);
+ }
+ else {
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ glDisable(GL_COLOR_MATERIAL);
+ glDisable(GL_LIGHTING);
+ BIF_ThemeColor(TH_WIRE);
+ }
if(totchild && (part->draw&PART_DRAW_PARENT)==0)
totpart=0;
@@ -3350,9 +3412,13 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
for(a=0, pa=psys->particles; a<totpart; a++, pa++){
path=cache[a];
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
- if(part->draw&PART_DRAW_MAT_COL)
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+
+ if(dt > OB_WIRE) {
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
+ if(part->draw&PART_DRAW_MAT_COL)
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+ }
+
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
}
@@ -3360,15 +3426,21 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
for(a=0; a<totchild; a++){
path=cache[a];
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
- if(part->draw&PART_DRAW_MAT_COL)
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+
+ if(dt > OB_WIRE) {
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
+ if(part->draw&PART_DRAW_MAT_COL)
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+ }
+
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
}
- if(part->draw&PART_DRAW_MAT_COL)
- glDisable(GL_COLOR_ARRAY);
- glDisable(GL_COLOR_MATERIAL);
+ if(dt > OB_WIRE) {
+ if(part->draw&PART_DRAW_MAT_COL)
+ glDisable(GL_COLOR_ARRAY);
+ glDisable(GL_COLOR_MATERIAL);
+ }
if(cdata2)
MEM_freeN(cdata2);
@@ -3389,7 +3461,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
else
glDisableClientState(GL_VERTEX_ARRAY);
- if(ndata && MIN2(G.vd->drawtype, ob->dt)>OB_WIRE){
+ if(ndata && dt>OB_WIRE){
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, ndata);
glEnable(GL_LIGHTING);
@@ -3399,20 +3471,21 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
glDisable(GL_LIGHTING);
}
+ if(cdata){
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, cdata);
+ }
+
switch(draw_as){
case PART_DRAW_AXIS:
case PART_DRAW_CROSS:
- if(cdata){
- glEnableClientState(GL_COLOR_ARRAY);
- glColorPointer(3, GL_FLOAT, 0, cdata);
- }
glDrawArrays(GL_LINES, 0, 6*totpoint);
break;
case PART_DRAW_LINE:
glDrawArrays(GL_LINES, 0, 2*totpoint);
break;
case PART_DRAW_BB:
- if(MIN2(G.vd->drawtype, ob->dt)<=OB_WIRE)
+ if(dt<=OB_WIRE)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glDrawArrays(GL_QUADS, 0, 4*totpoint);
@@ -3466,7 +3539,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
mymultmatrix(ob->obmat); // bring back local matrix for dtx
}
-static void draw_particle_edit(Object *ob, ParticleSystem *psys)
+static void draw_particle_edit(Object *ob, ParticleSystem *psys, int dt)
{
ParticleEdit *edit = psys->edit;
ParticleData *pa;
@@ -3479,6 +3552,7 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys)
float nosel_col[3];
char val[32];
+ /* create path and child path cache if it doesn't exist already */
if(psys->pathcache==0){
PE_hide_keys_time(psys,CFRA);
psys_cache_paths(ob,psys,CFRA,0);
@@ -3493,11 +3567,13 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys)
else if(!(pset->flag & PE_SHOW_CHILD) && psys->childcache)
free_child_path_cache(psys);
+ /* opengl setup */
if((G.vd->flag & V3D_ZBUF_SELECT)==0)
glDisable(GL_DEPTH_TEST);
myloadmatrix(G.vd->viewmat);
+ /* get selection theme colors */
BIF_GetThemeColor3ubv(TH_VERTEX_SELECT, sel);
BIF_GetThemeColor3ubv(TH_VERTEX, nosel);
sel_col[0]=(float)sel[0]/255.0f;
@@ -3511,41 +3587,61 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys)
totchild = psys->totchildcache;
/* draw paths */
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
if(timed)
glEnable(GL_BLEND);
- if(pset->brushtype == PE_BRUSH_WEIGHT){
- glLineWidth(2.0f);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ if(dt > OB_WIRE) {
+ /* solid shaded with lighting */
+ glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
+
+ glEnable(GL_COLOR_MATERIAL);
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ }
+ else {
+ /* flat wire color */
+ glDisableClientState(GL_NORMAL_ARRAY);
glDisable(GL_LIGHTING);
+ BIF_ThemeColor(TH_WIRE);
}
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
-
- for(i=0, pa=psys->particles, path = psys->pathcache; i<totpart; i++, pa++, path++){
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
-
- glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
- }
+ /* only draw child paths with lighting */
+ if(dt > OB_WIRE)
+ glEnable(GL_LIGHTING);
- glEnable(GL_LIGHTING);
if(psys->part->draw_as == PART_DRAW_PATH) {
for(i=0, path=psys->childcache; i<totchild; i++,path++){
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
+ if(dt > OB_WIRE) {
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
+ }
glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
}
}
- glDisable(GL_COLOR_MATERIAL);
+ if(dt > OB_WIRE)
+ glDisable(GL_LIGHTING);
+
+ if(pset->brushtype == PE_BRUSH_WEIGHT) {
+ glLineWidth(2.0f);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glDisable(GL_LIGHTING);
+ }
+
+ /* draw parents last without lighting */
+ for(i=0, pa=psys->particles, path = psys->pathcache; i<totpart; i++, pa++, path++){
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
+ if(dt > OB_WIRE)
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
+ if(dt > OB_WIRE || pset->brushtype == PE_BRUSH_WEIGHT)
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
+
+ glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
+ }
/* draw edit vertices */
if(G.scene->selectmode!=SCE_SELECT_PATH){
@@ -3619,6 +3715,7 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys)
glDisable(GL_BLEND);
glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnable(GL_DEPTH_TEST);
@@ -5011,12 +5108,12 @@ void draw_object(Base *base, int flag)
glDepthMask(GL_FALSE);
for(psys=ob->particlesystem.first; psys; psys=psys->next)
- draw_new_particle_system(base, psys);
+ draw_new_particle_system(base, psys, dt);
if(G.f & G_PARTICLEEDIT && ob==OBACT) {
psys= PE_get_current(ob);
if(psys && !G.obedit && psys_in_edit_mode(psys))
- draw_particle_edit(ob, psys);
+ draw_particle_edit(ob, psys, dt);
}
glDepthMask(GL_TRUE);
if(col) cpack(col);
diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c
index e979f6e16fc..e554b91dd52 100644
--- a/source/blender/src/drawseq.c
+++ b/source/blender/src/drawseq.c
@@ -691,7 +691,7 @@ static void draw_seq_strip(Sequence *seq, ScrArea *sa, SpaceSeq *sseq, int outli
/* draw the main strip body */
if (is_single_image) /* single image */
- draw_shadedstrip(seq, col, seq_tx_get_final_left(seq), y1, seq_tx_get_final_right(seq), y2);
+ draw_shadedstrip(seq, col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2);
else /* normal operation */
draw_shadedstrip(seq, col, x1, y1, x2, y2);
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
index 52e0d3d6f05..e83ecb13960 100644
--- a/source/blender/src/drawview.c
+++ b/source/blender/src/drawview.c
@@ -3732,18 +3732,22 @@ int play_anim(int mode)
else viewmove(0);
}
} else if (event==WHEELDOWNMOUSE || (val && event==PADMINUS)) { /* copied from persptoetsen */
- /* this min and max is also in viewmove() */
- if(G.vd->persp==V3D_CAMOB) {
- G.vd->camzoom-= 10;
- if(G.vd->camzoom<-30) G.vd->camzoom= -30;
+ if (G.vd) { /* when using the sequencer this can be NULL */
+ /* this min and max is also in viewmove() */
+ if(G.vd->persp==V3D_CAMOB) {
+ G.vd->camzoom-= 10;
+ if(G.vd->camzoom<-30) G.vd->camzoom= -30;
+ }
+ else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f;
}
- else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f;
} else if (event==WHEELUPMOUSE || (val && event==PADPLUSKEY)) { /* copied from persptoetsen */
- if(G.vd->persp==V3D_CAMOB) {
- G.vd->camzoom+= 10;
- if(G.vd->camzoom>300) G.vd->camzoom= 300;
+ if (G.vd) {
+ if(G.vd->persp==V3D_CAMOB) {
+ G.vd->camzoom+= 10;
+ if(G.vd->camzoom>300) G.vd->camzoom= 300;
+ }
+ else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f;
}
- else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f;
} else if(event==MKEY) {
if(val) add_marker(CFRA-1);
}
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
index 12b9cb8919f..40b6b7ba6fe 100644
--- a/source/blender/src/editaction.c
+++ b/source/blender/src/editaction.c
@@ -1485,7 +1485,7 @@ void insertkey_action(void)
data= get_action_context(&datatype);
if (data == NULL) return;
cfra = frame_to_float(CFRA);
-
+
if (datatype == ACTCONT_ACTION) {
ListBase act_data = {NULL, NULL};
bActListElem *ale;
@@ -1941,6 +1941,7 @@ void paste_actdata ()
int filter;
void *data;
short datatype;
+ Object *ob= OBACT;
short no_name= 0;
float offset = CFRA - actcopy_firstframe;
@@ -2017,7 +2018,7 @@ void paste_actdata ()
/* loop over curves, pasting keyframes */
for (ico= ipo_src->curve.first; ico; ico= ico->next) {
- icu= verify_ipocurve((ID*)OBACT, ico->blocktype, actname, conname, "", ico->adrcode);
+ icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, "", ico->adrcode);
if (icu) {
/* just start pasting, with the the first keyframe on the current frame, and so on */
@@ -2045,6 +2046,14 @@ void paste_actdata ()
/* free temp memory */
BLI_freelistN(&act_data);
+ /* do depsgraph updates (for 3d-view)? */
+ if ((ob) && (G.saction->pin==0)) {
+ if (ob->type == OB_ARMATURE)
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
+ else
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
+ }
+
/* undo and redraw stuff */
allqueue(REDRAWVIEW3D, 0);
allspace(REMAKEIPO, 0);
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
index 172e06f5add..39f93510358 100644
--- a/source/blender/src/editarmature.c
+++ b/source/blender/src/editarmature.c
@@ -2396,6 +2396,7 @@ void fill_bones_armature(void)
else if (count == 2) {
EditBonePoint *ebp, *ebp2;
float head[3], tail[3];
+ short headtail = 0;
/* check that the points don't belong to the same bone */
ebp= (EditBonePoint *)points.first;
@@ -2420,7 +2421,7 @@ void fill_bones_armature(void)
float distA, distB;
/* get cursor location */
- VECCOPY (curs, give_cursor());
+ VECCOPY(curs, give_cursor());
Mat4Invert(G.obedit->imat, G.obedit->obmat);
Mat4MulVecfl(G.obedit->imat, curs);
@@ -2432,26 +2433,47 @@ void fill_bones_armature(void)
distB= VecLength(vecB);
/* compare distances - closer one therefore acts as direction for bone to go */
- if (distA < distB) {
- VECCOPY(head, ebp2->vec);
- VECCOPY(tail, ebp->vec);
- }
- else {
- VECCOPY(head, ebp->vec);
- VECCOPY(tail, ebp2->vec);
- }
+ headtail= (distA < distB) ? 2 : 1;
}
else if (ebp->head_owner) {
+ headtail = 1;
+ }
+ else if (ebp2->head_owner) {
+ headtail = 2;
+ }
+
+ /* assign head/tail combinations */
+ if (headtail == 2) {
VECCOPY(head, ebp->vec);
VECCOPY(tail, ebp2->vec);
}
- else if (ebp2->head_owner) {
+ else if (headtail == 1) {
VECCOPY(head, ebp2->vec);
VECCOPY(tail, ebp->vec);
}
- /* add new bone */
- newbone= add_points_bone(head, tail);
+ /* add new bone and parent it to the appropriate end */
+ if (headtail) {
+ newbone= add_points_bone(head, tail);
+
+ /* do parenting (will need to set connected flag too) */
+ if (headtail == 2) {
+ /* ebp tail or head - tail gets priority */
+ if (ebp->tail_owner)
+ newbone->parent= ebp->tail_owner;
+ else
+ newbone->parent= ebp->head_owner;
+ }
+ else {
+ /* ebp2 tail or head - tail gets priority */
+ if (ebp2->tail_owner)
+ newbone->parent= ebp2->tail_owner;
+ else
+ newbone->parent= ebp2->head_owner;
+ }
+
+ newbone->flag |= BONE_CONNECTED;
+ }
}
else {
// FIXME.. figure out a method for multiple bones
@@ -4097,16 +4119,34 @@ void transform_armature_mirror_update(void)
if (eboflip) {
/* we assume X-axis flipping for now */
if (ebo->flag & BONE_TIPSEL) {
+ EditBone *children;
+
eboflip->tail[0]= -ebo->tail[0];
eboflip->tail[1]= ebo->tail[1];
eboflip->tail[2]= ebo->tail[2];
eboflip->rad_tail= ebo->rad_tail;
+
+ /* Also move connected children, in case children's name aren't mirrored properly */
+ for (children=G.edbo.first; children; children=children->next) {
+ if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
+ VECCOPY(children->head, eboflip->tail);
+ children->rad_head = ebo->rad_tail;
+ }
+ }
}
if (ebo->flag & BONE_ROOTSEL) {
eboflip->head[0]= -ebo->head[0];
eboflip->head[1]= ebo->head[1];
eboflip->head[2]= ebo->head[2];
eboflip->rad_head= ebo->rad_head;
+
+ /* Also move connected parent, in case parent's name isn't mirrored properly */
+ if (eboflip->parent && eboflip->flag & BONE_CONNECTED)
+ {
+ EditBone *parent = eboflip->parent;
+ VECCOPY(parent->tail, eboflip->head);
+ parent->rad_tail = ebo->rad_head;
+ }
}
if (ebo->flag & BONE_SELECTED) {
eboflip->dist= ebo->dist;
diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c
index 7572391b383..bd0abe83ee4 100644
--- a/source/blender/src/editcurve.c
+++ b/source/blender/src/editcurve.c
@@ -99,7 +99,7 @@
ListBase editNurb;
BPoint *lastselbp;
-Nurb *lastnu; /* for selected */
+int actnu; /* for selected */
/* void freeNurblist(ListBase *lb); already declared in the kernel */
@@ -109,6 +109,23 @@ float nurbcircle[8][2]= {
{0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0}
};
+
+/* this replaces the active flag used in uv/face mode */
+void set_actNurb(Nurb *nu)
+{
+ if (nu==NULL) {
+ actnu = -1;
+ } else {
+ actnu = BLI_findindex(&editNurb, nu);
+ }
+}
+
+Nurb * get_actNurb( void )
+{
+ return BLI_findlink(&editNurb, actnu);
+}
+
+
/* ******************* SELECTION FUNCTIONS ********************* */
/* returns 1 in case (de)selection was successful */
@@ -318,14 +335,14 @@ void load_editNurb()
BLI_addtail(&(cu->nurb), newnu);
if((nu->type & 7)==CU_NURBS) {
- if(nu->pntsu < nu->orderu) nu->orderu= nu->pntsu;
+ clamp_nurb_order_u(nu);
}
}
}
}
- lastnu= NULL; /* for selected */
+ set_actNurb(NULL);
}
void make_editNurb()
@@ -361,8 +378,7 @@ void make_editNurb()
else G.obedit= NULL;
countall();
-
- lastnu= NULL; /* for selected */
+ set_actNurb(NULL);
}
void remake_editNurb()
@@ -457,8 +473,7 @@ void separate_nurb()
countall();
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
-
- lastnu= NULL; /* for selected */
+ set_actNurb(NULL);
}
/* ******************* FLAGS ********************* */
@@ -640,7 +655,7 @@ void deleteflagNurb(short flag)
}
if(a==0) {
BLI_remlink(&editNurb, nu);
- freeNurb(nu);
+ freeNurb(nu); nu=NULL;
}
else {
/* is nurb in U direction selected */
@@ -674,7 +689,7 @@ void deleteflagNurb(short flag)
nu->pntsv= newv;
MEM_freeN(nu->bp);
nu->bp= newbp;
- if(nu->orderv>nu->pntsv) nu->orderv= nu->pntsv;
+ clamp_nurb_order_v(nu);
makeknots(nu, 2, nu->flagv>>1);
}
@@ -714,13 +729,13 @@ void deleteflagNurb(short flag)
nu->pntsu= nu->pntsv;
nu->pntsv= 1;
SWAP(short, nu->orderu, nu->orderv);
- if(nu->orderu>nu->pntsu) nu->orderu= nu->pntsu;
+ clamp_nurb_order_u(nu);
if(nu->knotsv) MEM_freeN(nu->knotsv);
- nu->knotsv= 0;
+ nu->knotsv= NULL;
}
else {
nu->pntsu= newu;
- if(nu->orderu>nu->pntsu) nu->orderu= nu->pntsu;
+ clamp_nurb_order_u(nu);
}
makeknots(nu, 1, nu->flagu>>1);
}
@@ -878,7 +893,7 @@ void adduplicateflagNurb(short flag)
newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN");
memcpy(newnu, nu, sizeof(Nurb));
BLI_addtail(&editNurb, newnu);
- lastnu= newnu;
+ set_actNurb(newnu);
newnu->pntsu= enda-starta+1;
newnu->bezt=
(BezTriple*)MEM_mallocN((enda - starta + 1) * sizeof(BezTriple), "adduplicateN");
@@ -891,8 +906,10 @@ void adduplicateflagNurb(short flag)
bezt1++;
}
- if(nu->flagu & 1) {
- if(starta!=0 || enda!=nu->pntsu-1) newnu->flagu--;
+ if(nu->flagu & CU_CYCLIC) {
+ if(starta!=0 || enda!=nu->pntsu-1) {
+ newnu->flagu &= ~CU_CYCLIC;
+ }
}
}
bezt++;
@@ -913,7 +930,7 @@ void adduplicateflagNurb(short flag)
if(enda>=starta) {
newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN3");
memcpy(newnu, nu, sizeof(Nurb));
- lastnu= newnu;
+ set_actNurb(newnu);
BLI_addtail(&editNurb, newnu);
newnu->pntsu= enda-starta+1;
newnu->bp = (BPoint*)MEM_mallocN((enda-starta+1) * sizeof(BPoint), "adduplicateN4");
@@ -926,12 +943,14 @@ void adduplicateflagNurb(short flag)
bp1++;
}
- if(nu->flagu & 1) {
- if(starta!=0 || enda!=nu->pntsu-1) newnu->flagu--;
+ if(nu->flagu & CU_CYCLIC) {
+ if(starta!=0 || enda!=nu->pntsu-1) {
+ newnu->flagu &= ~CU_CYCLIC;
+ }
}
/* knots */
- newnu->knotsu= 0;
+ newnu->knotsu= NULL;
makeknots(newnu, 1, newnu->flagu>>1);
}
bp++;
@@ -971,14 +990,16 @@ void adduplicateflagNurb(short flag)
newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN5");
memcpy(newnu, nu, sizeof(Nurb));
BLI_addtail(&editNurb, newnu);
- lastnu= newnu;
+ set_actNurb(newnu);
newnu->pntsu= newu;
newnu->pntsv= newv;
newnu->bp =
(BPoint*)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN6");
- newnu->orderu= MIN2(nu->orderu, newu);
- newnu->orderv= MIN2(nu->orderv, newv);
-
+ clamp_nurb_order_u(newnu);
+ clamp_nurb_order_v(newnu);
+
+ newnu->knotsu= newnu->knotsv= NULL;
+
bp= newnu->bp;
bp1= nu->bp;
for(a=0; a<nu->pntsv; a++) {
@@ -990,23 +1011,20 @@ void adduplicateflagNurb(short flag)
}
}
}
- if(nu->pntsu==newnu->pntsu) {
- newnu->knotsu= MEM_mallocN(sizeof(float)*KNOTSU(nu), "adduplicateN6");
- memcpy(newnu->knotsu, nu->knotsu, sizeof(float)*KNOTSU(nu));
- }
- else {
- newnu->knotsu= 0;
- makeknots(newnu, 1, newnu->flagu>>1);
- }
- if(nu->pntsv==newnu->pntsv) {
- newnu->knotsv= MEM_mallocN(sizeof(float)*KNOTSV(nu), "adduplicateN7");
- memcpy(newnu->knotsv, nu->knotsv, sizeof(float)*KNOTSV(nu));
+ if (check_valid_nurb_u(newnu)) {
+ if(nu->pntsu==newnu->pntsu && nu->knotsu) {
+ newnu->knotsu= MEM_dupallocN( nu->knotsu );
+ } else {
+ makeknots(newnu, 1, newnu->flagu>>1);
+ }
}
- else {
- newnu->knotsv= 0;
- makeknots(newnu, 2, newnu->flagv>>1);
+ if (check_valid_nurb_v(newnu)) {
+ if(nu->pntsv==newnu->pntsv && nu->knotsv) {
+ newnu->knotsv= MEM_dupallocN( nu->knotsv );
+ } else {
+ makeknots(newnu, 2, newnu->flagv>>1);
+ }
}
-
}
MEM_freeN(usel);
}
@@ -1015,7 +1033,7 @@ void adduplicateflagNurb(short flag)
nu= nu->prev;
}
- /* lastnu changed */
+ /* actnu changed */
allqueue(REDRAWBUTSEDIT, 0);
}
@@ -1569,7 +1587,7 @@ void subdivideNurb()
newly created. Old points are discarded.
*/
/* count */
- if(nu->flagu & 1) {
+ if(nu->flagu & CU_CYCLIC) {
a= nu->pntsu;
bezt= nu->bezt;
prevbezt= bezt+(a-1);
@@ -1590,7 +1608,7 @@ void subdivideNurb()
beztnew =
(BezTriple*)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb");
beztn= beztnew;
- if(nu->flagu & 1) {
+ if(nu->flagu & CU_CYCLIC) {
a= nu->pntsu;
bezt= nu->bezt;
prevbezt= bezt+(a-1);
@@ -1622,7 +1640,7 @@ void subdivideNurb()
VecMidf(beztn->vec[1], vec+9, vec+12);
VECCOPY(beztn->vec[2], vec+12);
/* handle of next bezt */
- if(a==0 && (nu->flagu & 1)) {VECCOPY(beztnew->vec[0], vec+6);}
+ if(a==0 && (nu->flagu & CU_CYCLIC)) {VECCOPY(beztnew->vec[0], vec+6);}
else {VECCOPY(bezt->vec[0], vec+6);}
beztn->radius = (prevbezt->radius + bezt->radius)/2.0f;
@@ -1635,7 +1653,7 @@ void subdivideNurb()
bezt++;
}
/* last point */
- if((nu->flagu & 1)==0) memcpy(beztn, prevbezt, sizeof(BezTriple));
+ if((nu->flagu & CU_CYCLIC)==0) memcpy(beztn, prevbezt, sizeof(BezTriple));
MEM_freeN(nu->bezt);
nu->bezt= beztnew;
@@ -1652,7 +1670,7 @@ void subdivideNurb()
stable... nzc 30-5-'00
*/
/* count */
- if(nu->flagu & 1) {
+ if(nu->flagu & CU_CYCLIC) {
a= nu->pntsu*nu->pntsv;
bp= nu->bp;
prevbp= bp+(a-1);
@@ -1674,7 +1692,7 @@ void subdivideNurb()
(BPoint*)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2");
bpn= bpnew;
- if(nu->flagu & 1) {
+ if(nu->flagu & CU_CYCLIC) {
a= nu->pntsu;
bp= nu->bp;
prevbp= bp+(a-1);
@@ -1701,7 +1719,7 @@ void subdivideNurb()
prevbp= bp;
bp++;
}
- if((nu->flagu & 1)==0) memcpy(bpn, prevbp, sizeof(BPoint)); /* last point */
+ if((nu->flagu & CU_CYCLIC)==0) memcpy(bpn, prevbp, sizeof(BPoint)); /* last point */
MEM_freeN(nu->bp);
nu->bp= bpnew;
@@ -2075,7 +2093,7 @@ int convertspline(short type, Nurb *nu)
nu->type &= ~7;
nu->type+= 4;
nu->orderu= 4;
- nu->flagu &= 1;
+ nu->flagu &= CU_CYCLIC; /* disable all flags except for cyclic */
nu->flagu += 4;
makeknots(nu, 1, nu->flagu>>1);
a= nu->pntsu*nu->pntsv;
@@ -2126,10 +2144,10 @@ int convertspline(short type, Nurb *nu)
nu->orderv= 1;
nu->type &= ~7;
nu->type+= type;
- if(nu->flagu & 1) c= nu->orderu-1;
+ if(nu->flagu & CU_CYCLIC) c= nu->orderu-1;
else c= 0;
if(type== 4) {
- nu->flagu &= 1;
+ nu->flagu &= CU_CYCLIC; /* disable all flags except for cyclic */
nu->flagu += 4;
makeknots(nu, 1, nu->flagu>>1);
}
@@ -2139,9 +2157,9 @@ int convertspline(short type, Nurb *nu)
if(type==0) { /* to Poly */
nu->type &= ~7;
if(nu->knotsu) MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */
- nu->knotsu= 0;
+ nu->knotsu= NULL;
if(nu->knotsv) MEM_freeN(nu->knotsv);
- nu->knotsv= 0;
+ nu->knotsv= NULL;
}
else if(type==CU_BEZIER) { /* to Bezier */
nr= nu->pntsu/3;
@@ -2170,7 +2188,7 @@ int convertspline(short type, Nurb *nu)
MEM_freeN(nu->bp);
nu->bp= 0;
MEM_freeN(nu->knotsu);
- nu->knotsu= 0;
+ nu->knotsu= NULL;
nu->pntsu= nr;
nu->type &= ~7;
nu->type+= 1;
@@ -2481,7 +2499,7 @@ void merge_nurb()
BLI_freelistN(&nsortbase);
countall();
- lastnu= NULL;
+ set_actNurb(NULL);
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
@@ -2527,7 +2545,7 @@ void addsegment_nurb()
/* find both nurbs and points, nu1 will be put behind nu2 */
for(nu= editNurb.first; nu; nu= nu->next) {
- if((nu->flagu & 1)==0) { /* not cyclic */
+ if((nu->flagu & CU_CYCLIC)==0) { /* not cyclic */
if( (nu->type & 7)==CU_BEZIER ) {
bezt= nu->bezt;
if(nu1==0) {
@@ -2594,7 +2612,7 @@ void addsegment_nurb()
nu1->bezt= bezt;
nu1->pntsu+= nu2->pntsu;
BLI_remlink(&editNurb, nu2);
- freeNurb(nu2);
+ freeNurb(nu2); nu2= NULL;
calchandlesNurb(nu1);
}
else {
@@ -2632,11 +2650,11 @@ void addsegment_nurb()
}
}
}
- freeNurb(nu2);
+ freeNurb(nu2); nu2= NULL;
}
}
- lastnu= NULL; /* for selected */
+ set_actNurb(NULL); /* for selected */
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
@@ -2704,8 +2722,8 @@ void mouse_nurb()
rightmouse_transform();
- if(nu!=lastnu) {
- lastnu= nu;
+ if(nu!=get_actNurb()) {
+ set_actNurb(nu);
allqueue(REDRAWBUTSEDIT, 0);
}
@@ -2808,7 +2826,7 @@ static void spin_nurb(float *dvec, short mode)
for(nu= editNurb.first; nu; nu= nu->next) {
if(isNurbsel(nu)) {
nu->orderv= 4;
- nu->flagv |= 1;
+ nu->flagv |= CU_CYCLIC;
makeknots(nu, 2, nu->flagv>>1);
}
}
@@ -3006,8 +3024,8 @@ void makecyclicNurb()
bp= nu->bp;
while(a--) {
if( bp->f1 & SELECT ) {
- if(nu->flagu & CU_CYCLIC) nu->flagu--;
- else nu->flagu++;
+ if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC;
+ else nu->flagu |= CU_CYCLIC;
break;
}
bp++;
@@ -3018,8 +3036,8 @@ void makecyclicNurb()
bezt= nu->bezt;
while(a--) {
if( BEZSELECTED_HIDDENHANDLES(bezt) ) {
- if(nu->flagu & CU_CYCLIC) nu->flagu--;
- else nu->flagu++;
+ if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC;
+ else nu->flagu |= CU_CYCLIC;
break;
}
bezt++;
@@ -3027,26 +3045,28 @@ void makecyclicNurb()
calchandlesNurb(nu);
}
else if(nu->pntsv==1 && (nu->type & 7)==CU_NURBS) {
- a= nu->pntsu;
- bp= nu->bp;
- while(a--) {
- if( bp->f1 & SELECT ) {
- if(nu->flagu & CU_CYCLIC) nu->flagu--;
- else {
- nu->flagu++;
- nu->flagu &= ~2; /* endpoint flag, fixme */
- fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
- b= (nu->orderu+nu->pntsu);
- memcpy(fp, nu->knotsu, sizeof(float)*b);
- MEM_freeN(nu->knotsu);
- nu->knotsu= fp;
+ if (nu->knotsu) { /* if check_valid_nurb_u fails the knotsu can be NULL */
+ a= nu->pntsu;
+ bp= nu->bp;
+ while(a--) {
+ if( bp->f1 & SELECT ) {
+ if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC;
+ else {
+ nu->flagu |= CU_CYCLIC;
+ nu->flagu &= ~2; /* endpoint flag, fixme */
+ fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
+ b= (nu->orderu+nu->pntsu);
+ memcpy(fp, nu->knotsu, sizeof(float)*b);
+ MEM_freeN(nu->knotsu);
+ nu->knotsu= fp;
- makeknots(nu, 1, 0); /* 1==u 0==uniform */
+ makeknots(nu, 1, 0); /* 1==u 0==uniform */
+ }
+ break;
}
- break;
+ bp++;
}
- bp++;
}
}
else if(nu->type==CU_NURBS) {
@@ -3060,29 +3080,37 @@ void makecyclicNurb()
if( bp->f1 & SELECT) {
if(cyclmode==1 && nu->pntsu>1) {
- if(nu->flagu & CU_CYCLIC) nu->flagu--;
+ if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC;
else {
- nu->flagu++;
- fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
- b= (nu->orderu+nu->pntsu);
- memcpy(fp, nu->knotsu, sizeof(float)*b);
- MEM_freeN(nu->knotsu);
- nu->knotsu= fp;
+ nu->flagu |= CU_CYCLIC;
+ if (check_valid_nurb_u(nu)) {
+ fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
+ b= (nu->orderu+nu->pntsu);
+ if (nu->knotsu) { /* null if check_valid_nurb_u failed before but is valid now */
+ memcpy(fp, nu->knotsu, sizeof(float)*b);
+ MEM_freeN(nu->knotsu);
+ }
+ nu->knotsu= fp;
- makeknots(nu, 1, 0); /* 1==u 0==uniform */
+ makeknots(nu, 1, 0); /* 1==u 0==uniform */
+ }
}
}
if(cyclmode==2 && nu->pntsv>1) {
if(nu->flagv & 1) nu->flagv--;
else {
nu->flagv++;
- fp= MEM_mallocN(sizeof(float)*KNOTSV(nu), "makecyclicN");
- b= (nu->orderv+nu->pntsv);
- memcpy(fp, nu->knotsv, sizeof(float)*b);
- MEM_freeN(nu->knotsv);
- nu->knotsv= fp;
+ if (check_valid_nurb_v(nu)) {
+ fp= MEM_mallocN(sizeof(float)*KNOTSV(nu), "makecyclicN");
+ b= (nu->orderv+nu->pntsv);
+ if (nu->knotsv) { /* null if check_valid_nurb_v failed before but is valid now */
+ memcpy(fp, nu->knotsv, sizeof(float)*b);
+ MEM_freeN(nu->knotsv);
+ }
+ nu->knotsv= fp;
- makeknots(nu, 2, 0); /* 2==v 0==uniform */
+ makeknots(nu, 2, 0); /* 2==v 0==uniform */
+ }
}
}
break;
@@ -3638,7 +3666,7 @@ void delNurb()
}
if(a==0) {
BLI_remlink(&editNurb, nu);
- freeNurb(nu);
+ freeNurb(nu); nu= NULL;
}
}
}
@@ -3654,15 +3682,18 @@ void delNurb()
}
if(a==0) {
BLI_remlink(&editNurb, nu);
- freeNurb(nu);
+ freeNurb(nu); nu= NULL;
}
}
}
- /* Never allow the order to exceed the number of points */
- if ((nu->type & 7)==CU_NURBS && (nu->pntsu < nu->orderu)) {
- nu->orderu = nu->pntsu;
+ /* Never allow the order to exceed the number of points
+ - note, this is ok but changes unselected nurbs, disable for now */
+ /*
+ if ((nu!= NULL) && ((nu->type & 7)==CU_NURBS)) {
+ clamp_nurb_order_u(nu);
}
+ */
nu= next;
}
/* 2nd loop, delete small pieces: just for curves */
@@ -3710,10 +3741,12 @@ void delNurb()
MEM_freeN(nu->bp);
nu->bp= bp1;
- /* Never allow the order to exceed the number of points */
- if ((nu->type & 7)==CU_NURBS && (nu->pntsu < nu->orderu)) {
- nu->orderu = nu->pntsu;
- }
+ /* Never allow the order to exceed the number of points\
+ - note, this is ok but changes unselected nurbs, disable for now */
+ /*
+ if ((nu->type & 7)==CU_NURBS) {
+ clamp_nurb_order_u(nu);
+ }*/
}
makeknots(nu, 1, nu->flagu>>1);
}
@@ -3736,10 +3769,10 @@ void delNurb()
bezt2= bezt+1;
if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) ;
else { /* maybe do not make cyclic */
- if(a==0 && (nu->flagu & 1) ) {
+ if(a==0 && (nu->flagu & CU_CYCLIC) ) {
bezt2= bezt+(nu->pntsu-1);
if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) {
- nu->flagu--;
+ nu->flagu &= ~CU_CYCLIC;
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
@@ -3763,10 +3796,10 @@ void delNurb()
bp2= bp+1;
if( bp2->f1 & 1 ) ;
else { /* maybe do not make cyclic */
- if(a==0 && (nu->flagu & 1) ) {
+ if(a==0 && (nu->flagu & CU_CYCLIC) ) {
bp2= bp+(nu->pntsu-1);
- if( bp2->f1 & 1 ) {
- nu->flagu--;
+ if( bp2->f1 & SELECT ) {
+ nu->flagu &= ~CU_CYCLIC;
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
@@ -3790,16 +3823,16 @@ void delNurb()
if(bezt1) {
if(nu1->pntsu==2) { /* remove completely */
BLI_remlink(&editNurb, nu);
- freeNurb(nu);
+ freeNurb(nu); nu = NULL;
}
- else if(nu1->flagu & 1) { /* cyclic */
+ else if(nu1->flagu & CU_CYCLIC) { /* cyclic */
bezt =
(BezTriple*)MEM_mallocN((cut+1) * sizeof(BezTriple), "delNurb1");
memcpy(bezt, nu1->bezt,(cut+1)*sizeof(BezTriple));
a= nu1->pntsu-cut-1;
memcpy(nu1->bezt, bezt2, a*sizeof(BezTriple));
memcpy(nu1->bezt+a, bezt, (cut+1)*sizeof(BezTriple));
- nu1->flagu--;
+ nu1->flagu &= ~CU_CYCLIC;
MEM_freeN(bezt);
calchandlesNurb(nu);
}
@@ -3832,16 +3865,16 @@ void delNurb()
else if(bp1) {
if(nu1->pntsu==2) { /* remove completely */
BLI_remlink(&editNurb, nu);
- freeNurb(nu);
+ freeNurb(nu); nu= NULL;
}
- else if(nu1->flagu & 1) { /* cyclic */
+ else if(nu1->flagu & CU_CYCLIC) { /* cyclic */
bp =
(BPoint*)MEM_mallocN((cut+1) * sizeof(BPoint), "delNurb5");
memcpy(bp, nu1->bp,(cut+1)*sizeof(BPoint));
a= nu1->pntsu-cut-1;
memcpy(nu1->bp, bp2, a*sizeof(BPoint));
memcpy(nu1->bp+a, bp, (cut+1)*sizeof(BPoint));
- nu1->flagu--;
+ nu1->flagu &= ~CU_CYCLIC;
MEM_freeN(bp);
}
else { /* add new curve */
@@ -4151,7 +4184,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
if((type & 7)==CU_BEZIER) {
nu->pntsu= 4;
nu->bezt= callocstructN(BezTriple, 4, "addNurbprim1");
- nu->flagu= 1;
+ nu->flagu= CU_CYCLIC;
bezt= nu->bezt;
for(a=0;a<3;a++) {
@@ -4200,7 +4233,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
nu->pntsv= 1;
nu->orderu= 4;
nu->bp= callocstructN(BPoint, 8, "addNurbprim6");
- nu->flagu= 1;
+ nu->flagu= CU_CYCLIC;
bp= nu->bp;
for(a=0; a<8; a++) {
@@ -4592,10 +4625,6 @@ static void undoCurve_to_editCurve(void *lbv)
{
ListBase *lb= lbv;
Nurb *nu, *newnu;
- int nr, lastnunr= 0;
-
- /* we try to restore lastnu too, for buttons */
- for(nu= editNurb.first; nu; nu = nu->next, lastnunr++) if(nu==lastnu) break;
freeNurblist(&editNurb);
@@ -4604,9 +4633,6 @@ static void undoCurve_to_editCurve(void *lbv)
newnu= duplicateNurb(nu);
BLI_addtail(&editNurb, newnu);
}
- /* restore */
- for(nr=0, lastnu= editNurb.first; lastnu; lastnu = lastnu->next, nr++) if(nr==lastnunr) break;
-
}
static void *editCurve_to_undoCurve(void)
diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c
index d4ebe181218..f9bb14a08c6 100644
--- a/source/blender/src/editmesh_tools.c
+++ b/source/blender/src/editmesh_tools.c
@@ -4497,8 +4497,7 @@ void bevel_menu() {
while(G.editBMesh->options & BME_BEVEL_RUNNING) {
options = G.editBMesh->options;
res = G.editBMesh->res;
- bm = BME_make_mesh();
- bm = BME_editmesh_to_bmesh(G.editMesh, bm);
+ bm = BME_editmesh_to_bmesh(G.editMesh);
BIF_undo_push("Pre-Bevel");
free_editMesh(G.editMesh);
BME_bevel(bm,0.1f,res,options,0,0,&td);
diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c
index afafc4f2590..9057556b796 100644
--- a/source/blender/src/editnode.c
+++ b/source/blender/src/editnode.c
@@ -166,13 +166,14 @@ static void snode_handle_recalc(SpaceNode *snode)
snode->nodetree->test_break= NULL;
waitcursor(0);
- allqueue(REDRAWNODE, 1);
allqueue(REDRAWIMAGE, 1);
if(G.scene->r.scemode & R_DOCOMP) {
BIF_redraw_render_rect(); /* seems to screwup display? */
mywinset(curarea->win);
}
}
+
+ allqueue(REDRAWNODE, 1);
}
}
diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c
index bb706f1aa3f..fb0fac4489d 100644
--- a/source/blender/src/editseq.c
+++ b/source/blender/src/editseq.c
@@ -184,13 +184,24 @@ int seq_tx_get_end(Sequence *seq)
return seq->start+seq->len;
}
-int seq_tx_get_final_left(Sequence *seq)
+int seq_tx_get_final_left(Sequence *seq, int metaclip)
{
- return (seq->start - seq->startstill) + seq->startofs;
+ if (metaclip && seq->tmp) {
+ /* return the range clipped by the parents range */
+ return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) );
+ } else {
+ return (seq->start - seq->startstill) + seq->startofs;
+ }
+
}
-int seq_tx_get_final_right(Sequence *seq)
+int seq_tx_get_final_right(Sequence *seq, int metaclip)
{
- return ((seq->start+seq->len) + seq->endstill) - seq->endofs;
+ if (metaclip && seq->tmp) {
+ /* return the range clipped by the parents range */
+ return MIN2( seq_tx_get_final_right(seq, 0), seq_tx_get_final_right((Sequence *)seq->tmp, 1) );
+ } else {
+ return ((seq->start+seq->len) + seq->endstill) - seq->endofs;
+ }
}
void seq_tx_set_final_left(Sequence *seq, int val)
@@ -260,12 +271,12 @@ static void fix_single_image_seq(Sequence *seq)
/* make sure the image is always at the start since there is only one,
adjusting its start should be ok */
- left = seq_tx_get_final_left(seq);
+ left = seq_tx_get_final_left(seq, 0);
start = seq->start;
if (start != left) {
offset = left - start;
- seq_tx_set_final_left( seq, seq_tx_get_final_left(seq) - offset );
- seq_tx_set_final_right( seq, seq_tx_get_final_right(seq) - offset );
+ seq_tx_set_final_left( seq, seq_tx_get_final_left(seq, 0) - offset );
+ seq_tx_set_final_right( seq, seq_tx_get_final_right(seq, 0) - offset );
seq->start += offset;
}
}
@@ -2927,34 +2938,34 @@ static int seq_get_snaplimit(void)
static void transform_grab_xlimits(Sequence *seq, int leftflag, int rightflag)
{
if(leftflag) {
- if (seq_tx_get_final_left(seq) >= seq_tx_get_final_right(seq)) {
- seq_tx_set_final_left(seq, seq_tx_get_final_right(seq)-1);
+ if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_final_right(seq, 0)) {
+ seq_tx_set_final_left(seq, seq_tx_get_final_right(seq, 0)-1);
}
if (check_single_seq(seq)==0) {
- if (seq_tx_get_final_left(seq) >= seq_tx_get_end(seq)) {
+ if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_end(seq)) {
seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1);
}
/* dosnt work now - TODO */
/*
- if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq)) {
+ if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) {
int ofs;
- ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq);
+ ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0);
seq->start -= ofs;
- seq_tx_set_final_left(seq, seq_tx_get_final_left(seq) + ofs );
+ seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs );
}*/
}
}
if(rightflag) {
- if (seq_tx_get_final_right(seq) <= seq_tx_get_final_left(seq)) {
- seq_tx_set_final_right(seq, seq_tx_get_final_left(seq)+1);
+ if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_final_left(seq, 0)) {
+ seq_tx_set_final_right(seq, seq_tx_get_final_left(seq, 0)+1);
}
if (check_single_seq(seq)==0) {
- if (seq_tx_get_final_right(seq) <= seq_tx_get_start(seq)) {
+ if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_start(seq)) {
seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1);
}
}
@@ -3033,9 +3044,24 @@ void transform_seq(int mode, int context)
for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK))
totstrip++;
+ /* only needed for extend but can set here anyway since were alredy looping */
+ seq->tmp= NULL;
}
}
+ /* for extending we need the metastrip clipped left/right values, set the metastrips as parents in seq->tmp */
+ if (mode=='e') {
+ Sequence *meta_seq;
+ for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
+ if (seq->type == SEQ_META) {
+ for (meta_seq = seq->seqbase.first; meta_seq; meta_seq= meta_seq->next){
+ meta_seq->tmp= (void *)seq;
+ }
+ }
+ }
+ }
+
+
if (sseq->flag & SEQ_MARKER_TRANS) {
for(marker= G.scene->markers.first; marker; marker= marker->next) {
if(marker->flag & SELECT) totmark++;
@@ -3064,8 +3090,8 @@ void transform_seq(int mode, int context)
/* for extend only */
if (mode=='e') {
- ts->final_left = seq_tx_get_final_left(seq);
- ts->final_right = seq_tx_get_final_right(seq);
+ ts->final_left = seq_tx_get_final_left(seq, 1);
+ ts->final_right = seq_tx_get_final_right(seq, 1);
}
ts++;
}
@@ -3151,9 +3177,9 @@ void transform_seq(int mode, int context)
snap_point_num=0;
if (last_seq && (last_seq->flag & SELECT)) { /* active seq bounds */
if(seq_tx_check_left(last_seq))
- snap_points[snap_point_num++] = seq_tx_get_final_left(last_seq);
+ snap_points[snap_point_num++] = seq_tx_get_final_left(last_seq, 0);
if(seq_tx_check_right(last_seq))
- snap_points[snap_point_num++] = seq_tx_get_final_right(last_seq);
+ snap_points[snap_point_num++] = seq_tx_get_final_right(last_seq, 0);
}
if (totstrip > 1) { /* selection bounds */
@@ -3163,9 +3189,9 @@ void transform_seq(int mode, int context)
for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
if(seq->flag & SELECT) {
if(seq_tx_check_left(seq))
- bounds_left = MIN2(bounds_left, seq_tx_get_final_left(seq));
+ bounds_left = MIN2(bounds_left, seq_tx_get_final_left(seq, 0));
if(seq_tx_check_right(seq))
- bounds_right = MAX2(bounds_right,seq_tx_get_final_right(seq));
+ bounds_right = MAX2(bounds_right,seq_tx_get_final_right(seq, 0));
}
}
@@ -3214,13 +3240,13 @@ void transform_seq(int mode, int context)
if (snap_dist && last_seq && seq_tx_check_left(last_seq)) {
seq = find_next_prev_sequence(last_seq, 1, 0); /* left */
if(seq && !seq_tx_check_right(seq))
- TESTSNAP(seq_tx_get_final_right(seq));
+ TESTSNAP(seq_tx_get_final_right(seq, 0));
}
if (snap_dist && last_seq && seq_tx_check_right(last_seq)) {
seq = find_next_prev_sequence(last_seq, 2, 0); /* right */
if(seq && !seq_tx_check_left(seq))
- TESTSNAP(seq_tx_get_final_left(seq));
+ TESTSNAP(seq_tx_get_final_left(seq, 0));
}
#undef TESTSNAP
@@ -3242,20 +3268,23 @@ void transform_seq(int mode, int context)
for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
int myofs;
+ /* flag, ignores lefsel/rightsel for nested strips */
+ int sel_flag = (seq->depth==0) ? seq->flag : seq->flag & ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
+
// SEQ_DEBUG_INFO(seq);
/* X Transformation */
- if(seq->flag & SEQ_LEFTSEL) {
+ if((seq->depth==0) && (sel_flag & SEQ_LEFTSEL)) {
myofs = (ts->startofs - ts->startstill);
seq_tx_set_final_left(seq, ts->start + (myofs + ix));
}
- if(seq->flag & SEQ_RIGHTSEL) {
+ if((seq->depth==0) && (sel_flag & SEQ_RIGHTSEL)) {
myofs = (ts->endstill - ts->endofs);
seq_tx_set_final_right(seq, ts->start + seq->len + (myofs + ix));
}
- transform_grab_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
+ transform_grab_xlimits(seq, sel_flag & SEQ_LEFTSEL, sel_flag & SEQ_RIGHTSEL);
- if( (seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) {
+ if( (sel_flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) {
if(sequence_is_free_transformable(seq)) seq->start= ts->start+ ix;
/* Y Transformation */
@@ -3300,8 +3329,8 @@ void transform_seq(int mode, int context)
//SEQ_DEBUG_INFO(seq);
- final_left = seq_tx_get_final_left(seq);
- final_right = seq_tx_get_final_right(seq);
+ final_left = seq_tx_get_final_left(seq, 1);
+ final_right = seq_tx_get_final_right(seq, 1);
/* Only X Axis moving */
@@ -3591,8 +3620,8 @@ void seq_separate_images(void)
BLI_remlink(ed->seqbasep, seq);
if(seq->ipo) seq->ipo->id.us--;
- start_ofs = cfra = seq_tx_get_final_left(seq);
- frame_end = seq_tx_get_final_right(seq);
+ start_ofs = cfra = seq_tx_get_final_left(seq, 0);
+ frame_end = seq_tx_get_final_right(seq, 0);
while (cfra < frame_end) {
/* new seq */
diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c
index 9689ffdafeb..2ba5745b19b 100644
--- a/source/blender/src/filesel.c
+++ b/source/blender/src/filesel.c
@@ -1591,7 +1591,7 @@ static void do_filesel_buttons(short event, SpaceFile *sfile)
BLI_del_slash(butname);
if(sfile->type & FILE_UNIX) {
- if (!BLI_exists(butname)) {
+ if (butname[0] != '\0' && !BLI_exists(butname)) {
if (okee("Makedir")) {
BLI_recurdir_fileops(butname);
if (!BLI_exists(butname)) parent(sfile);
diff --git a/source/blender/src/fluidsim.c b/source/blender/src/fluidsim.c
index a7361a9ffca..8b9c89656fb 100644
--- a/source/blender/src/fluidsim.c
+++ b/source/blender/src/fluidsim.c
@@ -481,6 +481,7 @@ void fluidsimBake(struct Object *ob)
struct Object *fsDomain = NULL;
FluidsimSettings *domainSettings;
struct Object *obit = NULL; /* object iterator */
+ Base *base;
int origFrame = G.scene->r.cfra;
char debugStrBuffer[256];
int dirExist = 0;
@@ -522,7 +523,7 @@ void fluidsimBake(struct Object *ob)
float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale
float *channelObjInivel[256]; // initial velocities
float *channelObjActive[256]; // obj active channel
-
+
if(getenv(strEnvName)) {
int dlevel = atoi(getenv(strEnvName));
elbeemSetDebugLevel(dlevel);
@@ -545,7 +546,6 @@ void fluidsimBake(struct Object *ob)
/* no object pointer, find in selected ones.. */
if(!ob) {
- Base *base;
for(base=G.scene->base.first; base; base= base->next) {
if ( ((base)->flag & SELECT)
// ignore layer setting for now? && ((base)->lay & G.vd->lay)
@@ -561,8 +561,26 @@ void fluidsimBake(struct Object *ob)
if(!ob) return;
}
+ channelObjCount = 0;
+ for(base=G.scene->base.first; base; base= base->next) {
+ obit = base->object;
+ //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
+ if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+ (obit->type==OB_MESH) &&
+ (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH
+ (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE) ) {
+ channelObjCount++;
+ }
+ }
+
+ if (channelObjCount>=255) {
+ pupmenu("Fluidsim Bake Error%t|Cannot bake with more then 256 objects");
+ return;
+ }
+
/* check if there's another domain... */
- for(obit= G.main->object.first; obit; obit= obit->id.next) {
+ for(base=G.scene->base.first; base; base= base->next) {
+ obit = base->object;
if((obit->fluidsimFlag & OB_FLUIDSIM_ENABLE)&&(obit->type==OB_MESH)) {
if(obit->fluidsimSettings->type == OB_FLUIDSIM_DOMAIN) {
if(obit != ob) {
@@ -605,7 +623,8 @@ void fluidsimBake(struct Object *ob)
// check if theres any fluid
// abort baking if not...
- for(obit= G.main->object.first; obit; obit= obit->id.next) {
+ for(base=G.scene->base.first; base; base= base->next) {
+ obit = base->object;
if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
(obit->type==OB_MESH) && (
(obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) ||
@@ -749,7 +768,8 @@ void fluidsimBake(struct Object *ob)
// init obj movement channels
channelObjCount=0;
- for(obit= G.main->object.first; obit; obit= obit->id.next) {
+ for(base=G.scene->base.first; base; base= base->next) {
+ obit = base->object;
//{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
(obit->type==OB_MESH) &&
@@ -952,7 +972,8 @@ void fluidsimBake(struct Object *ob)
// init objects
channelObjCount = 0;
- for(obit= G.main->object.first; obit; obit= obit->id.next) {
+ for(base=G.scene->base.first; base; base= base->next) {
+ obit = base->object;
//{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && // if has to match 3 places! // CHECKMATCH
(obit->type==OB_MESH) &&
diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c
index ab8e53c3cb3..6582866d9a1 100644
--- a/source/blender/src/interface.c
+++ b/source/blender/src/interface.c
@@ -3394,6 +3394,7 @@ static int ui_do_but_HSVCUBE(uiBut *but)
/* we redraw the entire block */
for (bt= but->block->buttons.first; bt; bt= bt->next) {
if(but->poin == bt->poin) VECCOPY(bt->hsv, but->hsv);
+ ui_check_but(bt);
ui_draw_but(bt);
}
ui_block_flush_back(but->block);
diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c
index e27e772edee..0f30aef04df 100644
--- a/source/blender/src/meshtools.c
+++ b/source/blender/src/meshtools.c
@@ -957,6 +957,12 @@ int *mesh_get_x_mirror_faces(Object *ob)
mirrormf.v3= mirrorverts[mf->v1];
mirrormf.v4= (mf->v4)? mirrorverts[mf->v4]: 0;
+ /* make sure v4 is not 0 if a quad */
+ if(mf->v4 && mirrormf.v4==0) {
+ SWAP(int, mirrormf.v1, mirrormf.v3);
+ SWAP(int, mirrormf.v2, mirrormf.v4);
+ }
+
hashmf= BLI_ghash_lookup(fhash, &mirrormf);
if(hashmf) {
mirrorfaces[a*2]= hashmf - mface;
@@ -1020,7 +1026,7 @@ void objects_bake_render_menu(void)
{
short event;
- event= pupmenu("Bake Selected Meshes %t|Full Render %x1|Ambient Occlusion %x2|Normals %x3|Texture Only %x4|Displacement %x5");
+ event= pupmenu("Bake Selected Meshes %t|Full Render %x1|Ambient Occlusion %x2|Normals %x3|Texture Only %x4|Displacement %x5|Shadow %x6");
if (event < 1) return;
objects_bake_render_ui(event);
}
@@ -1056,7 +1062,8 @@ void objects_bake_render(short event, char **error_msg)
else if(event==2) event= RE_BAKE_AO;
else if(event==3) event= RE_BAKE_NORMALS;
else if(event==4) event= RE_BAKE_TEXTURE;
- else event= RE_BAKE_DISPLACEMENT;
+ else if(event==5) event= RE_BAKE_DISPLACEMENT;
+ else event= RE_BAKE_SHADOW;
if(event==RE_BAKE_AO) {
if(G.scene->world==NULL) {
diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c
index 4c97a8fdbdf..dcceea971f7 100644
--- a/source/blender/src/poseobject.c
+++ b/source/blender/src/poseobject.c
@@ -659,6 +659,10 @@ void pose_copy_menu(void)
free_constraints(&pchan->constraints);
copy_constraints(&pchan->constraints, &pchanact->constraints);
pchan->constflag = pchanact->constflag;
+
+ if (ob->pose) {
+ ob->pose->flag |= POSE_RECALC;
+ }
}
break;
case 6: /* Transform Locks */
@@ -741,6 +745,10 @@ void pose_copy_menu(void)
}
BLI_freelistN(&const_copy);
update_pose_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */
+
+ if (ob->pose) {
+ ob->pose->flag |= POSE_RECALC;
+ }
}
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); // and all its relations
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index 47e3387755b..8cc7e6975b4 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -5121,7 +5121,7 @@ static void init_seqspace(ScrArea *sa)
sseq->v2d.min[0]= 10.0;
sseq->v2d.min[1]= 4.0;
- sseq->v2d.max[0]= 32000.0;
+ sseq->v2d.max[0]= MAXFRAMEF;
sseq->v2d.max[1]= MAXSEQ;
sseq->v2d.minzoom= 0.1f;
diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c
index 5b6af61949f..5f80f14d069 100644
--- a/source/blender/src/toets.c
+++ b/source/blender/src/toets.c
@@ -228,8 +228,8 @@ void persptoetsen(unsigned short event)
}
else {
/* Indicate that this view is not inverted.
- * Don't do this for PADMINUS/PADPLUSKEY, though. (jobbe)*/
- if (event != PADMINUS && event != PADPLUSKEY)
+ * Don't do this for PADMINUS/PADPLUSKEY/PAD5, though. (jobbe)*/
+ if (! ELEM3(event, PADMINUS, PADPLUSKEY, PAD5) )
G.vd->flag2 &= ~V3D_OPP_DIRECTION_NAME;
diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c
index 10035c61651..4f6c33b0a64 100644
--- a/source/blender/src/transform.c
+++ b/source/blender/src/transform.c
@@ -135,24 +135,23 @@ static void helpline(TransInfo *t, float *vec)
getmouseco_areawin(mval);
projectFloatView(t, vecrot, cent); // no overflow in extreme cases
- if(cent[0]!=IS_CLIPPED) {
- persp(PERSP_WIN);
-
- glDrawBuffer(GL_FRONT);
-
- BIF_ThemeColor(TH_WIRE);
-
- setlinestyle(3);
- glBegin(GL_LINE_STRIP);
- glVertex2sv(mval);
- glVertex2fv(cent);
- glEnd();
- setlinestyle(0);
-
- persp(PERSP_VIEW);
- bglFlush(); // flush display for frontbuffer
- glDrawBuffer(GL_BACK);
- }
+
+ persp(PERSP_WIN);
+
+ glDrawBuffer(GL_FRONT);
+
+ BIF_ThemeColor(TH_WIRE);
+
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ glVertex2sv(mval);
+ glVertex2fv(cent);
+ glEnd();
+ setlinestyle(0);
+
+ persp(PERSP_VIEW);
+ bglFlush(); // flush display for frontbuffer
+ glDrawBuffer(GL_BACK);
}
@@ -354,8 +353,9 @@ void convertViewVec(TransInfo *t, float *vec, short dx, short dy)
void projectIntView(TransInfo *t, float *vec, int *adr)
{
- if (t->spacetype==SPACE_VIEW3D)
- project_int(vec, adr);
+ if (t->spacetype==SPACE_VIEW3D) {
+ project_int_noclip(vec, adr);
+ }
else if(t->spacetype==SPACE_IMAGE) {
float aspx, aspy, v[2];
@@ -376,8 +376,9 @@ void projectIntView(TransInfo *t, float *vec, int *adr)
void projectFloatView(TransInfo *t, float *vec, float *adr)
{
- if (t->spacetype==SPACE_VIEW3D)
- project_float(vec, adr);
+ if (t->spacetype==SPACE_VIEW3D) {
+ project_float_noclip(vec, adr);
+ }
else if(t->spacetype==SPACE_IMAGE) {
int a[2];
diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c
index f69218664ea..dcebf6b7557 100644
--- a/source/blender/src/transform_conversions.c
+++ b/source/blender/src/transform_conversions.c
@@ -1365,7 +1365,7 @@ static void createTransCurveVerts(TransInfo *t)
tail++;
}
if( propmode ||
- ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
+ ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
) {
VECCOPY(td->iloc, bezt->vec[2]);
@@ -4054,6 +4054,7 @@ void createTransData(TransInfo *t)
t->flag |= T_POINTS;
}
else {
+ t->flag &= ~T_PROP_EDIT; /* no proportional edit in object mode */
createTransObject(t);
t->flag |= T_OBJECT;
}
diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c
index 5c06aaea890..050360887b4 100644
--- a/source/blender/src/transform_manipulator.c
+++ b/source/blender/src/transform_manipulator.c
@@ -158,7 +158,7 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags)
}
/* for pose mode */
-static void stats_pose(View3D *v3d, bPoseChannel *pchan, float *normal, float *plane)
+static void stats_pose(View3D *v3d, bPoseChannel *pchan)
{
Bone *bone= pchan->bone;
@@ -166,9 +166,6 @@ static void stats_pose(View3D *v3d, bPoseChannel *pchan, float *normal, float *p
if (bone->flag & BONE_TRANSFORM) {
calc_tw_center(pchan->pose_head);
protectflag_to_drawflags(pchan->protectflag, &v3d->twdrawflag);
-
- VecAddf(normal, normal, pchan->pose_mat[2]);
- VecAddf(plane, plane, pchan->pose_mat[1]);
}
}
}
@@ -349,26 +346,24 @@ int calc_manipulator_stats(ScrArea *sa)
}
}
else if(ob && (ob->flag & OB_POSEMODE)) {
- bArmature *arm= ob->data;
+ bArmature *arm = ob->data;
bPoseChannel *pchan;
int mode;
if((ob->lay & G.vd->lay)==0) return 0;
- mode= Trans.mode;
- Trans.mode= TFM_ROTATION; // mislead counting bones... bah
+ mode = Trans.mode;
+ Trans.mode = TFM_ROTATION; // mislead counting bones... bah
/* count total, we use same method as transform will do */
Trans.total= 0;
count_bone_select(&Trans, arm, &arm->bonebase, 1);
- totsel= Trans.total;
+ totsel = Trans.total;
if(totsel) {
/* use channels to get stats */
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- stats_pose(v3d, pchan, normal, plane);
+ stats_pose(v3d, pchan);
}
- //VecMulf(normal, -1.0);
- VecMulf(plane, -1.0);
VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid!
Mat4MulVecfl(ob->obmat, G.scene->twcent);
@@ -376,7 +371,7 @@ int calc_manipulator_stats(ScrArea *sa)
Mat4MulVecfl(ob->obmat, G.scene->twmax);
}
/* restore, mode can be TFM_INIT */
- Trans.mode= mode;
+ Trans.mode = mode;
}
else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE)) {
;
@@ -433,7 +428,7 @@ int calc_manipulator_stats(ScrArea *sa)
break;
case V3D_MANIP_NORMAL:
- if(G.obedit) {
+ if(G.obedit || ob->flag & OB_POSEMODE) {
float mat[3][3];
int type;
@@ -479,34 +474,6 @@ int calc_manipulator_stats(ScrArea *sa)
}
break;
}
- /* pose mode is a bit weird, so keep it separated */
- else if (ob->flag & OB_POSEMODE)
- {
- strcpy(t->spacename, "normal");
- if(normal[0]!=0.0 || normal[1]!=0.0 || normal[2]!=0.0) {
- float imat[3][3], mat[3][3];
-
- /* we need the transpose of the inverse for a normal... */
- Mat3CpyMat4(imat, ob->obmat);
-
- Mat3Inv(mat, imat);
- Mat3Transp(mat);
- Mat3MulVecfl(mat, normal);
- Mat3MulVecfl(mat, plane);
-
- Normalize(normal);
- if(0.0==Normalize(plane)) VECCOPY(plane, mat[1]);
-
- VECCOPY(mat[2], normal);
- Crossf(mat[0], normal, plane);
- Crossf(mat[1], mat[2], mat[0]);
-
- Mat4CpyMat3(v3d->twmat, mat);
- Mat4Ortho(v3d->twmat);
-
- break;
- }
- }
/* no break we define 'normal' as 'local' in Object mode */
case V3D_MANIP_LOCAL:
strcpy(t->spacename, "local");
diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c
index 6696fcf95d6..9c7a2f67b89 100644
--- a/source/blender/src/transform_orientations.c
+++ b/source/blender/src/transform_orientations.c
@@ -27,6 +27,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
#include "DNA_curve_types.h"
#include "DNA_listBase.h"
#include "DNA_object_types.h"
@@ -68,11 +69,17 @@ void BIF_clearTransformOrientation(void)
}
void BIF_manageTransformOrientation(int confirm, int set) {
+ Object *ob = OBACT;
int index = -1;
if (G.obedit) {
if (G.obedit->type == OB_MESH)
index = manageMeshSpace(confirm, set);
+ else if (G.obedit->type == OB_ARMATURE)
+ index = manageBoneSpace(confirm, set);
+ }
+ else if (ob && (ob->flag & OB_POSEMODE)) {
+ index = manageBoneSpace(confirm, set);
}
else {
index = manageObjectSpace(confirm, set);
@@ -122,6 +129,31 @@ int confirmSpace(int set, char text[])
}
}
+int manageBoneSpace(int confirm, int set) {
+ float mat[3][3];
+ float normal[3], plane[3];
+ char name[36] = "";
+ int index;
+
+ getTransformOrientation(normal, plane, 0);
+
+ if (confirm == 0 && confirmSpace(set, "Bone") == 0) {
+ return -1;
+ }
+
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ error("Cannot use zero-length bone");
+ return -1;
+ }
+
+ strcpy(name, "Bone");
+
+ /* Input name */
+ sbutton(name, 1, 35, "name: ");
+
+ index = addMatrixSpace(mat, name);
+ return index;
+}
int manageMeshSpace(int confirm, int set) {
float mat[3][3];
@@ -363,6 +395,29 @@ void applyTransformOrientation() {
}
}
+static int count_bone_select(bArmature *arm, ListBase *lb, int do_it)
+{
+ Bone *bone;
+ int do_next;
+ int total = 0;
+
+ for(bone= lb->first; bone; bone= bone->next) {
+ bone->flag &= ~BONE_TRANSFORM;
+ do_next = do_it;
+ if(do_it) {
+ if(bone->layer & arm->layer) {
+ if (bone->flag & BONE_SELECTED) {
+ bone->flag |= BONE_TRANSFORM;
+ total++;
+ do_next= 0; // no transform on children if one parent bone is selected
+ }
+ }
+ }
+ total += count_bone_select(arm, &bone->childbase, do_next);
+ }
+
+ return total;
+}
int getTransformOrientation(float normal[3], float plane[3], int activeOnly)
{
@@ -375,6 +430,14 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly)
if(G.obedit)
{
+ float imat[3][3], mat[3][3];
+
+ /* we need the transpose of the inverse for a normal... */
+ Mat3CpyMat4(imat, ob->obmat);
+
+ Mat3Inv(mat, imat);
+ Mat3Transp(mat);
+
ob= G.obedit;
if(G.obedit->type==OB_MESH)
@@ -639,12 +702,48 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly)
}
}
-
- Mat4Mul3Vecfl(G.obedit->obmat, plane);
- Mat4Mul3Vecfl(G.obedit->obmat, normal);
+
+ /* Vectors from edges don't need the special transpose inverse multiplication */
+ if (result == ORIENTATION_EDGE)
+ {
+ Mat4Mul3Vecfl(ob->obmat, normal);
+ Mat4Mul3Vecfl(ob->obmat, plane);
+ }
+ else
+ {
+ Mat3MulVecfl(mat, normal);
+ Mat3MulVecfl(mat, plane);
+ }
}
else if(ob && (ob->flag & OB_POSEMODE))
{
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ int totsel;
+
+ totsel = count_bone_select(arm, &arm->bonebase, 1);
+ if(totsel) {
+ float imat[3][3], mat[3][3];
+
+ /* use channels to get stats */
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
+ VecAddf(normal, normal, pchan->pose_mat[2]);
+ VecAddf(plane, plane, pchan->pose_mat[1]);
+ }
+ }
+ VecMulf(plane, -1.0);
+
+ /* we need the transpose of the inverse for a normal... */
+ Mat3CpyMat4(imat, ob->obmat);
+
+ Mat3Inv(mat, imat);
+ Mat3Transp(mat);
+ Mat3MulVecfl(mat, normal);
+ Mat3MulVecfl(mat, plane);
+
+ result = ORIENTATION_EDGE;
+ }
}
else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE))
{
diff --git a/source/blender/src/view.c b/source/blender/src/view.c
index 2904ca60a12..f53bcb3a9f7 100644
--- a/source/blender/src/view.c
+++ b/source/blender/src/view.c
@@ -228,6 +228,29 @@ void project_int(float *vec, int *adr)
}
}
+void project_int_noclip(float *vec, int *adr)
+{
+ float fx, fy, vec4[4];
+
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(G.vd->persmat, vec4);
+
+ if( fabs(vec4[3]) > BL_NEAR_CLIP ) {
+ fx = (curarea->winx/2)*(1 + vec4[0]/vec4[3]);
+ fy = (curarea->winy/2)*(1 + vec4[1]/vec4[3]);
+
+ adr[0] = floor(fx);
+ adr[1] = floor(fy);
+ }
+ else
+ {
+ adr[0] = curarea->winx / 2;
+ adr[1] = curarea->winy / 2;
+ }
+}
+
void project_short_noclip(float *vec, short *adr)
{
float fx, fy, vec4[4];
@@ -264,8 +287,28 @@ void project_float(float *vec, float *adr)
Mat4MulVec4fl(G.vd->persmat, vec4);
if( vec4[3]>BL_NEAR_CLIP ) {
- adr[0]= (curarea->winx/2.0)+(curarea->winx/2.0)*vec4[0]/vec4[3];
- adr[1]= (curarea->winy/2.0)+(curarea->winy/2.0)*vec4[1]/vec4[3];
+ adr[0] = (curarea->winx/2.0)+(curarea->winx/2.0)*vec4[0]/vec4[3];
+ adr[1] = (curarea->winy/2.0)+(curarea->winy/2.0)*vec4[1]/vec4[3];
+ }
+}
+
+void project_float_noclip(float *vec, float *adr)
+{
+ float vec4[4];
+
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(G.vd->persmat, vec4);
+
+ if( fabs(vec4[3]) > BL_NEAR_CLIP ) {
+ adr[0] = (curarea->winx/2.0)+(curarea->winx/2.0)*vec4[0]/vec4[3];
+ adr[1] = (curarea->winy/2.0)+(curarea->winy/2.0)*vec4[1]/vec4[3];
+ }
+ else
+ {
+ adr[0] = curarea->winx / 2.0f;
+ adr[1] = curarea->winy / 2.0f;
}
}
@@ -1448,6 +1491,8 @@ void obmat_to_viewmat(Object *ob, short smooth)
float bmat[4][4];
float tmat[3][3];
+ G.vd->view= 0; /* dont show the grid */
+
Mat4CpyMat4(bmat, ob->obmat);
Mat4Ortho(bmat);
Mat4Invert(G.vd->viewmat, bmat);