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:
authorJoseph Eagar <joeedh@gmail.com>2011-02-27 09:19:40 +0300
committerJoseph Eagar <joeedh@gmail.com>2011-02-27 09:19:40 +0300
commitf01261d040be27337db9f9996d648a279c89b7c4 (patch)
treec448230939b3c90d53ce8852dd00925d6052e3a4 /source/blender/blenkernel/intern
parentdcaeda5c4e3a0687251b8511de4f2e8b85ef75c0 (diff)
parent2198cfdb2deec8b2e85e242c74a032f43d0b26ca (diff)
merge with/from trunk at r35190
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/BME_Customdata.c3
-rw-r--r--source/blender/blenkernel/intern/BME_conversions.c5
-rw-r--r--source/blender/blenkernel/intern/BME_eulers.c3
-rw-r--r--source/blender/blenkernel/intern/BME_mesh.c1
-rw-r--r--source/blender/blenkernel/intern/BME_structure.c4
-rw-r--r--source/blender/blenkernel/intern/BME_tools.c26
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c33
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c449
-rw-r--r--source/blender/blenkernel/intern/Makefile156
-rw-r--r--source/blender/blenkernel/intern/action.c71
-rw-r--r--source/blender/blenkernel/intern/anim.c204
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c477
-rw-r--r--source/blender/blenkernel/intern/armature.c353
-rw-r--r--source/blender/blenkernel/intern/blender.c147
-rw-r--r--source/blender/blenkernel/intern/bmesh_private.h2
-rw-r--r--source/blender/blenkernel/intern/bmfont.c3
-rw-r--r--source/blender/blenkernel/intern/boids.c107
-rw-r--r--source/blender/blenkernel/intern/brush.c59
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c49
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c255
-rw-r--r--source/blender/blenkernel/intern/cloth.c144
-rw-r--r--source/blender/blenkernel/intern/collision.c105
-rw-r--r--source/blender/blenkernel/intern/colortools.c42
-rw-r--r--source/blender/blenkernel/intern/constraint.c295
-rw-r--r--source/blender/blenkernel/intern/context.c36
-rw-r--r--source/blender/blenkernel/intern/curve.c234
-rw-r--r--source/blender/blenkernel/intern/customdata.c380
-rw-r--r--source/blender/blenkernel/intern/customdata_file.c5
-rw-r--r--source/blender/blenkernel/intern/deform.c94
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c362
-rw-r--r--source/blender/blenkernel/intern/displist.c168
-rw-r--r--source/blender/blenkernel/intern/editderivedbmesh.c60
-rw-r--r--source/blender/blenkernel/intern/effect.c63
-rw-r--r--source/blender/blenkernel/intern/exotic.c1834
-rw-r--r--source/blender/blenkernel/intern/fcurve.c186
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c9
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c83
-rw-r--r--source/blender/blenkernel/intern/font.c139
-rw-r--r--source/blender/blenkernel/intern/gpencil.c8
-rw-r--r--source/blender/blenkernel/intern/group.c6
-rw-r--r--source/blender/blenkernel/intern/icons.c27
-rwxr-xr-xsource/blender/blenkernel/intern/idcode.c8
-rw-r--r--source/blender/blenkernel/intern/idprop.c32
-rw-r--r--source/blender/blenkernel/intern/image.c334
-rw-r--r--source/blender/blenkernel/intern/image_gen.c10
-rw-r--r--source/blender/blenkernel/intern/implicit.c98
-rw-r--r--source/blender/blenkernel/intern/ipo.c148
-rw-r--r--source/blender/blenkernel/intern/key.c263
-rw-r--r--source/blender/blenkernel/intern/lattice.c95
-rw-r--r--source/blender/blenkernel/intern/library.c160
-rw-r--r--source/blender/blenkernel/intern/material.c206
-rw-r--r--source/blender/blenkernel/intern/mball.c110
-rw-r--r--source/blender/blenkernel/intern/mesh.c175
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c379
-rw-r--r--source/blender/blenkernel/intern/modifier.c50
-rw-r--r--source/blender/blenkernel/intern/multires.c983
-rw-r--r--source/blender/blenkernel/intern/nla.c61
-rw-r--r--source/blender/blenkernel/intern/node.c1952
-rw-r--r--source/blender/blenkernel/intern/object.c340
-rw-r--r--source/blender/blenkernel/intern/packedFile.c42
-rw-r--r--source/blender/blenkernel/intern/paint.c9
-rw-r--r--source/blender/blenkernel/intern/particle.c1342
-rw-r--r--source/blender/blenkernel/intern/particle_system.c1736
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2339
-rw-r--r--source/blender/blenkernel/intern/property.c6
-rw-r--r--source/blender/blenkernel/intern/report.c30
-rw-r--r--source/blender/blenkernel/intern/sca.c27
-rw-r--r--source/blender/blenkernel/intern/scene.c160
-rw-r--r--source/blender/blenkernel/intern/screen.c2
-rw-r--r--source/blender/blenkernel/intern/script.c2
-rwxr-xr-xsource/blender/blenkernel/intern/seqcache.c81
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c430
-rw-r--r--source/blender/blenkernel/intern/sequencer.c1102
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c90
-rw-r--r--source/blender/blenkernel/intern/sketch.c9
-rw-r--r--source/blender/blenkernel/intern/smoke.c429
-rw-r--r--source/blender/blenkernel/intern/softbody.c62
-rw-r--r--source/blender/blenkernel/intern/sound.c31
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c169
-rw-r--r--source/blender/blenkernel/intern/suggestions.c24
-rw-r--r--source/blender/blenkernel/intern/text.c55
-rw-r--r--source/blender/blenkernel/intern/texture.c151
-rw-r--r--source/blender/blenkernel/intern/unit.c304
-rw-r--r--source/blender/blenkernel/intern/world.c13
-rw-r--r--source/blender/blenkernel/intern/writeavi.c14
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c125
-rw-r--r--source/blender/blenkernel/intern/writeframeserver.c26
87 files changed, 11283 insertions, 9618 deletions
diff --git a/source/blender/blenkernel/intern/BME_Customdata.c b/source/blender/blenkernel/intern/BME_Customdata.c
index 139f07c3902..f8b432ed384 100644
--- a/source/blender/blenkernel/intern/BME_Customdata.c
+++ b/source/blender/blenkernel/intern/BME_Customdata.c
@@ -1,5 +1,6 @@
#if 0
/**
+/*
* BME_customdata.c jan 2007
*
* Custom Data functions for Bmesh
@@ -44,7 +45,7 @@
/********************* Layer type information **********************/
typedef struct BME_LayerTypeInfo {
int size;
- char *defaultname;
+ const 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);
diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c
index 439b77db9a6..8c399e88d67 100644
--- a/source/blender/blenkernel/intern/BME_conversions.c
+++ b/source/blender/blenkernel/intern/BME_conversions.c
@@ -1,5 +1,6 @@
#if 0
/**
+/*
* BME_mesh.c jan 2007
*
* BMesh mesh level functions.
@@ -39,10 +40,12 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BLI_edgehash.h"
+#include "BLI_utildefines.h"
+
#include "BKE_mesh.h"
#include "BKE_cdderivedmesh.h"
-#include "BLI_edgehash.h"
//XXX #include "BIF_editmesh.h"
//XXX #include "editmesh.h"
#include "bmesh_private.h"
diff --git a/source/blender/blenkernel/intern/BME_eulers.c b/source/blender/blenkernel/intern/BME_eulers.c
index baa490bbeb5..6897b0c8990 100644
--- a/source/blender/blenkernel/intern/BME_eulers.c
+++ b/source/blender/blenkernel/intern/BME_eulers.c
@@ -1,5 +1,6 @@
#if 0
/**
+/*
* BME_eulers.c jan 2007
*
* BMesh Euler construction API.
@@ -34,7 +35,7 @@
*/
#include "MEM_guardedalloc.h"
-
+#include "BLI_utildefines.h"
#include "bmesh_private.h"
diff --git a/source/blender/blenkernel/intern/BME_mesh.c b/source/blender/blenkernel/intern/BME_mesh.c
index 938b193a433..1097b9da2bc 100644
--- a/source/blender/blenkernel/intern/BME_mesh.c
+++ b/source/blender/blenkernel/intern/BME_mesh.c
@@ -1,5 +1,6 @@
#if 0
/**
+/*
* BME_mesh.c jan 2007
*
* BMesh mesh level functions.
diff --git a/source/blender/blenkernel/intern/BME_structure.c b/source/blender/blenkernel/intern/BME_structure.c
index 53cf93c43af..f79b8edc866 100644
--- a/source/blender/blenkernel/intern/BME_structure.c
+++ b/source/blender/blenkernel/intern/BME_structure.c
@@ -1,5 +1,6 @@
#if 0
/**
+/*
* BME_structure.c jan 2007
*
* Low level routines for manipulating the BMesh structure.
@@ -34,8 +35,9 @@
*/
#if 0
#include <limits.h>
-#include "MEM_guardedalloc.h"
+#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BKE_bmesh.h"
/**
* MISC utility functions.
diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c
index 66df8f2ad6a..9dd4669ba1f 100644
--- a/source/blender/blenkernel/intern/BME_tools.c
+++ b/source/blender/blenkernel/intern/BME_tools.c
@@ -1,5 +1,6 @@
#if 0
/**
+/*
* BME_tools.c jan 2007
*
* Functions for changing the topology of a mesh.
@@ -39,9 +40,14 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BKE_bmesh.h"
#include "BLI_math.h"
+<<<<<<< .working
#include "BLI_cellalloc.h"
+=======
+#include "BLI_utildefines.h"
+>>>>>>> .merge-right.r35190
+
+#include "BKE_bmesh.h"
/*split this all into a seperate bevel.c file in src*/
@@ -109,7 +115,7 @@ float *BME_new_transdata_float(BME_TransData_Head *td) {
return BLI_memarena_alloc(td->ma, sizeof(float));
}
-static int BME_is_nonmanifold_vert(BME_Mesh *bm, BME_Vert *v) {
+static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) {
BME_Edge *e, *oe;
BME_Loop *l;
int len, count, flag;
@@ -219,7 +225,7 @@ static void BME_data_interp_from_verts(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2,
#endif
-static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, BME_Edge *e1, float fac){
+static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *UNUSED(v2), BME_Vert *v, BME_Edge *e1, float fac){
void *src[2];
float w[2];
BME_Loop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
@@ -358,7 +364,7 @@ static int BME_bevel_get_vec(float *vec, BME_Vert *v1, BME_Vert *v2, BME_TransDa
* vec2 is the direction of projection (pointing away from vec1)
* up_vec is used for orientation (expected to be normalized)
* returns the length of the projected vector that lies along vec1 */
-static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *td) {
+static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *UNUSED(td)) {
float factor, vec3[3], tmp[3],c1,c2;
cross_v3_v3v3(tmp,vec1,vec2);
@@ -584,7 +590,7 @@ static float BME_bevel_set_max(BME_Vert *v1, BME_Vert *v2, float value, BME_Tran
return max;
}
-static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int options, BME_TransData_Head *td) {
+static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int UNUSED(options), BME_TransData_Head *td) {
BME_Vert *ov1, *ov2, *v1, *v2;
ov1 = BME_edge_getothervert(v->e, v);
@@ -609,7 +615,7 @@ static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res,
return v1;
}
-static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int options, float *up_vec, BME_TransData_Head *td) {
+static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUSED(options), float *up_vec, BME_TransData_Head *td) {
BME_Vert *v1, *v2, *kv;
BME_Loop *kl=NULL, *nl;
BME_Edge *e;
@@ -710,7 +716,7 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int opti
return l;
}
-static BME_Loop *BME_bevel_vert(BME_Mesh *bm, BME_Loop *l, float value, int options, float *up_vec, BME_TransData_Head *td) {
+static BME_Loop *BME_bevel_vert(BME_Mesh *bm, BME_Loop *l, float value, int UNUSED(options), float *up_vec, BME_TransData_Head *td) {
BME_Vert *v1, *v2;
BME_Poly *f;
@@ -861,7 +867,7 @@ static void BME_bevel_add_vweight(BME_TransData_Head *td, BME_Mesh *bm, BME_Vert
}
}
-static float BME_bevel_get_angle(BME_Mesh *bm, BME_Edge *e, BME_Vert *v) {
+static float BME_bevel_get_angle(BME_Mesh *UNUSED(bm), BME_Edge *e, BME_Vert *v) {
BME_Vert *v1, *v2;
BME_Loop *l1, *l2;
float vec1[3], vec2[3], vec3[3], vec4[3];
@@ -920,7 +926,7 @@ static int BME_face_sharededges(BME_Poly *f1, BME_Poly *f2){
* Returns -
* A BME_Mesh pointer to the BMesh passed as a parameter.
*/
-static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int defgrp_index, float angle, BME_TransData_Head *td) {
+static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defgrp_index), float angle, BME_TransData_Head *td) {
BME_Vert *v;
BME_Edge *e;
BME_Poly *f;
@@ -1164,7 +1170,7 @@ static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){
//BME_JEKV(bm,v->e,v);
}
}
-static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int defgrp_index, BME_TransData_Head *td) {
+static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int UNUSED(defgrp_index), BME_TransData_Head *td) {
BME_Vert *v, *nv;
BME_Edge *e, *oe;
BME_Loop *l, *l2;
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index bbd68fb797b..3564c93681a 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -15,6 +15,13 @@
#define CCG_INLINE inline
#endif
+/* copied from BKE_utildefines.h ugh */
+#ifdef __GNUC__
+# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
+#else
+# define UNUSED(x) x
+#endif
+
/* used for normalize_v3 in BLI_math_vector
* float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */
#define EPSILON (1.0e-35f)
@@ -185,13 +192,13 @@ static int _ehashIterator_isStopped(EHashIterator *ehi) {
/***/
-static void *_stdAllocator_alloc(CCGAllocatorHDL a, int numBytes) {
+static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes) {
return malloc(numBytes);
}
-static void *_stdAllocator_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
+static void *_stdAllocator_realloc(CCGAllocatorHDL UNUSED(a), void *ptr, int newSize, int UNUSED(oldSize)) {
return realloc(ptr, newSize);
}
-static void _stdAllocator_free(CCGAllocatorHDL a, void *ptr) {
+static void _stdAllocator_free(CCGAllocatorHDL UNUSED(a), void *ptr) {
free(ptr);
}
@@ -236,13 +243,13 @@ enum {
Vert_eEffected= (1<<0),
Vert_eChanged= (1<<1),
Vert_eSeam= (1<<2),
-} VertFlags;
+} /*VertFlags*/;
enum {
Edge_eEffected= (1<<0),
-} CCGEdgeFlags;
+} /*CCGEdgeFlags*/;
enum {
Face_eEffected= (1<<0),
-} FaceFlags;
+} /*FaceFlags*/;
struct _CCGVert {
CCGVert *next; /* EHData.next */
@@ -390,7 +397,7 @@ static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) {
(e->v1==v && e->v0==vQ))
return e;
}
- return 0;
+ return NULL;
}
static int _vert_isBoundary(CCGVert *v) {
int i;
@@ -592,7 +599,7 @@ static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int e
static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) {
return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset);
}
-void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) {
+static void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) {
float *a = _face_getIFCo(f, lvl, S, x+0, y+0, levels, dataSize);
float *b = _face_getIFCo(f, lvl, S, x+1, y+0, levels, dataSize);
float *c = _face_getIFCo(f, lvl, S, x+1, y+1, levels, dataSize);
@@ -1514,7 +1521,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
}
}
- if (seam && seamEdges < 2)
+ if (seamEdges < 2 || seamEdges != v->numEdges)
seam = 0;
if (!v->numEdges) {
@@ -1942,7 +1949,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
}
- if (seam && seamEdges < 2)
+ if (seamEdges < 2 || seamEdges != v->numEdges)
seam = 0;
if (!v->numEdges) {
@@ -2601,7 +2608,7 @@ float ccgSubSurf_getEdgeCrease(CCGEdge *e) {
/* Face accessors */
-CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *ss, CCGFace *f) {
+CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *UNUSED(ss), CCGFace *f) {
return f->fHDL;
}
int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) {
@@ -2619,14 +2626,14 @@ void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) {
int ccgSubSurf_getFaceNumVerts(CCGFace *f) {
return f->numVerts;
}
-CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *ss, CCGFace *f, int index) {
+CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *UNUSED(ss), CCGFace *f, int index) {
if (index<0 || index>=f->numVerts) {
return NULL;
} else {
return FACE_getVerts(f)[index];
}
}
-CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *ss, CCGFace *f, int index) {
+CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *UNUSED(ss), CCGFace *f, int index) {
if (index<0 || index>=f->numVerts) {
return NULL;
} else {
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index c9a1cfc4618..05c06e86cd0 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -44,6 +44,7 @@
#include "BLI_memarena.h"
#include "BLI_array.h"
#include "BLI_pbvh.h"
+#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_displist.h"
@@ -53,11 +54,12 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_texture.h"
-#include "BKE_utildefines.h"
+#include "BKE_multires.h"
#include "BKE_particle.h"
#include "BKE_tessmesh.h"
#include "BKE_bvhutils.h"
+
#include "BLO_sys_types.h" // for intptr_t support
#include "BIF_gl.h"
@@ -68,6 +70,8 @@
#include "GPU_extensions.h"
#include "GPU_material.h"
+#include "ED_sculpt.h" /* for ED_sculpt_modifiers_changed */
+
///////////////////////////////////
///////////////////////////////////
@@ -398,6 +402,15 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me)
if(!CustomData_has_layer(&tmp.pdata, CD_MPOLY))
dm_add_polys_from_iter(&tmp.ldata, &tmp.pdata, dm, totloop);
+ /* object had got displacement layer, should copy this layer to save sculpted data */
+ /* NOTE: maybe some other layers should be copied? nazgul */
+ if(CustomData_has_layer(&me->fdata, CD_MDISPS)) {
+ if (totface == me->totface) {
+ MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
+ CustomData_add_layer(&tmp.fdata, CD_MDISPS, CD_DUPLICATE, mdisps, totface);
+ }
+ }
+
mesh_update_customdata_pointers(&tmp);
CustomData_free(&me->vdata, me->totvert);
@@ -637,7 +650,7 @@ void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
}
///
-static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
+DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3])
{
DerivedMesh *dm = CDDM_from_mesh(me, ob);
@@ -670,11 +683,11 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier
float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0);
- dm = getMeshDerivedMesh(me, ob, deformedVerts);
+ dm = mesh_create_derived(me, ob, deformedVerts);
MEM_freeN(deformedVerts);
} else {
- DerivedMesh *tdm = getMeshDerivedMesh(me, ob, NULL);
+ DerivedMesh *tdm = mesh_create_derived(me, ob, NULL);
dm = mti->applyModifier(md, ob, tdm, 0, 0);
if(tdm != dm) tdm->release(tdm);
@@ -920,17 +933,32 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
DerivedMesh *dm, *orcodm, *clothorcodm, *finaldm;
int numVerts = me->totvert;
int required_mode;
+ int isPrevDeform= FALSE;
+ int skipVirtualArmature = (useDeform < 0);
+ MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0);
+ int has_multires = mmd != NULL, multires_applied = 0;
+ int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt;
+
+ if(mmd && !mmd->sculptlvl)
+ has_multires = 0;
+
+ if(!skipVirtualArmature) {
+ firstmd = modifiers_getVirtualModifierList(ob);
+ }
+ else {
+ /* game engine exception */
+ firstmd = ob->modifiers.first;
+ if(firstmd && firstmd->type == eModifierType_Armature)
+ firstmd = firstmd->next;
+ }
- md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob);
+ md = firstmd;
modifiers_clearErrors(ob);
if(useRenderParams) required_mode = eModifierMode_Render;
else required_mode = eModifierMode_Realtime;
- /* we always want to keep original indices */
- dataMask |= CD_MASK_ORIGINDEX;
-
datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode);
curr = datamasks;
@@ -996,13 +1024,18 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene= scene;
-
+
if(!modifier_isEnabled(scene, md, required_mode)) continue;
if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
modifier_setError(md, "Modifier requires original data, bad stack position.");
continue;
}
+ if(sculpt_mode && (!has_multires || multires_applied))
+ if(mti->type != eModifierTypeType_OnlyDeform || multires_applied) {
+ modifier_setError(md, "Not supported in sculpt mode.");
+ continue;
+ }
if(needMapping && !modifier_supportsMapping(md)) continue;
if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
@@ -1037,10 +1070,26 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
}
+ /* if this is not the last modifier in the stack then recalculate the normals
+ * to avoid giving bogus normals to the next modifier see: [#23673] */
+ if(isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+ /* XXX, this covers bug #23673, but we may need normal calc for other types */
+ if(dm->type == DM_TYPE_CDDM) {
+ CDDM_apply_vert_coords(dm, deformedVerts);
+ CDDM_calc_normals(dm);
+ }
+ }
+
mti->deformVerts(md, ob, dm, deformedVerts, numVerts, useRenderParams, useDeform);
} else {
DerivedMesh *ndm;
+ /* determine which data layers are needed by following modifiers */
+ if(curr->next)
+ nextmask= (CustomDataMask)GET_INT_FROM_POINTER(curr->next->link);
+ else
+ nextmask= dataMask;
+
/* apply vertex coordinates or build a DerivedMesh as necessary */
if(dm) {
if(deformedVerts) {
@@ -1062,28 +1111,30 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
add_weight_mcol_dm(ob, dm);
- /* constructive modifiers need to have an origindex
- * otherwise they wont have anywhere to copy the data from */
- if(needMapping) {
- int *index, i;
+ /* Constructive modifiers need to have an origindex
+ * otherwise they wont have anywhere to copy the data from.
+ *
+ * Also create ORIGINDEX data if any of the following modifiers
+ * requests it, this way Mirror, Solidify etc will keep ORIGINDEX
+ * data by using generic DM_copy_vert_data() functions.
+ */
+ if(needMapping || (nextmask & CD_MASK_ORIGINDEX)) {
+ int i, *orig;
+
+ /* calc */
DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
- index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
- for(i=0; i<dm->numVertData; i++) *index++= i;
- index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
- for(i=0; i<dm->numEdgeData; i++) *index++= i;
- index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
- for(i=0; i<dm->numPolyData; i++) *index++= i;
+ orig = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
+ for(i=0; i<dm->numVertData; i++) *orig++= i;
+ orig = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
+ for(i=0; i<dm->numEdgeData; i++) *orig++= i;
+ orig = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+ for(i=0; i<dm->numPolyData; i++) *orig++= i;
}
}
- /* determine which data layers are needed by following modifiers */
- if(curr->next)
- nextmask= (CustomDataMask)GET_INT_FROM_POINTER(curr->next->link);
- else
- nextmask= dataMask;
/* set the DerivedMesh to only copy needed data */
mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link);
@@ -1120,7 +1171,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
orcodm= create_orco_dm(ob, me, NULL, CD_ORCO);
nextmask &= ~CD_MASK_ORCO;
- DM_set_only_copy(orcodm, nextmask);
+ DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX);
ndm = mti->applyModifier(md, ob, orcodm, useRenderParams, 0);
if(ndm) {
@@ -1136,7 +1187,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
clothorcodm= create_orco_dm(ob, me, NULL, CD_CLOTH_ORCO);
nextmask &= ~CD_MASK_CLOTH_ORCO;
- DM_set_only_copy(clothorcodm, nextmask);
+ DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX);
ndm = mti->applyModifier(md, ob, clothorcodm, useRenderParams, 0);
if(ndm) {
@@ -1147,9 +1198,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
}
+ isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform);
+
/* grab modifiers until index i */
if((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
break;
+
+ if(sculpt_mode && md->type == eModifierType_Multires)
+ multires_applied = 1;
}
for(md=firstmd; md; md=md->next)
@@ -1204,7 +1260,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
BLI_linklist_free(datamasks, NULL);
}
-static float (*editbmesh_getVertexCos(BMEditMesh *em, int *numVerts_r))[3]
+float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *numVerts_r))[3]
{
int i, numVerts = *numVerts_r = em->bm->totvert;
float (*cos)[3];
@@ -1221,7 +1277,7 @@ static float (*editbmesh_getVertexCos(BMEditMesh *em, int *numVerts_r))[3]
return cos;
}
-static int editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm)
+int editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
@@ -1255,9 +1311,6 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
dm = NULL;
md = modifiers_getVirtualModifierList(ob);
-
- /* we always want to keep original indices */
- dataMask |= CD_MASK_ORIGINDEX;
datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode);
@@ -1295,7 +1348,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
dm->getVertCos(dm, deformedVerts);
} else {
- deformedVerts = editbmesh_getVertexCos(em, &numVerts);
+ deformedVerts = editbmesh_get_vertex_cos(em, &numVerts);
}
}
@@ -1336,7 +1389,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
orcodm= create_orco_dm(ob, ob->data, em, CD_ORCO);
mask &= ~CD_MASK_ORCO;
- DM_set_only_copy(orcodm, mask);
+ DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX);
if (mti->applyModifierEM)
ndm = mti->applyModifierEM(md, ob, em, orcodm);
@@ -1351,9 +1404,11 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
}
/* set the DerivedMesh to only copy needed data */
- DM_set_only_copy(dm, (CustomDataMask)GET_INT_FROM_POINTER(curr->link));
+ mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); /* CD_MASK_ORCO may have been cleared above */
- if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE)
+ DM_set_only_copy(dm, mask | CD_MASK_ORIGINDEX);
+
+ if(mask & CD_MASK_ORIGSPACE)
if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
DM_add_tessface_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
@@ -1448,14 +1503,9 @@ static void clear_mesh_caches(Object *ob)
ob->derivedDeform->release(ob->derivedDeform);
ob->derivedDeform= NULL;
}
- /* we free pbvh on changes, except during sculpt since it can't deal with
- changing PVBH node organization, we hope topology does not change in
- the meantime .. weak */
- if(ob->sculpt && ob->sculpt->pbvh) {
- if(!ob->sculpt->cache) {
- BLI_pbvh_free(ob->sculpt->pbvh);
- ob->sculpt->pbvh= NULL;
- }
+
+ if(ob->sculpt) {
+ ED_sculpt_modifiers_changed(ob);
}
}
@@ -1463,8 +1513,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
{
Object *obact = scene->basact?scene->basact->object:NULL;
int editing = paint_facesel_test(ob);
- /* weight paint and face select need original indicies because of selection buffer drawing */
- int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)) || editing);
+ /* weight paint and face select need original indices because of selection buffer drawing */
+ int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)));
clear_mesh_caches(ob);
@@ -1584,6 +1634,16 @@ DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*ve
return final;
}
+DerivedMesh *mesh_create_derived_physics(Scene *scene, Object *ob, float (*vertCos)[3],
+ CustomDataMask dataMask)
+{
+ DerivedMesh *final;
+
+ mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0);
+
+ return final;
+}
+
DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
float (*vertCos)[3],
CustomDataMask dataMask)
@@ -1685,61 +1745,112 @@ float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
return vertexcosnos;
}
-/* ********* crazyspace *************** */
+/* ******************* GLSL ******************** */
-int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3])
+typedef struct
{
- ModifierData *md;
- DerivedMesh *dm;
- int i, a, numleft = 0, numVerts = 0;
- int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
- float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
+ float * precomputedFaceNormals;
+ MTFace * mtface; // texture coordinates
+ MFace * mface; // indices
+ MVert * mvert; // vertices & normals
+ float (*orco)[3];
+ float (*tangent)[4]; // destination
+ int numFaces;
- modifiers_clearErrors(ob);
+} SGLSLMeshToTangent;
- dm = NULL;
- md = modifiers_getVirtualModifierList(ob);
+// interface
+#include "mikktspace.h"
- /* compute the deformation matrices and coordinates for the first
- modifiers with on cage editing that are enabled and support computing
- deform matrices */
- for(i = 0; md && i <= cageIndex; i++, md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+static int GetNumFaces(const SMikkTSpaceContext * pContext)
+{
+ SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ return pMesh->numFaces;
+}
- if(!editbmesh_modifier_is_enabled(scene, md, dm))
- continue;
+static int GetNumVertsOfFace(const SMikkTSpaceContext * pContext, const int face_num)
+{
+ SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ return pMesh->mface[face_num].v4!=0 ? 4 : 3;
+}
- if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
- if(!defmats) {
- dm= getEditDerivedBMesh(em, ob, NULL);
- deformedVerts= editbmesh_getVertexCos(em, &numVerts);
- defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats");
+static void GetPosition(const SMikkTSpaceContext * pContext, float fPos[], const int face_num, const int vert_index)
+{
+ //assert(vert_index>=0 && vert_index<4);
+ SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ unsigned int indices[] = { pMesh->mface[face_num].v1, pMesh->mface[face_num].v2,
+ pMesh->mface[face_num].v3, pMesh->mface[face_num].v4 };
+ VECCOPY(fPos, pMesh->mvert[indices[vert_index]].co);
+}
- for(a=0; a<numVerts; a++)
- unit_m3(defmats[a]);
- }
+static void GetTextureCoordinate(const SMikkTSpaceContext * pContext, float fUV[], const int face_num, const int vert_index)
+{
+ //assert(vert_index>=0 && vert_index<4);
+ SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats,
- numVerts);
- }
- else
- break;
+ if(pMesh->mtface!=NULL)
+ {
+ float * uv = pMesh->mtface[face_num].uv[vert_index];
+ fUV[0]=uv[0]; fUV[1]=uv[1];
}
+ else
+ {
+ unsigned int indices[] = { pMesh->mface[face_num].v1, pMesh->mface[face_num].v2,
+ pMesh->mface[face_num].v3, pMesh->mface[face_num].v4 };
- for(; md && i <= cageIndex; md = md->next, i++)
- if(editbmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md))
- numleft++;
+ map_to_sphere( &fUV[0], &fUV[1],pMesh->orco[indices[vert_index]][0], pMesh->orco[indices[vert_index]][1], pMesh->orco[indices[vert_index]][2]);
+ }
+}
- if(dm)
- dm->release(dm);
-
- *deformmats= defmats;
- *deformcos= deformedVerts;
+static void GetNormal(const SMikkTSpaceContext * pContext, float fNorm[], const int face_num, const int vert_index)
+{
+ //assert(vert_index>=0 && vert_index<4);
+ SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ unsigned int indices[] = { pMesh->mface[face_num].v1, pMesh->mface[face_num].v2,
+ pMesh->mface[face_num].v3, pMesh->mface[face_num].v4 };
- return numleft;
+ const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH);
+ if(!smoothnormal) // flat
+ {
+ if(pMesh->precomputedFaceNormals)
+ {
+ VECCOPY(fNorm, &pMesh->precomputedFaceNormals[3*face_num]);
+ }
+ else
+ {
+ float nor[3];
+ float * p0, * p1, * p2;
+ const int iGetNrVerts = pMesh->mface[face_num].v4!=0 ? 4 : 3;
+ p0 = pMesh->mvert[indices[0]].co; p1 = pMesh->mvert[indices[1]].co; p2 = pMesh->mvert[indices[2]].co;
+ if(iGetNrVerts==4)
+ {
+ float * p3 = pMesh->mvert[indices[3]].co;
+ normal_quad_v3( nor, p0, p1, p2, p3);
+ }
+ else {
+ normal_tri_v3(nor, p0, p1, p2);
+ }
+ VECCOPY(fNorm, nor);
+ }
+ }
+ else
+ {
+ int i=0;
+ short * no = pMesh->mvert[indices[vert_index]].no;
+ for(i=0; i<3; i++)
+ fNorm[i]=no[i]/32767.0f;
+ normalize_v3(fNorm);
+ }
+}
+static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert)
+{
+ //assert(vert_index>=0 && vert_index<4);
+ SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ float * pRes = pMesh->tangent[4*face_num+iVert];
+ VECCOPY(pRes, fvTangent);
+ pRes[3]=fSign;
}
-/* ******************* GLSL ******************** */
void DM_add_tangent_layer(DerivedMesh *dm)
{
@@ -1749,14 +1860,17 @@ void DM_add_tangent_layer(DerivedMesh *dm)
MVert *mvert, *v1, *v2, *v3, *v4;
MemArena *arena= NULL;
VertexTangent **vtangents= NULL;
- float (*orco)[3]= NULL, (*tangent)[3];
+ float (*orco)[3]= NULL, (*tangent)[4];
float *uv1, *uv2, *uv3, *uv4, *vtang;
float fno[3], tang[3], uv[4][2];
- int i, j, len, mf_vi[4], totvert, totface;
+ int i, j, len, mf_vi[4], totvert, totface, iCalcNewMethod;
+ float *nors;
if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
return;
+ nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
+
/* check we have all the needed layers */
totvert= dm->getNumVerts(dm);
totface= dm->getNumTessFaces(dm);
@@ -1779,79 +1893,108 @@ void DM_add_tangent_layer(DerivedMesh *dm)
arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "tangent layer arena");
BLI_memarena_use_calloc(arena);
vtangents= MEM_callocN(sizeof(VertexTangent*)*totvert, "VertexTangent");
-
- /* sum tangents at connected vertices */
- for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) {
- v1= &mvert[mf->v1];
- v2= &mvert[mf->v2];
- v3= &mvert[mf->v3];
-
- if (mf->v4) {
- v4= &mvert[mf->v4];
- normal_quad_v3( fno,v4->co, v3->co, v2->co, v1->co);
- }
- else {
- v4= NULL;
- normal_tri_v3( fno,v3->co, v2->co, v1->co);
- }
-
- if(mtface) {
- uv1= tf->uv[0];
- uv2= tf->uv[1];
- uv3= tf->uv[2];
- uv4= tf->uv[3];
- }
- else {
- uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
- map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]);
- map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]);
- map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]);
- if(v4)
- map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]);
- }
+
+ // new computation method
+ iCalcNewMethod = 1;
+ if(iCalcNewMethod!=0)
+ {
+ SGLSLMeshToTangent mesh2tangent;
+ SMikkTSpaceContext sContext;
+ SMikkTSpaceInterface sInterface;
+ memset(&mesh2tangent, 0, sizeof(SGLSLMeshToTangent));
+ memset(&sContext, 0, sizeof(SMikkTSpaceContext));
+ memset(&sInterface, 0, sizeof(SMikkTSpaceInterface));
+
+ mesh2tangent.precomputedFaceNormals = nors;
+ mesh2tangent.mtface = mtface;
+ mesh2tangent.mface = mface;
+ mesh2tangent.mvert = mvert;
+ mesh2tangent.orco = orco;
+ mesh2tangent.tangent = tangent;
+ mesh2tangent.numFaces = totface;
+
+ sContext.m_pUserData = &mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = GetNumVertsOfFace;
+ sInterface.m_getPosition = GetPosition;
+ sInterface.m_getTexCoord = GetTextureCoordinate;
+ sInterface.m_getNormal = GetNormal;
+ sInterface.m_setTSpaceBasic = SetTSpace;
+
+ // 0 if failed
+ iCalcNewMethod = genTangSpaceDefault(&sContext);
+ }
+
+ if(!iCalcNewMethod)
+ {
+ /* sum tangents at connected vertices */
+ for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) {
+ v1= &mvert[mf->v1];
+ v2= &mvert[mf->v2];
+ v3= &mvert[mf->v3];
+
+ if (mf->v4) {
+ v4= &mvert[mf->v4];
+ normal_quad_v3( fno,v4->co, v3->co, v2->co, v1->co);
+ }
+ else {
+ v4= NULL;
+ normal_tri_v3( fno,v3->co, v2->co, v1->co);
+ }
- tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang);
- sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
- sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2);
- sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
+ if(mtface) {
+ uv1= tf->uv[0];
+ uv2= tf->uv[1];
+ uv3= tf->uv[2];
+ uv4= tf->uv[3];
+ }
+ else {
+ uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
+ map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]);
+ map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]);
+ map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]);
+ if(v4)
+ map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]);
+ }
- if(mf->v4) {
- v4= &mvert[mf->v4];
-
- tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang);
+ tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang);
sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
+ sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2);
sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
- sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4);
- }
- }
-
- /* write tangent to layer */
- for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) {
- len= (mf->v4)? 4 : 3;
- if(mtface) {
- uv1= tf->uv[0];
- uv2= tf->uv[1];
- uv3= tf->uv[2];
- uv4= tf->uv[3];
- }
- else {
- uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
- map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]);
- map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]);
- map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]);
- if(len==4)
- map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]);
+ if(mf->v4) {
+ v4= &mvert[mf->v4];
+
+ tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang);
+ sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
+ sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
+ sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4);
+ }
}
+
+ /* write tangent to layer */
+ for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) {
+ len= (mf->v4)? 4 : 3;
+
+ if(mtface == NULL) {
+ map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]);
+ map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]);
+ map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]);
+ if(len==4)
+ map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]);
+ }
- mf_vi[0]= mf->v1;
- mf_vi[1]= mf->v2;
- mf_vi[2]= mf->v3;
- mf_vi[3]= mf->v4;
+ mf_vi[0]= mf->v1;
+ mf_vi[1]= mf->v2;
+ mf_vi[2]= mf->v3;
+ mf_vi[3]= mf->v4;
- for(j=0; j<len; j++) {
- vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]);
- normalize_v3_v3(tangent[j], vtang);
+ for(j=0; j<len; j++) {
+ vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]);
+ normalize_v3_v3(tangent[j], vtang);
+ ((float *) tangent[j])[3]=1.0f;
+ }
}
}
diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile
deleted file mode 100644
index 53a9999758c..00000000000
--- a/source/blender/blenkernel/intern/Makefile
+++ /dev/null
@@ -1,156 +0,0 @@
-#
-# $Id$
-#
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): none yet.
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-#
-
-LIBNAME = blenkernel
-DIR = $(OCGDIR)/blender/$(LIBNAME)
-
-include nan_compile.mk
-
-CFLAGS += $(LEVEL_1_C_WARNINGS)
-
-# OpenGL and Python
-CPPFLAGS += -I$(NAN_GLEW)/include
-CPPFLAGS += -I$(OPENGL_HEADERS)
-CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
-
-CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
-CPPFLAGS += -I../../../../intern/memutil
-CPPFLAGS += -I$(NAN_AUDASPACE)/include
-# Reference to the types in makesdna and imbuf
-CPPFLAGS += -I../../makesdna
-CPPFLAGS += -I../../makesrna
-CPPFLAGS += -I../../imbuf
-CPPFLAGS += -I../../ikplugin
-# This mod uses the BLI and BLO module
-CPPFLAGS += -I../../blenlib
-CPPFLAGS += -I../../blenloader
-CPPFLAGS += -I../../python
-CPPFLAGS += -I../../blenfont
-# This is bad level, remove eventually
-CPPFLAGS += -I../../windowmanager
-# also avi is used
-CPPFLAGS += -I../../avi
-CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
-
-# we still refer to /include a bit...
-CPPFLAGS += -I../../editors/include
-
-# to include the render stuff:
-CPPFLAGS += -I../../render/extern/include
-
-# for sound
-#CPPFLAGS += -I../../../kernel/gen_system
-CPPFLAGS += $(NAN_SDLCFLAGS)
-
-CPPFLAGS += -I$(NAN_IKSOLVER)/include
-CPPFLAGS += -I$(NAN_DECIMATION)/include
-CPPFLAGS += -I$(NAN_ELBEEM)/include
-CPPFLAGS += -I$(NAN_OPENNL)/include
-CPPFLAGS += -I$(NAN_BSP)/include
-CPPFLAGS += -I$(NAN_SMOKE)/include
-
-# path to zlib
-CPPFLAGS += -I$(NAN_ZLIB)/include
-
-#path to nodes
-CPPFLAGS += -I../../nodes
-
-#path to gpu
-CPPFLAGS += -I../../gpu
-
-#modifiers got moved
-CPPFLAGS += -I../../modifiers
-
-# path to our own external headerfiles
-CPPFLAGS += -I..
-
-CPPFLAGS += -I$(NAN_FREETYPE)/include
-CPPFLAGS += -I$(NAN_FREETYPE)/include/freetype2
-
-# path to bullet2, for cloth
-ifeq ($(NAN_USE_BULLET), true)
- CPPFLAGS += -I$(NAN_BULLET2)/include
-endif
-
-# lzo and lzma, for pointcache
-ifeq ($(WITH_LZO),true)
- CPPFLAGS += -I$(NAN_LZO)/minilzo
- CPPFLAGS += -DWITH_LZO
-endif
-
-ifeq ($(WITH_LZO),true)
- CPPFLAGS += -I$(NAN_LZMA)
- CPPFLAGS += -DWITH_LZMA
-endif
-
-ifeq ($(WITH_FFMPEG),true)
- CPPFLAGS += -DWITH_FFMPEG
- CPPFLAGS += $(NAN_FFMPEGCFLAGS)
-endif
-
-ifeq ($(WITH_OPENEXR), true)
- CPPFLAGS += -DWITH_OPENEXR
-endif
-
-ifeq ($(WITH_DDS), true)
- CPPFLAGS += -DWITH_DDS
-endif
-
-ifeq ($(WITH_OPENJPEG), true)
- CPPFLAGS += -DWITH_OPENJPEG
-endif
-
-ifeq ($(WITH_QUICKTIME), true)
- CPPFLAGS += -I../../quicktime
- CPPFLAGS += -DWITH_QUICKTIME
-endif
-
-ifeq ($(WITH_TIFF), true)
- CPPFLAGS += -DWITH_TIFF
-endif
-
-ifeq ($(WITH_CINEON), true)
- CPPFLAGS += -DWITH_CINEON
-endif
-
-ifeq ($(WITH_HDR), true)
- CPPFLAGS += -DWITH_HDR
-endif
-
-ifeq ($(OS), darwin)
- ifeq ($(WITH_BF_OPENMP), true)
- CPPFLAGS += -DPARALLEL=1
- endif
-endif
-
-ifeq ($(WITH_LCMS), true)
- CPPFLAGS += -DWITH_LCMS
- CPPFLAGS += -I$(BF_LCMS_INC)
-endif
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 90a3a6ce664..14a0f71f824 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -39,6 +39,11 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_anim.h"
@@ -48,15 +53,11 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_utildefines.h"
+
#include "BKE_idprop.h"
#include "BIK_api.h"
-#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
-#include "BLI_math.h"
-
#include "RNA_access.h"
/* *********************** NOTE ON POSE AND ACTION **********************
@@ -92,12 +93,11 @@ void make_local_action(bAction *act)
bAction *actn;
int local=0, lib=0;
- if (act->id.lib==0) return;
+ if (act->id.lib==NULL) return;
if (act->id.us==1) {
- act->id.lib= 0;
+ act->id.lib= NULL;
act->id.flag= LIB_LOCAL;
- //make_local_action_channels(act);
- new_id(0, (ID *)act, 0);
+ new_id(NULL, (ID *)act, NULL);
return;
}
@@ -113,10 +113,10 @@ void make_local_action(bAction *act)
#endif
if(local && lib==0) {
- act->id.lib= 0;
+ act->id.lib= NULL;
act->id.flag= LIB_LOCAL;
//make_local_action_channels(act);
- new_id(0, (ID *)act, 0);
+ new_id(NULL, (ID *)act, NULL);
}
else if(local && lib) {
actn= copy_action(act);
@@ -376,6 +376,20 @@ bActionGroup *action_groups_find_named (bAction *act, const char name[])
return BLI_findstring(&act->groups, name, offsetof(bActionGroup, name));
}
+/* Clear all 'temp' flags on all groups */
+void action_groups_clear_tempflags (bAction *act)
+{
+ bActionGroup *agrp;
+
+ /* sanity checks */
+ if (ELEM(NULL, act, act->groups.first))
+ return;
+
+ /* flag clearing loop */
+ for (agrp = act->groups.first; agrp; agrp = agrp->next)
+ agrp->flag &= ~AGRP_TEMP;
+}
+
/* *************** Pose channels *************** */
/* usually used within a loop, so we got a N^2 slowdown */
@@ -408,9 +422,10 @@ bPoseChannel *verify_pose_channel(bPose *pose, const char *name)
/* If not, create it and add it */
chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
- strncpy(chan->name, name, 31);
+ BLI_strncpy(chan->name, name, sizeof(chan->name));
/* init vars to prevent math errors */
- chan->quat[0] = chan->rotAxis[1]= 1.0f;
+ unit_qt(chan->quat);
+ unit_axis_angle(chan->rotAxis, &chan->rotAngle);
chan->size[0] = chan->size[1] = chan->size[2] = 1.0f;
chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f;
@@ -774,7 +789,7 @@ void pose_add_group (Object *ob)
return;
grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup");
- strcpy(grp->name, "Group");
+ BLI_strncpy(grp->name, "Group", sizeof(grp->name));
BLI_addtail(&pose->agroups, grp);
BLI_uniquename(&pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name));
@@ -1027,7 +1042,6 @@ void extract_pose_from_pose(bPose *pose, const bPose *src)
void rest_pose(bPose *pose)
{
bPoseChannel *pchan;
- int i;
if (!pose)
return;
@@ -1036,16 +1050,12 @@ void rest_pose(bPose *pose)
memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset));
for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) {
- for (i=0; i<3; i++) {
- pchan->loc[i]= 0.0f;
- pchan->quat[i+1]= 0.0f;
- pchan->eul[i]= 0.0f;
- pchan->size[i]= 1.0f;
- pchan->rotAxis[i]= 0.0f;
- }
- pchan->quat[0]= pchan->rotAxis[1]= 1.0f;
- pchan->rotAngle= 0.0f;
-
+ zero_v3(pchan->loc);
+ zero_v3(pchan->eul);
+ unit_qt(pchan->quat);
+ unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+ pchan->size[0]= pchan->size[1]= pchan->size[2]= 1.0f;
+
pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
}
}
@@ -1091,7 +1101,7 @@ void copy_pose_result(bPose *to, bPose *from)
/* For the calculation of the effects of an Action at the given frame on an object
* This is currently only used for the Action Constraint
*/
-void what_does_obaction (Scene *scene, Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe)
+void what_does_obaction (Scene *UNUSED(scene), Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe)
{
bActionGroup *agrp= action_groups_find_named(act, groupname);
@@ -1119,8 +1129,8 @@ void what_does_obaction (Scene *scene, Object *ob, Object *workob, bPose *pose,
workob->pose= pose; /* need to set pose too, since this is used for both types of Action Constraint */
- strcpy(workob->parsubstr, ob->parsubstr);
- strcpy(workob->id.name, "OB<ConstrWorkOb>"); /* we don't use real object name, otherwise RNA screws with the real thing */
+ BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr));
+ BLI_strncpy(workob->id.name, "OB<ConstrWorkOb>", sizeof(workob->id.name)); /* we don't use real object name, otherwise RNA screws with the real thing */
/* if we're given a group to use, it's likely to be more efficient (though a bit more dangerous) */
if (agrp) {
@@ -1134,10 +1144,9 @@ void what_does_obaction (Scene *scene, Object *ob, Object *workob, bPose *pose,
animsys_evaluate_action_group(&id_ptr, act, agrp, NULL, cframe);
}
else {
- AnimData adt;
+ AnimData adt= {NULL};
/* init animdata, and attach to workob */
- memset(&adt, 0, sizeof(AnimData));
workob->adt= &adt;
adt.recalc= ADT_RECALC_ANIM;
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 167ceab23eb..5842197da48 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -1,4 +1,4 @@
-/** anim.c
+/* anim.c
*
*
* $Id$
@@ -39,6 +39,7 @@
#include "BLI_editVert.h"
#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -50,6 +51,7 @@
#include "DNA_view3d_types.h"
#include "DNA_vfont_types.h"
+#include "BKE_animsys.h"
#include "BKE_curve.h"
#include "BKE_DerivedMesh.h"
#include "BKE_depsgraph.h"
@@ -66,6 +68,7 @@
#include "BKE_utildefines.h"
#include "BKE_tessmesh.h"
#include "BKE_depsgraph.h"
+#include "BKE_anim.h"
// XXX bad level call...
@@ -299,7 +302,7 @@ static void motionpaths_calc_update_scene(Scene *scene)
Base *base, *last=NULL;
/* only stuff that moves or needs display still */
- DAG_scene_update_flags(G.main, scene, scene->lay);
+ DAG_scene_update_flags(G.main, scene, scene->lay, TRUE);
/* find the last object with the tag
* - all those afterwards are assumed to not be relevant for our calculations
@@ -439,6 +442,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
/* free curve path data
* NOTE: frees the path itself!
+ * NOTE: this is increasingly innacurate with non-uniform BevPoint subdivisions [#24633]
*/
void free_path(Path *path)
{
@@ -447,7 +451,7 @@ void free_path(Path *path)
}
/* calculate a curve-deform path for a curve
- * - only called from displist.c -> makeDispListCurveTypes
+ * - only called from displist.c -> do_makeDispListCurveTypes
*/
void calc_curvepath(Object *ob)
{
@@ -510,7 +514,7 @@ void calc_curvepath(Object *ob)
/* the path verts in path->data */
/* now also with TILT value */
- pp= path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint)*4*path->len, "pathdata"); // XXX - why *4? - in 2.4x each element was 4 and the size was 16, so better leave for now - Campbell
+ pp= path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint)*path->len, "pathdata");
bevp= bevpfirst;
bevpn= bevp+1;
@@ -640,32 +644,21 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat,
vec[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ; /* Y */
vec[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ; /* Z */
vec[3]= data[0]*p0->vec[3] + data[1]*p1->vec[3] + data[2]*p2->vec[3] + data[3]*p3->vec[3] ; /* Tilt, should not be needed since we have quat still used */
- /* Need to verify the quat interpolation is correct - XXX */
if (quat) {
- //float totfac, q1[4], q2[4];
+ float totfac, q1[4], q2[4];
- /* checks for totfac are needed when 'fac' is 1.0 key_curve_position_weights can assign zero
- * to more then one index in data which can give divide by zero error */
-/*
- totfac= data[0]+data[1];
- if(totfac>0.000001) interp_qt_qtqt(q1, p0->quat, p1->quat, data[0] / totfac);
- else QUATCOPY(q1, p1->quat);
+ totfac= data[0]+data[3];
+ if(totfac>FLT_EPSILON) interp_qt_qtqt(q1, p0->quat, p3->quat, data[3] / totfac);
+ else QUATCOPY(q1, p1->quat);
- normalize_qt(q1);
-
- totfac= data[2]+data[3];
- if(totfac>0.000001) interp_qt_qtqt(q2, p2->quat, p3->quat, data[2] / totfac);
- else QUATCOPY(q1, p3->quat);
- normalize_qt(q2);
+ totfac= data[1]+data[2];
+ if(totfac>FLT_EPSILON) interp_qt_qtqt(q2, p1->quat, p2->quat, data[2] / totfac);
+ else QUATCOPY(q2, p3->quat);
totfac = data[0]+data[1]+data[2]+data[3];
- if(totfac>0.000001) interp_qt_qtqt(quat, q1, q2, (data[0]+data[1]) / totfac);
- else QUATCOPY(quat, q2);
- normalize_qt(quat);
- */
- // XXX - find some way to make quat interpolation work correctly, above code fails in rare but nasty cases.
- QUATCOPY(quat, p1->quat);
+ if(totfac>FLT_EPSILON) interp_qt_qtqt(quat, q1, q2, (data[1]+data[2]) / totfac);
+ else QUATCOPY(quat, q2);
}
if(radius)
@@ -753,41 +746,69 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, i
static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated)
{
extern int enable_cu_speed; /* object.c */
- Object copyob;
- DupliObject *dob;
- int cfrao, ok;
+ Object copyob = {{NULL}};
+ int cfrao = scene->r.cfra;
- /* simple preventing of too deep nested groups */
- if(level>MAX_DUPLI_RECUR) return;
+ /* simple prevention of too deep nested groups */
+ if (level > MAX_DUPLI_RECUR) return;
- cfrao= scene->r.cfra;
- if(ob->parent==NULL && ob->constraints.first==NULL) return;
-
- if(ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0;
- copyob= *ob; /* store transform info */
-
- for(scene->r.cfra= ob->dupsta; scene->r.cfra<=ob->dupend; scene->r.cfra++) {
-
- ok= 1;
- if(ob->dupoff) {
+ /* if we don't have any data/settings which will lead to object movement,
+ * don't waste time trying, as it will all look the same...
+ */
+ if (ob->parent==NULL && ob->constraints.first==NULL && ob->adt==NULL)
+ return;
+
+ /* make a copy of the object's original data (before any dupli-data overwrites it)
+ * as we'll need this to keep track of unkeyed data
+ * - this doesn't take into account other data that can be reached from the object,
+ * for example it's shapekeys or bones, hence the need for an update flush at the end
+ */
+ copyob = *ob;
+
+ /* duplicate over the required range */
+ if (ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0;
+
+ for (scene->r.cfra= ob->dupsta; scene->r.cfra<=ob->dupend; scene->r.cfra++) {
+ short ok= 1;
+
+ /* - dupoff = how often a frames within the range shouldn't be made into duplis
+ * - dupon = the length of each "skipping" block in frames
+ */
+ if (ob->dupoff) {
ok= scene->r.cfra - ob->dupsta;
ok= ok % (ob->dupon+ob->dupoff);
- if(ok < ob->dupon) ok= 1;
- else ok= 0;
+ ok= (ok < ob->dupon);
}
- if(ok) {
-#if 0 // XXX old animation system
- do_ob_ipo(scene, ob);
-#endif // XXX old animation system
+
+ if (ok) {
+ DupliObject *dob;
+
+ /* WARNING: doing animation updates in this way is not terribly accurate, as the dependencies
+ * and/or other objects which may affect this object's transforms are not updated either.
+ * However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine!
+ */
+ BKE_animsys_evaluate_animdata(&ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
where_is_object_time(scene, ob, (float)scene->r.cfra);
+
dob= new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, OB_DUPLIFRAMES, animated);
copy_m4_m4(dob->omat, copyob.obmat);
}
}
- *ob= copyob; /* restore transform info */
- scene->r.cfra= cfrao;
enable_cu_speed= 1;
+
+ /* reset frame to original frame, then re-evaluate animation as above
+ * as 2.5 animation data may have far-reaching consequences
+ */
+ scene->r.cfra= cfrao;
+
+ BKE_animsys_evaluate_animdata(&ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
+ where_is_object_time(scene, ob, (float)scene->r.cfra);
+
+ /* but, to make sure unkeyed object transforms are still sane,
+ * let's copy object's original data back over
+ */
+ *ob = copyob;
}
typedef struct vertexDupliData {
@@ -809,6 +830,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n
DupliObject *dob;
vertexDupliData *vdd= userData;
float vec[3], q2[4], mat[3][3], tmat[4][4], obmat[4][4];
+ int origlay;
mul_v3_m4v3(vec, vdd->pmat, co);
sub_v3_v3(vec, vdd->pmat[3]);
@@ -831,7 +853,14 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n
copy_m4_m4(tmat, obmat);
mul_m4_m4m3(obmat, tmat, mat);
}
+
+ origlay = vdd->ob->lay;
+
dob= new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS, vdd->animated);
+
+ /* restore the original layer so that each dupli will have proper dob->origlay */
+ vdd->ob->lay = origlay;
+
if(vdd->orco)
VECCOPY(dob->orco, vdd->orco[index]);
@@ -856,7 +885,8 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
GroupObject * go = NULL;
BMEditMesh *em;
float vec[3], no[3], pmat[4][4];
- int lay, totvert, a, oblay;
+ int totvert, a, oblay;
+ unsigned int lay;
copy_m4_m4(pmat, par->obmat);
@@ -939,6 +969,14 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
vertex_dupli__mapFunc(&vdd, a, vec, no, NULL);
}
}
+ if(sce) {
+ /* Set proper layer in case of scene looping,
+ * in case of groups the object layer will be
+ * changed when it's duplicated due to the
+ * group duplication.
+ */
+ ob->lay = vdd.par->lay;
+ }
break;
}
@@ -1150,33 +1188,37 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated)
{
GroupObject *go;
- Object *ob=0, **oblist=0, obcopy, *obcopylist=0;
+ Object *ob=NULL, **oblist=NULL, obcopy, *obcopylist=NULL;
DupliObject *dob;
ParticleDupliWeight *dw;
- ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)};
ParticleSettings *part;
ParticleData *pa;
- ChildParticle *cpa=0;
+ ChildParticle *cpa=NULL;
ParticleKey state;
ParticleCacheKey *cache;
float ctime, pa_time, scale = 1.0f;
float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0;
float (*obmat)[4], (*oldobmat)[4];
- int lay, a, b, counter, hair = 0;
+ int a, b, counter, hair = 0;
int totpart, totchild, totgroup=0, pa_num;
- if(psys==0) return;
+ int no_draw_flag = PARS_UNEXIST;
+
+ if(psys==NULL) return;
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;
part=psys->part;
- if(part==0)
+ if(part==NULL)
return;
if(!psys_check_enabled(par, psys))
return;
+
+ if(G.rendering == 0)
+ no_draw_flag |= PARS_NO_DISP;
ctime = bsystem_time(scene, par, (float)scene->r.cfra, 0.0);
@@ -1184,9 +1226,13 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
totchild = psys->totchild;
BLI_srandom(31415926 + psys->seed);
-
- lay= scene->lay;
+
if((psys->renderdata || part->draw_as==PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
+ ParticleSimulationData sim= {NULL};
+ sim.scene= scene;
+ sim.ob= par;
+ sim.psys= psys;
+ sim.psmd= psys_get_modifier(par, psys);
/* first check for loops (particle system object used as dupli object) */
if(part->ren_as == PART_DRAW_OB) {
@@ -1268,7 +1314,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) {
if(a<totpart) {
/* handle parent particle */
- if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP))
+ if(pa->flag & no_draw_flag)
continue;
pa_num = pa->num;
@@ -1281,7 +1327,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
pa_num = a;
pa_time = psys->particles[cpa->parent].time;
- size = psys_get_child_size(psys, cpa, ctime, 0);
+ size = psys_get_child_size(psys, cpa, ctime, NULL);
}
/* some hair paths might be non-existent so they can't be used for duplication */
@@ -1312,11 +1358,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
/* hair we handle separate and compute transform based on hair keys */
if(a < totpart) {
cache = psys->pathcache[a];
- psys_get_dupli_path_transform(&sim, pa, 0, cache, pamat, &scale);
+ psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale);
}
else {
cache = psys->childcache[a-totpart];
- psys_get_dupli_path_transform(&sim, 0, cpa, cache, pamat, &scale);
+ psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale);
}
VECCOPY(pamat[3], cache->co);
@@ -1326,12 +1372,16 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
else {
/* first key */
state.time = ctime;
- if(psys_get_particle_state(&sim, a, &state, 0) == 0)
+ if(psys_get_particle_state(&sim, a, &state, 0) == 0) {
continue;
-
- quat_to_mat4( pamat,state.rot);
- VECCOPY(pamat[3], state.co);
- pamat[3][3]= 1.0f;
+ }
+ else {
+ float tquat[4];
+ normalize_qt_qt(tquat, state.rot);
+ quat_to_mat4(pamat, tquat);
+ copy_v3_v3(pamat[3], state.co);
+ pamat[3][3]= 1.0f;
+ }
}
if(part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
@@ -1356,20 +1406,26 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
VECCOPY(vec, obmat[3]);
obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;
- copy_m4_m4(mat, pamat);
+ /* Normal particles and cached hair live in global space so we need to
+ * remove the real emitter's transformation before 2nd order duplication.
+ */
+ if(par_space_mat && GS(id->name) != ID_GR)
+ mul_m4_m4m4(mat, pamat, psys->imat);
+ else
+ copy_m4_m4(mat, pamat);
mul_m4_m4m4(tmat, obmat, mat);
mul_mat3_m4_fl(tmat, size*scale);
- if(part->draw & PART_DRAW_GLOBAL_OB)
- VECADD(tmat[3], tmat[3], vec);
-
if(par_space_mat)
mul_m4_m4m4(mat, tmat, par_space_mat);
else
copy_m4_m4(mat, tmat);
- dob= new_dupli_object(lb, ob, mat, ob->lay, counter, OB_DUPLIPARTS, animated);
+ if(part->draw & PART_DRAW_GLOBAL_OB)
+ VECADD(mat[3], mat[3], vec);
+
+ dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated);
copy_m4_m4(dob->omat, oldobmat);
if(G.rendering)
psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
@@ -1422,7 +1478,7 @@ static Object *find_family_object(Object **obar, char *family, char ch)
static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, int animated)
{
- Object *ob, *obar[256];
+ Object *ob, *obar[256]= {NULL};
Curve *cu;
struct chartrans *ct, *chartransdata;
float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
@@ -1436,10 +1492,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, i
/* in par the family name is stored, use this to find the other objects */
chartransdata= BKE_text_to_curve(scene, par, FO_DUPLI);
- if(chartransdata==0) return;
-
- memset(obar, 0, 256*sizeof(void *));
-
+ if(chartransdata==NULL) return;
+
cu= par->data;
slen= strlen(cu->str);
fsize= cu->fsize;
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 10c2c1801cb..77d0f008c2b 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -37,9 +37,12 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
+#include "DNA_material_types.h"
#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
@@ -47,6 +50,7 @@
#include "BKE_nla.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_library.h"
#include "BKE_utildefines.h"
#include "RNA_access.h"
@@ -70,7 +74,7 @@ short id_type_can_have_animdata (ID *id)
switch (GS(id->name)) {
/* has AnimData */
case ID_OB:
- case ID_ME: case ID_MB: case ID_CU: case ID_AR:
+ case ID_ME: case ID_MB: case ID_CU: case ID_AR: case ID_LT:
case ID_KE:
case ID_PA:
case ID_MA: case ID_TE: case ID_NT:
@@ -175,7 +179,7 @@ void BKE_free_animdata (ID *id)
/* Freeing -------------------------------------------- */
/* Make a copy of the given AnimData - to be used when copying datablocks */
-AnimData *BKE_copy_animdata (AnimData *adt)
+AnimData *BKE_copy_animdata (AnimData *adt, const short do_action)
{
AnimData *dadt;
@@ -185,9 +189,15 @@ AnimData *BKE_copy_animdata (AnimData *adt)
dadt= MEM_dupallocN(adt);
/* make a copy of action - at worst, user has to delete copies... */
- dadt->action= copy_action(adt->action);
- dadt->tmpact= copy_action(adt->tmpact);
-
+ if(do_action) {
+ dadt->action= copy_action(adt->action);
+ dadt->tmpact= copy_action(adt->tmpact);
+ }
+ else {
+ id_us_plus((ID *)dadt->action);
+ id_us_plus((ID *)dadt->tmpact);
+ }
+
/* duplicate NLA data */
copy_nladata(&dadt->nla_tracks, &adt->nla_tracks);
@@ -201,7 +211,7 @@ AnimData *BKE_copy_animdata (AnimData *adt)
return dadt;
}
-int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from)
+int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const short do_action)
{
AnimData *adt;
@@ -213,13 +223,26 @@ int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from)
adt = BKE_animdata_from_id(id_from);
if (adt) {
IdAdtTemplate *iat = (IdAdtTemplate *)id_to;
- iat->adt= BKE_copy_animdata(adt);
+ iat->adt= BKE_copy_animdata(adt, do_action);
}
return 1;
}
-
+void BKE_copy_animdata_id_action(struct ID *id)
+{
+ AnimData *adt= BKE_animdata_from_id(id);
+ if(adt) {
+ if(adt->action) {
+ ((ID *)adt->action)->us--;
+ adt->action= copy_action(adt->action);
+ }
+ if(adt->tmpact) {
+ ((ID *)adt->tmpact)->us--;
+ adt->tmpact= copy_action(adt->tmpact);
+ }
+ }
+}
/* Make Local -------------------------------------------- */
@@ -254,6 +277,176 @@ void BKE_animdata_make_local(AnimData *adt)
make_local_strips(&nlt->strips);
}
+/* Sub-ID Regrouping ------------------------------------------- */
+
+/* helper heuristic for determining if a path is compatible with the basepath
+ * < path: (str) full RNA-path from some data (usually an F-Curve) to compare
+ * < basepath: (str) shorter path fragment to look for
+ * > returns (bool) whether there is a match
+ */
+static short animpath_matches_basepath (const char path[], const char basepath[])
+{
+ /* we need start of path to be basepath */
+ return (path && basepath) && (strstr(path, basepath) == path);
+}
+
+/* Move F-Curves in src action to dst action, setting up all the necessary groups
+ * for this to happen, but only if the F-Curves being moved have the appropriate
+ * "base path".
+ * - This is used when data moves from one datablock to another, causing the
+ * F-Curves to need to be moved over too
+ */
+void action_move_fcurves_by_basepath (bAction *srcAct, bAction *dstAct, const char basepath[])
+{
+ FCurve *fcu, *fcn=NULL;
+
+ /* sanity checks */
+ if ELEM3(NULL, srcAct, dstAct, basepath) {
+ if (G.f & G_DEBUG) {
+ printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n",
+ srcAct, dstAct, basepath);
+ }
+ return;
+ }
+
+ /* clear 'temp' flags on all groups in src, as we'll be needing them later
+ * to identify groups that we've managed to empty out here
+ */
+ action_groups_clear_tempflags(srcAct);
+
+ /* iterate over all src F-Curves, moving over the ones that need to be moved */
+ for (fcu = srcAct->curves.first; fcu; fcu = fcn) {
+ /* store next pointer in case we move stuff */
+ fcn = fcu->next;
+
+ /* should F-Curve be moved over?
+ * - we only need the start of the path to match basepath
+ */
+ if (animpath_matches_basepath(fcu->rna_path, basepath)) {
+ bActionGroup *agrp = NULL;
+
+ /* if grouped... */
+ if (fcu->grp) {
+ /* make sure there will be a matching group on the other side for the migrants */
+ agrp = action_groups_find_named(dstAct, fcu->grp->name);
+
+ if (agrp == NULL) {
+ /* add a new one with a similar name (usually will be the same though) */
+ agrp = action_groups_add_new(dstAct, fcu->grp->name);
+ }
+
+ /* old groups should be tagged with 'temp' flags so they can be removed later
+ * if we remove everything from them
+ */
+ fcu->grp->flag |= AGRP_TEMP;
+ }
+
+ /* perform the migration now */
+ action_groups_remove_channel(srcAct, fcu);
+
+ if (agrp)
+ action_groups_add_channel(dstAct, agrp, fcu);
+ else
+ BLI_addtail(&dstAct->curves, fcu);
+ }
+ }
+
+ /* cleanup groups (if present) */
+ if (srcAct->groups.first) {
+ bActionGroup *agrp, *grp=NULL;
+
+ for (agrp = srcAct->groups.first; agrp; agrp = grp) {
+ grp = agrp->next;
+
+ /* only tagged groups need to be considered - clearing these tags or removing them */
+ if (agrp->flag & AGRP_TEMP) {
+ /* if group is empty and tagged, then we can remove as this operation
+ * moved out all the channels that were formerly here
+ */
+ if (agrp->channels.first == NULL)
+ BLI_freelinkN(&srcAct->groups, agrp);
+ else
+ agrp->flag &= ~AGRP_TEMP;
+ }
+ }
+ }
+}
+
+/* Transfer the animation data from srcID to dstID where the srcID
+ * animation data is based off "basepath", creating new AnimData and
+ * associated data as necessary
+ */
+void BKE_animdata_separate_by_basepath (ID *srcID, ID *dstID, ListBase *basepaths)
+{
+ AnimData *srcAdt=NULL, *dstAdt=NULL;
+ LinkData *ld;
+
+ /* sanity checks */
+ if ELEM(NULL, srcID, dstID) {
+ if (G.f & G_DEBUG)
+ printf("ERROR: no source or destination ID to separate AnimData with\n");
+ return;
+ }
+
+ /* get animdata from src, and create for destination (if needed) */
+ srcAdt = BKE_animdata_from_id(srcID);
+ dstAdt = BKE_id_add_animdata(dstID);
+
+ if ELEM(NULL, srcAdt, dstAdt) {
+ if (G.f & G_DEBUG)
+ printf("ERROR: no AnimData for this pair of ID's\n");
+ return;
+ }
+
+ /* active action */
+ if (srcAdt->action) {
+ /* set up an action if necessary, and name it in a similar way so that it can be easily found again */
+ if (dstAdt->action == NULL) {
+ dstAdt->action = add_empty_action(srcAdt->action->id.name+2);
+ }
+ else if (dstAdt->action == srcAdt->action) {
+ printf("Argh! Source and Destination share animation! ('%s' and '%s' both use '%s') Making new empty action\n",
+ srcID->name, dstID->name, srcAdt->action->id.name);
+
+ // TODO: review this...
+ id_us_min(&dstAdt->action->id);
+ dstAdt->action = add_empty_action(dstAdt->action->id.name+2);
+ }
+
+ /* loop over base paths, trying to fix for each one... */
+ for (ld = basepaths->first; ld; ld = ld->next) {
+ const char *basepath = (const char *)ld->data;
+ action_move_fcurves_by_basepath(srcAdt->action, dstAdt->action, basepath);
+ }
+ }
+
+ /* drivers */
+ if (srcAdt->drivers.first) {
+ FCurve *fcu, *fcn=NULL;
+
+ /* check each driver against all the base paths to see if any should go */
+ for (fcu = srcAdt->drivers.first; fcu; fcu = fcn) {
+ fcn = fcu->next;
+
+ /* try each basepath in turn, but stop on the first one which works */
+ for (ld = basepaths->first; ld; ld = ld->next) {
+ const char *basepath = (const char *)ld->data;
+
+ if (animpath_matches_basepath(fcu->rna_path, basepath)) {
+ /* just need to change lists */
+ BLI_remlink(&srcAdt->drivers, fcu);
+ BLI_addtail(&dstAdt->drivers, fcu);
+
+ // TODO: add depsgraph flushing calls?
+
+ /* can stop now, as moved already */
+ break;
+ }
+ }
+ }
+ }
+}
+
/* Path Validation -------------------------------------------- */
/* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */
@@ -272,7 +465,7 @@ static short check_rna_path_is_valid (ID *owner_id, char *path)
/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate
* NOTE: we assume that oldName and newName have [" "] padding around them
*/
-static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldpath, int verify_paths)
+static char *rna_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, char *oldpath, int verify_paths)
{
char *prefixPtr= strstr(oldpath, prefix);
char *oldNamePtr= strstr(oldpath, oldName);
@@ -330,7 +523,7 @@ static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, cha
}
/* Check RNA-Paths for a list of F-Curves */
-static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths)
+static void fcurves_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths)
{
FCurve *fcu;
@@ -343,7 +536,7 @@ static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName,
}
/* Check RNA-Paths for a list of Drivers */
-static void drivers_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldKey, char *newKey, ListBase *curves, int verify_paths)
+static void drivers_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, char *oldKey, char *newKey, ListBase *curves, int verify_paths)
{
FCurve *fcu;
@@ -383,7 +576,7 @@ static void drivers_path_rename_fix (ID *owner_id, char *prefix, char *oldName,
}
/* Fix all RNA-Paths for Actions linked to NLA Strips */
-static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths)
+static void nlastrips_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths)
{
NlaStrip *strip;
@@ -403,7 +596,7 @@ static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName
* NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
* i.e. pose.bones["Bone"]
*/
-void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, char *oldName, char *newName, int oldSubscript, int newSubscript, int verify_paths)
+void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, const char *prefix, char *oldName, char *newName, int oldSubscript, int newSubscript, int verify_paths)
{
NlaTrack *nlt;
char *oldN, *newN;
@@ -443,44 +636,73 @@ void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, c
/* Whole Database Ops -------------------------------------------- */
/* apply the given callback function on all data in main database */
-void BKE_animdata_main_cb (Main *main, ID_AnimData_Edit_Callback func, void *user_data)
+void BKE_animdata_main_cb (Main *mainptr, ID_AnimData_Edit_Callback func, void *user_data)
{
ID *id;
+ /* standard data version */
#define ANIMDATA_IDS_CB(first) \
for (id= first; id; id= id->next) { \
AnimData *adt= BKE_animdata_from_id(id); \
if (adt) func(id, adt, user_data); \
}
-
- ANIMDATA_IDS_CB(main->nodetree.first); /* nodes */
- ANIMDATA_IDS_CB(main->tex.first); /* textures */
- ANIMDATA_IDS_CB(main->lamp.first); /* lamps */
- ANIMDATA_IDS_CB(main->mat.first); /* materials */
- ANIMDATA_IDS_CB(main->camera.first); /* cameras */
- ANIMDATA_IDS_CB(main->key.first); /* shapekeys */
- ANIMDATA_IDS_CB(main->mball.first); /* metaballs */
- ANIMDATA_IDS_CB(main->curve.first); /* curves */
- ANIMDATA_IDS_CB(main->armature.first); /* armatures */
- ANIMDATA_IDS_CB(main->mesh.first); /* meshes */
- ANIMDATA_IDS_CB(main->particle.first); /* particles */
- ANIMDATA_IDS_CB(main->object.first); /* objects */
- ANIMDATA_IDS_CB(main->world.first); /* worlds */
-
- /* scenes */
- for (id= main->scene.first; id; id= id->next) {
- AnimData *adt= BKE_animdata_from_id(id);
- Scene *scene= (Scene *)id;
-
- /* do compositing nodes first (since these aren't included in main tree) */
- if (scene->nodetree) {
- AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
- if (adt2) func(id, adt2, user_data);
- }
-
- /* now fix scene animation data as per normal */
- if (adt) func((ID *)id, adt, user_data);
+
+ /* "embedded" nodetree cases (i.e. scene/material/texture->nodetree) */
+#define ANIMDATA_NODETREE_IDS_CB(first, NtId_Type) \
+ for (id= first; id; id= id->next) { \
+ AnimData *adt= BKE_animdata_from_id(id); \
+ NtId_Type *ntp= (NtId_Type *)id; \
+ if (ntp->nodetree) { \
+ AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \
+ if (adt2) func(id, adt2, user_data); \
+ } \
+ if (adt) func(id, adt, user_data); \
}
+
+ /* nodes */
+ ANIMDATA_IDS_CB(mainptr->nodetree.first);
+
+ /* textures */
+ ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex);
+
+ /* lamps */
+ ANIMDATA_IDS_CB(mainptr->lamp.first);
+
+ /* materials */
+ ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material);
+
+ /* cameras */
+ ANIMDATA_IDS_CB(mainptr->camera.first);
+
+ /* shapekeys */
+ ANIMDATA_IDS_CB(mainptr->key.first);
+
+ /* metaballs */
+ ANIMDATA_IDS_CB(mainptr->mball.first);
+
+ /* curves */
+ ANIMDATA_IDS_CB(mainptr->curve.first);
+
+ /* armatures */
+ ANIMDATA_IDS_CB(mainptr->armature.first);
+
+ /* lattices */
+ ANIMDATA_IDS_CB(mainptr->latt.first);
+
+ /* meshes */
+ ANIMDATA_IDS_CB(mainptr->mesh.first);
+
+ /* particles */
+ ANIMDATA_IDS_CB(mainptr->particle.first);
+
+ /* objects */
+ ANIMDATA_IDS_CB(mainptr->object.first);
+
+ /* worlds */
+ ANIMDATA_IDS_CB(mainptr->world.first);
+
+ /* scenes */
+ ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene);
}
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
@@ -503,17 +725,29 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa
BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\
}
+ /* another version of this macro for nodetrees */
+#define RENAMEFIX_ANIM_NODETREE_IDS(first, NtId_Type) \
+ for (id= first; id; id= id->next) { \
+ AnimData *adt= BKE_animdata_from_id(id); \
+ NtId_Type *ntp= (NtId_Type *)id; \
+ if (ntp->nodetree) { \
+ AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \
+ BKE_animdata_fix_paths_rename((ID *)ntp, adt2, prefix, oldName, newName, 0, 0, 1);\
+ } \
+ BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\
+ }
+
/* nodes */
RENAMEFIX_ANIM_IDS(mainptr->nodetree.first);
/* textures */
- RENAMEFIX_ANIM_IDS(mainptr->tex.first);
+ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex);
/* lamps */
RENAMEFIX_ANIM_IDS(mainptr->lamp.first);
/* materials */
- RENAMEFIX_ANIM_IDS(mainptr->mat.first);
+ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material);
/* cameras */
RENAMEFIX_ANIM_IDS(mainptr->camera.first);
@@ -530,8 +764,11 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa
/* armatures */
RENAMEFIX_ANIM_IDS(mainptr->armature.first);
+ /* lattices */
+ RENAMEFIX_ANIM_IDS(mainptr->latt.first);
+
/* meshes */
- // TODO...
+ RENAMEFIX_ANIM_IDS(mainptr->mesh.first);
/* particles */
RENAMEFIX_ANIM_IDS(mainptr->particle.first);
@@ -543,19 +780,7 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa
RENAMEFIX_ANIM_IDS(mainptr->world.first);
/* scenes */
- for (id= mainptr->scene.first; id; id= id->next) {
- AnimData *adt= BKE_animdata_from_id(id);
- Scene *scene= (Scene *)id;
-
- /* do compositing nodes first (since these aren't included in main tree) */
- if (scene->nodetree) {
- AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
- BKE_animdata_fix_paths_rename((ID *)scene->nodetree, adt2, prefix, oldName, newName, 0, 0, 1);
- }
-
- /* now fix scene animation data as per normal */
- BKE_animdata_fix_paths_rename((ID *)id, adt, prefix, oldName, newName, 0, 0, 1);
- }
+ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene);
}
/* *********************************** */
@@ -565,7 +790,7 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa
/* Find the first path that matches the given criteria */
// TODO: do we want some method to perform partial matches too?
-KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode)
+KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int UNUSED(group_mode))
{
KS_Path *ksp;
@@ -584,7 +809,7 @@ KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[]
eq_id= 0;
/* path */
- if ((ksp->rna_path==0) || strcmp(rna_path, ksp->rna_path))
+ if ((ksp->rna_path==NULL) || strcmp(rna_path, ksp->rna_path))
eq_path= 0;
/* index - need to compare whole-array setting too... */
@@ -614,12 +839,9 @@ KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, sho
/* allocate new KeyingSet */
ks= MEM_callocN(sizeof(KeyingSet), "KeyingSet");
-
- if (name)
- strncpy(ks->name, name, sizeof(ks->name));
- else
- strcpy(ks->name, "KeyingSet");
-
+
+ BLI_strncpy(ks->name, name ? name : "KeyingSet", sizeof(ks->name));
+
ks->flag= flag;
ks->keyingflag= keyingflag;
@@ -665,9 +887,9 @@ KS_Path *BKE_keyingset_add_path (KeyingSet *ks, ID *id, const char group_name[],
/* just store absolute info */
ksp->id= id;
if (group_name)
- BLI_snprintf(ksp->group, 64, group_name);
+ BLI_strncpy(ksp->group, group_name, sizeof(ksp->group));
else
- strcpy(ksp->group, "");
+ ksp->group[0]= '\0';
/* store additional info for relative paths (just in case user makes the set relative) */
if (id)
@@ -695,10 +917,11 @@ void BKE_keyingset_free_path (KeyingSet *ks, KS_Path *ksp)
/* sanity check */
if ELEM(NULL, ks, ksp)
return;
-
+
/* free RNA-path info */
- MEM_freeN(ksp->rna_path);
-
+ if(ksp->rna_path)
+ MEM_freeN(ksp->rna_path);
+
/* free path itself */
BLI_freelinkN(&ks->paths, ksp);
}
@@ -767,7 +990,7 @@ void BKE_keyingsets_free (ListBase *list)
* - path: original path string (as stored in F-Curve data)
* - dst: destination string to write data to
*/
-static short animsys_remap_path (AnimMapper *remap, char *path, char **dst)
+static short animsys_remap_path (AnimMapper *UNUSED(remap), char *path, char **dst)
{
/* is there a valid remapping table to use? */
//if (remap) {
@@ -1591,9 +1814,6 @@ void nladata_flush_channels (ListBase *channels)
*/
static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
{
- ListBase dummy_trackslist = {NULL, NULL};
- NlaStrip dummy_strip;
-
NlaTrack *nlt;
short track_index=0;
short has_strips = 0;
@@ -1607,7 +1827,7 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
/* 1. get the stack of strips to evaluate at current time (influence calculated here) */
for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) {
- /* if tweaking is on and this strip is the tweaking track, stop on this one */
+ /* stop here if tweaking is on and this strip is the tweaking track (it will be the first one that's 'disabled')... */
if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED))
break;
@@ -1634,22 +1854,32 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
*/
if ((adt->action) && !(adt->flag & ADT_NLA_SOLO_TRACK)) {
/* if there are strips, evaluate action as per NLA rules */
- if (has_strips) {
+ if ((has_strips) || (adt->actstrip)) {
/* make dummy NLA strip, and add that to the stack */
- memset(&dummy_strip, 0, sizeof(NlaStrip));
- dummy_trackslist.first= dummy_trackslist.last= &dummy_strip;
-
- dummy_strip.act= adt->action;
- dummy_strip.remap= adt->remap;
+ NlaStrip dummy_strip= {NULL};
+ ListBase dummy_trackslist;
- /* action range is calculated taking F-Modifiers into account (which making new strips doesn't do due to the troublesome nature of that) */
- calc_action_range(dummy_strip.act, &dummy_strip.actstart, &dummy_strip.actend, 1);
- dummy_strip.start = dummy_strip.actstart;
- dummy_strip.end = (IS_EQ(dummy_strip.actstart, dummy_strip.actend)) ? (dummy_strip.actstart + 1.0f): (dummy_strip.actend);
+ dummy_trackslist.first= dummy_trackslist.last= &dummy_strip;
- dummy_strip.blendmode= adt->act_blendmode;
- dummy_strip.extendmode= adt->act_extendmode;
- dummy_strip.influence= adt->act_influence;
+ if ((nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP)) {
+ /* edit active action in-place according to its active strip, so copy the data */
+ memcpy(&dummy_strip, adt->actstrip, sizeof(NlaStrip));
+ dummy_strip.next = dummy_strip.prev = NULL;
+ }
+ else {
+ /* set settings of dummy NLA strip from AnimData settings */
+ dummy_strip.act= adt->action;
+ dummy_strip.remap= adt->remap;
+
+ /* action range is calculated taking F-Modifiers into account (which making new strips doesn't do due to the troublesome nature of that) */
+ calc_action_range(dummy_strip.act, &dummy_strip.actstart, &dummy_strip.actend, 1);
+ dummy_strip.start = dummy_strip.actstart;
+ dummy_strip.end = (IS_EQ(dummy_strip.actstart, dummy_strip.actend)) ? (dummy_strip.actstart + 1.0f): (dummy_strip.actend);
+
+ dummy_strip.blendmode= adt->act_blendmode;
+ dummy_strip.extendmode= adt->act_extendmode;
+ dummy_strip.influence= adt->act_influence;
+ }
/* add this to our list of evaluation strips */
nlastrips_ctime_get_strip(&estrips, &dummy_trackslist, -1, ctime);
@@ -1685,16 +1915,18 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
/* Clear all overides */
/* Add or get existing Override for given setting */
-AnimOverride *BKE_animsys_validate_override (PointerRNA *ptr, char *path, int array_index)
+#if 0
+AnimOverride *BKE_animsys_validate_override (PointerRNA *UNUSED(ptr), char *UNUSED(path), int UNUSED(array_index))
{
// FIXME: need to define how to get overrides
return NULL;
}
+#endif
/* -------------------- */
/* Evaluate Overrides */
-static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt, float ctime)
+static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt)
{
AnimOverride *aor;
@@ -1793,7 +2025,7 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re
* - Overrides are cleared upon frame change and/or keyframing
* - It is best that we execute this everytime, so that no errors are likely to occur.
*/
- animsys_evaluate_overrides(&id_ptr, adt, ctime);
+ animsys_evaluate_overrides(&id_ptr, adt);
/* clear recalc flag now */
adt->recalc= 0;
@@ -1813,7 +2045,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
if (G.f & G_DEBUG)
printf("Evaluate all animation - %f \n", ctime);
- /* macro for less typing
+ /* macros for less typing
* - only evaluate animation data for id if it has users (and not just fake ones)
* - whether animdata exists is checked for by the evaluation function, though taking
* this outside of the function may make things slightly faster?
@@ -1825,6 +2057,24 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
BKE_animsys_evaluate_animdata(id, adt, ctime, aflag); \
} \
}
+ /* another macro for the "embedded" nodetree cases
+ * - this is like EVAL_ANIM_IDS, but this handles the case "embedded nodetrees"
+ * (i.e. scene/material/texture->nodetree) which we need a special exception
+ * for, otherwise they'd get skipped
+ * - ntp = "node tree parent" = datablock where node tree stuff resides
+ */
+#define EVAL_ANIM_NODETREE_IDS(first, NtId_Type, aflag) \
+ for (id= first; id; id= id->next) { \
+ if (ID_REAL_USERS(id) > 0) { \
+ AnimData *adt= BKE_animdata_from_id(id); \
+ NtId_Type *ntp= (NtId_Type *)id; \
+ if (ntp->nodetree) { \
+ AnimData *adt2= BKE_animdata_from_id((ID *)ntp->nodetree); \
+ BKE_animsys_evaluate_animdata((ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM); \
+ } \
+ BKE_animsys_evaluate_animdata(id, adt, ctime, aflag); \
+ } \
+ }
/* optimisation:
* when there are no actions, don't go over database and loop over heaps of datablocks,
@@ -1845,45 +2095,32 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
EVAL_ANIM_IDS(main->nodetree.first, ADT_RECALC_ANIM);
/* textures */
- EVAL_ANIM_IDS(main->tex.first, ADT_RECALC_ANIM);
+ EVAL_ANIM_NODETREE_IDS(main->tex.first, Tex, ADT_RECALC_ANIM);
/* lamps */
EVAL_ANIM_IDS(main->lamp.first, ADT_RECALC_ANIM);
/* materials */
- EVAL_ANIM_IDS(main->mat.first, ADT_RECALC_ANIM);
+ EVAL_ANIM_NODETREE_IDS(main->mat.first, Material, ADT_RECALC_ANIM);
/* cameras */
EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM);
/* shapekeys */
- // TODO: we probably need the same hack as for curves (ctime-hack)
EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM);
/* metaballs */
EVAL_ANIM_IDS(main->mball.first, ADT_RECALC_ANIM);
/* curves */
- /* we need to perform a special hack here to ensure that the ctime
- * value of the curve gets set in case there's no animation for that
- * - it needs to be set before animation is evaluated just so that
- * animation can successfully override...
- * - it shouldn't get set when calculating drivers...
- */
- for (id= main->curve.first; id; id= id->next) {
- AnimData *adt= BKE_animdata_from_id(id);
- Curve *cu= (Curve *)id;
-
- /* set ctime variable for curve */
- cu->ctime= ctime;
-
- /* now execute animation data on top of this as per normal */
- BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM);
- }
+ EVAL_ANIM_IDS(main->curve.first, ADT_RECALC_ANIM);
/* armatures */
EVAL_ANIM_IDS(main->armature.first, ADT_RECALC_ANIM);
+ /* lattices */
+ EVAL_ANIM_IDS(main->latt.first, ADT_RECALC_ANIM);
+
/* meshes */
EVAL_ANIM_IDS(main->mesh.first, ADT_RECALC_ANIM);
@@ -1901,19 +2138,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM);
/* scenes */
- for (id= main->scene.first; id; id= id->next) {
- AnimData *adt= BKE_animdata_from_id(id);
- Scene *scene= (Scene *)id;
-
- /* do compositing nodes first (since these aren't included in main tree) */
- if (scene->nodetree) {
- AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
- BKE_animsys_evaluate_animdata((ID *)scene->nodetree, adt2, ctime, ADT_RECALC_ANIM);
- }
-
- /* now execute scene animation data as per normal */
- BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM);
- }
+ EVAL_ANIM_NODETREE_IDS(main->scene.first, Scene, ADT_RECALC_ANIM);
}
/* ***************************************** */
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index a482e4051d4..b9ff4c2a30b 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_cellalloc.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -64,13 +65,13 @@
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_utildefines.h"
+
#include "BIK_api.h"
#include "BKE_sketch.h"
/* **************** Generic Functions, data level *************** */
-bArmature *add_armature(char *name)
+bArmature *add_armature(const char *name)
{
bArmature *arm;
@@ -136,19 +137,19 @@ void make_local_armature(bArmature *arm)
Object *ob;
bArmature *newArm;
- if (arm->id.lib==0)
+ if (arm->id.lib==NULL)
return;
if (arm->id.us==1) {
- arm->id.lib= 0;
+ arm->id.lib= NULL;
arm->id.flag= LIB_LOCAL;
- new_id(0, (ID*)arm, 0);
+ new_id(NULL, (ID*)arm, NULL);
return;
}
if(local && lib==0) {
- arm->id.lib= 0;
+ arm->id.lib= NULL;
arm->id.flag= LIB_LOCAL;
- new_id(0, (ID *)arm, 0);
+ new_id(NULL, (ID *)arm, NULL);
}
else if(local && lib) {
newArm= copy_armature(arm);
@@ -158,7 +159,7 @@ void make_local_armature(bArmature *arm)
while(ob) {
if(ob->data==arm) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
ob->data= newArm;
newArm->id.us++;
arm->id.us--;
@@ -248,20 +249,19 @@ Bone *get_named_bone (bArmature *arm, const char *name)
}
/* Finds the best possible extension to the name on a particular axis. (For renaming, check for unique names afterwards)
- * This assumes that bone names are at most 32 chars long!
* strip_number: removes number extensions (TODO: not used)
* axis: the axis to name on
* head/tail: the head/tail co-ordinate of the bone on the specified axis
*/
-int bone_autoside_name (char *name, int strip_number, short axis, float head, float tail)
+int bone_autoside_name (char name[MAXBONENAME], int UNUSED(strip_number), short axis, float head, float tail)
{
unsigned int len;
- char basename[32]={""};
- char extension[5]={""};
+ char basename[MAXBONENAME]= "";
+ char extension[5]= "";
len= strlen(name);
if (len == 0) return 0;
- strcpy(basename, name);
+ BLI_strncpy(basename, name, sizeof(basename));
/* Figure out extension to append:
* - The extension to append is based upon the axis that we are working on.
@@ -350,13 +350,13 @@ int bone_autoside_name (char *name, int strip_number, short axis, float head, fl
}
}
}
-
- if ((32 - len) < strlen(extension) + 1) { /* add 1 for the '.' */
+
+ if ((MAXBONENAME - len) < strlen(extension) + 1) { /* add 1 for the '.' */
strncpy(name, basename, len-strlen(extension));
}
-
- sprintf(name, "%s.%s", basename, extension);
-
+
+ BLI_snprintf(name, MAXBONENAME, "%s.%s", basename, extension);
+
return 1;
}
@@ -578,23 +578,29 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
/* ************ Armature Deform ******************* */
-static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion)
+typedef struct bPoseChanDeform {
+ Mat4 *b_bone_mats;
+ DualQuat *dual_quat;
+ DualQuat *b_bone_dual_quats;
+} bPoseChanDeform;
+
+static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info, int use_quaternion)
{
Bone *bone= pchan->bone;
Mat4 *b_bone= b_bone_spline_setup(pchan, 0);
Mat4 *b_bone_rest= b_bone_spline_setup(pchan, 1);
Mat4 *b_bone_mats;
DualQuat *b_bone_dual_quats= NULL;
- float tmat[4][4];
+ float tmat[4][4]= MAT4_UNITY;
int a;
/* allocate b_bone matrices and dual quats */
b_bone_mats= MEM_mallocN((1+bone->segments)*sizeof(Mat4), "BBone defmats");
- pchan->b_bone_mats= b_bone_mats;
+ pdef_info->b_bone_mats= b_bone_mats;
if(use_quaternion) {
b_bone_dual_quats= MEM_mallocN((bone->segments)*sizeof(DualQuat), "BBone dqs");
- pchan->b_bone_dual_quats= b_bone_dual_quats;
+ pdef_info->b_bone_dual_quats= b_bone_dual_quats;
}
/* first matrix is the inverse arm_mat, to bring points in local bone space
@@ -606,7 +612,6 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion)
- translate over the curve to the bbone mat space
- transform with b_bone matrix
- transform back into global space */
- unit_m4(tmat);
for(a=0; a<bone->segments; a++) {
invert_m4_m4(tmat, b_bone_rest[a].mat);
@@ -619,9 +624,9 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion)
}
}
-static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *co, DualQuat *dq, float defmat[][3])
+static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float *co, DualQuat *dq, float defmat[][3])
{
- Mat4 *b_bone= pchan->b_bone_mats;
+ Mat4 *b_bone= pdef_info->b_bone_mats;
float (*mat)[4]= b_bone[0].mat;
float segment, y;
int a;
@@ -638,7 +643,7 @@ static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *co, DualQuat *
CLAMP(a, 0, bone->segments-1);
if(dq) {
- copy_dq_dq(dq, &((DualQuat*)pchan->b_bone_dual_quats)[a]);
+ copy_dq_dq(dq, &(pdef_info->b_bone_dual_quats)[a]);
}
else {
mul_m4_v3(b_bone[a+1].mat, co);
@@ -712,7 +717,7 @@ static void pchan_deform_mat_add(bPoseChannel *pchan, float weight, float bbonem
add_m3_m3m3(mat, mat, wmat);
}
-static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, float mat[][3], float *co)
+static float dist_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, float *vec, DualQuat *dq, float mat[][3], float *co)
{
Bone *bone= pchan->bone;
float fac, contrib=0.0;
@@ -733,7 +738,7 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo
if(vec) {
if(bone->segments>1)
// applies on cop and bbonemat
- b_bone_deform(pchan, bone, cop, NULL, (mat)?bbonemat:NULL);
+ b_bone_deform(pdef_info, bone, cop, NULL, (mat)?bbonemat:NULL);
else
mul_m4_v3(pchan->chan_mat, cop);
@@ -746,11 +751,11 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo
}
else {
if(bone->segments>1) {
- b_bone_deform(pchan, bone, cop, &bbonedq, NULL);
+ b_bone_deform(pdef_info, bone, cop, &bbonedq, NULL);
add_weighted_dq_dq(dq, &bbonedq, fac);
}
else
- add_weighted_dq_dq(dq, pchan->dual_quat, fac);
+ add_weighted_dq_dq(dq, pdef_info->dual_quat, fac);
}
}
}
@@ -758,7 +763,7 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo
return contrib;
}
-static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, DualQuat *dq, float mat[][3], float *co, float *contrib)
+static void pchan_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, float weight, float *vec, DualQuat *dq, float mat[][3], float *co, float *contrib)
{
float cop[3], bbonemat[3][3];
DualQuat bbonedq;
@@ -771,7 +776,7 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, Dua
if(vec) {
if(pchan->bone->segments>1)
// applies on cop and bbonemat
- b_bone_deform(pchan, pchan->bone, cop, NULL, (mat)?bbonemat:NULL);
+ b_bone_deform(pdef_info, pchan->bone, cop, NULL, (mat)?bbonemat:NULL);
else
mul_m4_v3(pchan->chan_mat, cop);
@@ -784,11 +789,11 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, Dua
}
else {
if(pchan->bone->segments>1) {
- b_bone_deform(pchan, pchan->bone, cop, &bbonedq, NULL);
+ b_bone_deform(pdef_info, pchan->bone, cop, &bbonedq, NULL);
add_weighted_dq_dq(dq, &bbonedq, weight);
}
else
- add_weighted_dq_dq(dq, pchan->dual_quat, weight);
+ add_weighted_dq_dq(dq, pdef_info->dual_quat, weight);
}
(*contrib)+=weight;
@@ -799,15 +804,18 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
int numVerts, int deformflag,
float (*prevCos)[3], const char *defgrp_name)
{
+ bPoseChanDeform *pdef_info_array;
+ bPoseChanDeform *pdef_info= NULL;
bArmature *arm= armOb->data;
bPoseChannel *pchan, **defnrToPC = NULL;
+ int *defnrToPCIndex= NULL;
MDeformVert *dverts = NULL;
bDeformGroup *dg;
DualQuat *dualquats= NULL;
float obinv[4][4], premat[4][4], postmat[4][4];
- int use_envelope = deformflag & ARM_DEF_ENVELOPE;
- int use_quaternion = deformflag & ARM_DEF_QUATERNION;
- int invert_vgroup= deformflag & ARM_DEF_INVERT_VGROUP;
+ const short use_envelope = deformflag & ARM_DEF_ENVELOPE;
+ const short use_quaternion = deformflag & ARM_DEF_QUATERNION;
+ const short invert_vgroup= deformflag & ARM_DEF_INVERT_VGROUP;
int numGroups = 0; /* safety for vertexgroup index overflow */
int i, target_totvert = 0; /* safety for vertexgroup overflow */
int use_dverts = 0;
@@ -824,20 +832,24 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
/* bone defmats are already in the channels, chan_mat */
/* initialize B_bone matrices and dual quaternions */
+ totchan= BLI_countlist(&armOb->pose->chanbase);
+
if(use_quaternion) {
- totchan= BLI_countlist(&armOb->pose->chanbase);
dualquats= MEM_callocN(sizeof(DualQuat)*totchan, "dualquats");
}
+
+ pdef_info_array= MEM_callocN(sizeof(bPoseChanDeform)*totchan, "bPoseChanDeform");
totchan= 0;
- for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
+ pdef_info= pdef_info_array;
+ for(pchan= armOb->pose->chanbase.first; pchan; pchan= pchan->next, pdef_info++) {
if(!(pchan->bone->flag & BONE_NO_DEFORM)) {
if(pchan->bone->segments > 1)
- pchan_b_bone_defmats(pchan, use_quaternion);
+ pchan_b_bone_defmats(pchan, pdef_info, use_quaternion);
if(use_quaternion) {
- pchan->dual_quat= &dualquats[totchan++];
- mat4_to_dquat( pchan->dual_quat,pchan->bone->arm_mat, pchan->chan_mat);
+ pdef_info->dual_quat= &dualquats[totchan++];
+ mat4_to_dquat( pdef_info->dual_quat,pchan->bone->arm_mat, pchan->chan_mat);
}
}
}
@@ -873,15 +885,19 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
else if(dverts) use_dverts = 1;
if(use_dverts) {
- defnrToPC = MEM_callocN(sizeof(*defnrToPC) * numGroups,
- "defnrToBone");
+ defnrToPC = MEM_callocN(sizeof(*defnrToPC) * numGroups, "defnrToBone");
+ defnrToPCIndex = MEM_callocN(sizeof(*defnrToPCIndex) * numGroups, "defnrToIndex");
for(i = 0, dg = target->defbase.first; dg;
i++, dg = dg->next) {
defnrToPC[i] = get_pose_channel(armOb->pose, dg->name);
/* exclude non-deforming bones */
if(defnrToPC[i]) {
- if(defnrToPC[i]->bone->flag & BONE_NO_DEFORM)
+ if(defnrToPC[i]->bone->flag & BONE_NO_DEFORM) {
defnrToPC[i]= NULL;
+ }
+ else {
+ defnrToPCIndex[i]= BLI_findindex(&armOb->pose->chanbase, defnrToPC[i]);
+ }
}
}
}
@@ -921,19 +937,15 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
dvert = NULL;
if(armature_def_nr >= 0 && dvert) {
- armature_weight = 0.0f; /* a def group was given, so default to 0 */
- for(j = 0; j < dvert->totweight; j++) {
- if(dvert->dw[j].def_nr == armature_def_nr) {
- armature_weight = dvert->dw[j].weight;
- break;
- }
+ armature_weight= defvert_find_weight(dvert, armature_def_nr);
+
+ if(invert_vgroup) {
+ armature_weight= 1.0f-armature_weight;
}
+
/* hackish: the blending factor can be used for blending with prevCos too */
if(prevCos) {
- if(invert_vgroup)
- prevco_weight= 1.0f-armature_weight;
- else
- prevco_weight= armature_weight;
+ prevco_weight= armature_weight;
armature_weight= 1.0f;
}
}
@@ -952,10 +964,10 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
for(j = 0; j < dvert->totweight; j++){
int index = dvert->dw[j].def_nr;
- pchan = index < numGroups?defnrToPC[index]:NULL;
- if(pchan) {
+ if(index < numGroups && (pchan= defnrToPC[index])) {
float weight = dvert->dw[j].weight;
- Bone *bone = pchan->bone;
+ Bone *bone= pchan->bone;
+ pdef_info= pdef_info_array + defnrToPCIndex[index];
deformed = 1;
@@ -966,25 +978,27 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
bone->rad_tail,
bone->dist);
}
- pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib);
+ pchan_bone_deform(pchan, pdef_info, weight, vec, dq, smat, co, &contrib);
}
}
/* if there are vertexgroups but not groups with bones
* (like for softbody groups)
*/
if(deformed == 0 && use_envelope) {
- for(pchan = armOb->pose->chanbase.first; pchan;
- pchan = pchan->next) {
+ pdef_info= pdef_info_array;
+ for(pchan= armOb->pose->chanbase.first; pchan;
+ pchan= pchan->next, pdef_info++) {
if(!(pchan->bone->flag & BONE_NO_DEFORM))
- contrib += dist_bone_deform(pchan, vec, dq, smat, co);
+ contrib += dist_bone_deform(pchan, pdef_info, vec, dq, smat, co);
}
}
}
else if(use_envelope) {
+ pdef_info= pdef_info_array;
for(pchan = armOb->pose->chanbase.first; pchan;
- pchan = pchan->next) {
+ pchan = pchan->next, pdef_info++) {
if(!(pchan->bone->flag & BONE_NO_DEFORM))
- contrib += dist_bone_deform(pchan, vec, dq, smat, co);
+ contrib += dist_bone_deform(pchan, pdef_info, vec, dq, smat, co);
}
}
@@ -1040,25 +1054,25 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
if(dualquats) MEM_freeN(dualquats);
if(defnrToPC) MEM_freeN(defnrToPC);
-
+ if(defnrToPCIndex) MEM_freeN(defnrToPCIndex);
+
/* free B_bone matrices */
- for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
- if(pchan->b_bone_mats) {
- MEM_freeN(pchan->b_bone_mats);
- pchan->b_bone_mats = NULL;
+ pdef_info= pdef_info_array;
+ for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next, pdef_info++) {
+ if(pdef_info->b_bone_mats) {
+ MEM_freeN(pdef_info->b_bone_mats);
}
- if(pchan->b_bone_dual_quats) {
- MEM_freeN(pchan->b_bone_dual_quats);
- pchan->b_bone_dual_quats = NULL;
+ if(pdef_info->b_bone_dual_quats) {
+ MEM_freeN(pdef_info->b_bone_dual_quats);
}
-
- pchan->dual_quat = NULL;
}
+
+ MEM_freeN(pdef_info_array);
}
/* ************ END Armature Deform ******************* */
-void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed)
+void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int UNUSED(root), int UNUSED(posed))
{
copy_m4_m4(M_accumulatedMatrix, bone->arm_mat);
}
@@ -1086,11 +1100,10 @@ void armature_mat_world_to_pose(Object *ob, float inmat[][4], float outmat[][4])
*/
void armature_loc_world_to_pose(Object *ob, float *inloc, float *outloc)
{
- float xLocMat[4][4];
+ float xLocMat[4][4]= MAT4_UNITY;
float nLocMat[4][4];
/* build matrix for location */
- unit_m4(xLocMat);
VECCOPY(xLocMat[3], inloc);
/* get bone-space cursor matrix and extract location */
@@ -1106,22 +1119,50 @@ void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outm
{
float pc_trans[4][4], inv_trans[4][4];
float pc_posemat[4][4], inv_posemat[4][4];
-
+ float pose_mat[4][4];
+
/* paranoia: prevent crashes with no pose-channel supplied */
if (pchan==NULL) return;
-
- /* get the inverse matrix of the pchan's transforms */
- if (pchan->rotmode)
- loc_eul_size_to_mat4(pc_trans, pchan->loc, pchan->eul, pchan->size);
- else
- loc_quat_size_to_mat4(pc_trans, pchan->loc, pchan->quat, pchan->size);
+
+ /* default flag */
+ if((pchan->bone->flag & BONE_NO_LOCAL_LOCATION)==0) {
+ /* get the inverse matrix of the pchan's transforms */
+ switch(pchan->rotmode) {
+ case ROT_MODE_QUAT:
+ loc_quat_size_to_mat4(pc_trans, pchan->loc, pchan->quat, pchan->size);
+ break;
+ case ROT_MODE_AXISANGLE:
+ loc_axisangle_size_to_mat4(pc_trans, pchan->loc, pchan->rotAxis, pchan->rotAngle, pchan->size);
+ break;
+ default: /* euler */
+ loc_eul_size_to_mat4(pc_trans, pchan->loc, pchan->eul, pchan->size);
+ }
+
+ copy_m4_m4(pose_mat, pchan->pose_mat);
+ }
+ else {
+ /* local location, this is not default, different calculation
+ * note: only tested for location with pose bone snapping.
+ * If this is not useful in other cases the BONE_NO_LOCAL_LOCATION
+ * case may have to be split into its own function. */
+ unit_m4(pc_trans);
+ copy_v3_v3(pc_trans[3], pchan->loc);
+
+ /* use parents rotation/scale space + own absolute position */
+ if(pchan->parent) copy_m4_m4(pose_mat, pchan->parent->pose_mat);
+ else unit_m4(pose_mat);
+
+ copy_v3_v3(pose_mat[3], pchan->pose_mat[3]);
+ }
+
+
invert_m4_m4(inv_trans, pc_trans);
/* Remove the pchan's transforms from it's pose_mat.
* This should leave behind the effects of restpose +
* parenting + constraints
*/
- mul_m4_m4m4(pc_posemat, inv_trans, pchan->pose_mat);
+ mul_m4_m4m4(pc_posemat, inv_trans, pose_mat);
/* get the inverse of the leftovers so that we can remove
* that component from the supplied matrix
@@ -1138,11 +1179,10 @@ void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outm
*/
void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc)
{
- float xLocMat[4][4];
+ float xLocMat[4][4]= MAT4_UNITY;
float nLocMat[4][4];
/* build matrix for location */
- unit_m4(xLocMat);
VECCOPY(xLocMat[3], inloc);
/* get bone-space cursor matrix and extract location */
@@ -1150,32 +1190,30 @@ void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc)
VECCOPY(outloc, nLocMat[3]);
}
+/* same as object_mat3_to_rot() */
+void pchan_mat3_to_rot(bPoseChannel *pchan, float mat[][3], short use_compat)
+{
+ switch(pchan->rotmode) {
+ case ROT_MODE_QUAT:
+ mat3_to_quat(pchan->quat, mat);
+ break;
+ case ROT_MODE_AXISANGLE:
+ mat3_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, mat);
+ break;
+ default: /* euler */
+ if(use_compat) mat3_to_compatible_eulO(pchan->eul, pchan->eul, pchan->rotmode, mat);
+ else mat3_to_eulO(pchan->eul, pchan->rotmode, mat);
+ }
+}
/* Apply a 4x4 matrix to the pose bone,
* similar to object_apply_mat4()
*/
-void pchan_apply_mat4(bPoseChannel *pchan, float mat[][4])
+void pchan_apply_mat4(bPoseChannel *pchan, float mat[][4], short use_compat)
{
- /* location */
- copy_v3_v3(pchan->loc, mat[3]);
-
- /* scale */
- mat4_to_size(pchan->size, mat);
-
- /* rotation */
- if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- float tmp_quat[4];
-
- /* need to convert to quat first (in temp var)... */
- mat4_to_quat(tmp_quat, mat);
- quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, tmp_quat);
- }
- else if (pchan->rotmode == ROT_MODE_QUAT) {
- mat4_to_quat(pchan->quat, mat);
- }
- else {
- mat4_to_eulO(pchan->eul, pchan->rotmode, mat);
- }
+ float rot[3][3];
+ mat4_to_loc_rot_size(pchan->loc, rot, pchan->size, mat);
+ pchan_mat3_to_rot(pchan, rot, use_compat);
}
/* Remove rest-position effects from pose-transform for obtaining
@@ -1207,6 +1245,7 @@ void BKE_rotMode_change_values (float quat[4], float eul[3], float axis[3], floa
}
else if (oldMode == ROT_MODE_QUAT) {
/* quat to euler */
+ normalize_qt(quat);
quat_to_eulO( eul, newMode,quat);
}
/* else { no conversion needed } */
@@ -1229,6 +1268,7 @@ void BKE_rotMode_change_values (float quat[4], float eul[3], float axis[3], floa
}
else if (oldMode == ROT_MODE_QUAT) {
/* quat to axis angle */
+ normalize_qt(quat);
quat_to_axis_angle( axis, angle,quat);
}
@@ -1290,7 +1330,9 @@ void vec_roll_to_mat3(float *vec, float roll, float mat[][3])
/* Find Axis & Amount for bone matrix*/
cross_v3_v3v3(axis,target,nor);
- if (dot_v3v3(axis,axis) > 0.0000000000001) {
+ /* was 0.0000000000001, caused bug [#23954], smaller values give unstable
+ * roll when toggling editmode */
+ if (dot_v3v3(axis,axis) > 0.00001) {
/* if nor is *not* a multiple of target ... */
normalize_v3(axis);
@@ -1359,13 +1401,6 @@ void where_is_armature_bone(Bone *bone, Bone *prevbone)
VECCOPY(bone->arm_mat[3], bone->head);
}
- /* head */
- VECCOPY(bone->arm_head, bone->arm_mat[3]);
- /* tail is in current local coord system */
- VECCOPY(vec, bone->arm_mat[1]);
- mul_v3_fl(vec, bone->length);
- add_v3_v3v3(bone->arm_tail, bone->arm_head, vec);
-
/* and the kiddies */
prevbone= bone;
for(bone= bone->childbase.first; bone; bone= bone->next) {
@@ -1410,10 +1445,6 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
if(error)
return;
- /* exception, armature local layer should be proxied too */
- if (pose->proxy_layer)
- ((bArmature *)ob->data)->layer= pose->proxy_layer;
-
/* clear all transformation values from library */
rest_pose(frompose);
@@ -1459,7 +1490,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
*/
extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints);
copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE);
- addlisttolist(&pchanw.constraints, &proxylocal_constraints);
+ BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints);
/* constraints - set target ob pointer to own object */
for (con= pchanw.constraints.first; con; con= con->next) {
@@ -1615,7 +1646,7 @@ typedef struct tSplineIK_Tree {
/* ----------- */
/* Tag the bones in the chain formed by the given bone for IK */
-static void splineik_init_tree_from_pchan(Scene *scene, Object *ob, bPoseChannel *pchan_tip)
+static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPoseChannel *pchan_tip)
{
bPoseChannel *pchan, *pchanRoot=NULL;
bPoseChannel *pchanChain[255];
@@ -1688,28 +1719,25 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *ob, bPoseChannel
ikData->numpoints= ikData->chainlen+1;
ikData->points= MEM_callocN(sizeof(float)*ikData->numpoints, "Spline IK Binding");
+ /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */
+ ikData->points[0] = 1.0f;
+
/* perform binding of the joints to parametric positions along the curve based
* proportion of the total length that each bone occupies
*/
for (i = 0; i < segcount; i++) {
- if (i != 0) {
- /* 'head' joints
- * - 2 methods; the one chosen depends on whether we've got usable lengths
- */
- if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) {
- /* 1) equi-spaced joints */
- ikData->points[i]= ikData->points[i-1] - segmentLen;
- }
- else {
- /* 2) to find this point on the curve, we take a step from the previous joint
- * a distance given by the proportion that this bone takes
- */
- ikData->points[i]= ikData->points[i-1] - (boneLengths[i] / totLength);
- }
+ /* 'head' joints, travelling towards the root of the chain
+ * - 2 methods; the one chosen depends on whether we've got usable lengths
+ */
+ if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) {
+ /* 1) equi-spaced joints */
+ ikData->points[i+1]= ikData->points[i] - segmentLen;
}
else {
- /* 'tip' of chain, special exception for the first joint */
- ikData->points[0]= 1.0f;
+ /* 2) to find this point on the curve, we take a step from the previous joint
+ * a distance given by the proportion that this bone takes
+ */
+ ikData->points[i+1]= ikData->points[i] - (boneLengths[i] / totLength);
}
}
@@ -1784,7 +1812,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *ob, bPoseChannel
}
/* Tag which bones are members of Spline IK chains */
-static void splineik_init_tree(Scene *scene, Object *ob, float ctime)
+static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime))
{
bPoseChannel *pchan;
@@ -1989,7 +2017,9 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
/* finally, store the new transform */
copy_m4_m4(pchan->pose_mat, poseMat);
VECCOPY(pchan->pose_head, poseHead);
- VECCOPY(pchan->pose_tail, poseTail);
+
+ /* recalculate tail, as it's now outdated after the head gets adjusted above! */
+ where_is_pose_bone_tail(pchan);
/* done! */
pchan->flag |= POSE_DONE;
@@ -2054,8 +2084,7 @@ void pchan_to_mat4(bPoseChannel *pchan, float chan_mat[4][4])
* but if this proves to be too problematic, switch back to the old system of operating directly on
* the stored copy
*/
- QUATCOPY(quat, pchan->quat);
- normalize_qt(quat);
+ normalize_qt_qt(quat, pchan->quat);
quat_to_mat3(rmat, quat);
}
@@ -2072,7 +2101,7 @@ void pchan_to_mat4(bPoseChannel *pchan, float chan_mat[4][4])
/* loc/rot/size to mat4 */
/* used in constraint.c too */
-void chan_calc_mat(bPoseChannel *pchan)
+void pchan_calc_mat(bPoseChannel *pchan)
{
/* this is just a wrapper around the copy of this function which calculates the matrix
* and stores the result in any given channel
@@ -2202,6 +2231,15 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha
}
}
+/* calculate tail of posechannel */
+void where_is_pose_bone_tail(bPoseChannel *pchan)
+{
+ float vec[3];
+
+ VECCOPY(vec, pchan->pose_mat[1]);
+ mul_v3_fl(vec, pchan->bone->length);
+ add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec);
+}
/* The main armature solver, does all constraints excluding IK */
/* pchan is validated, as having bone and parent pointer
@@ -2219,7 +2257,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
parchan= pchan->parent;
/* this gives a chan_mat with actions (ipos) results */
- if(do_extra) chan_calc_mat(pchan);
+ if(do_extra) pchan_calc_mat(pchan);
else unit_m4(pchan->chan_mat);
/* construct the posemat based on PoseChannels, that we do before applying constraints */
@@ -2238,13 +2276,28 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
offs_bone[3][1]+= parbone->length;
/* Compose the matrix for this bone */
- if(bone->flag & BONE_HINGE) { // uses restposition rotation, but actual position
+ if((bone->flag & BONE_HINGE) && (bone->flag & BONE_NO_SCALE)) { // uses restposition rotation, but actual position
float tmat[4][4];
-
/* the rotation of the parent restposition */
copy_m4_m4(tmat, parbone->arm_mat);
mul_serie_m4(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
}
+ else if(bone->flag & BONE_HINGE) { // same as above but apply parent scale
+ float tmat[4][4];
+
+ /* apply the parent matrix scale */
+ float tsmat[4][4], tscale[3];
+
+ /* the rotation of the parent restposition */
+ copy_m4_m4(tmat, parbone->arm_mat);
+
+ /* extract the scale of the parent matrix */
+ mat4_to_size(tscale, parchan->pose_mat);
+ size_to_mat4(tsmat, tscale);
+ mul_m4_m4m4(tmat, tmat, tsmat);
+
+ mul_serie_m4(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
+ }
else if(bone->flag & BONE_NO_SCALE) {
float orthmat[4][4];
@@ -2320,9 +2373,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
/* calculate head */
VECCOPY(pchan->pose_head, pchan->pose_mat[3]);
/* calculate tail */
- VECCOPY(vec, pchan->pose_mat[1]);
- mul_v3_fl(vec, bone->length);
- add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec);
+ where_is_pose_bone_tail(pchan);
}
/* This only reads anim data from channels, and writes to channels */
@@ -2340,7 +2391,7 @@ void where_is_pose (Scene *scene, Object *ob)
if(ELEM(NULL, arm, scene)) return;
if((ob->pose==NULL) || (ob->pose->flag & POSE_RECALC))
- armature_rebuild_pose(ob, arm);
+ armature_rebuild_pose(ob, arm);
ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0); /* not accurate... */
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 0f2218b8766..0556acbdece 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -32,7 +32,6 @@
#ifndef _WIN32
#include <unistd.h> // for read close
- #include <sys/param.h> // for MAXPATHLEN
#else
#include <io.h> // for open close read
#define open _open
@@ -56,8 +55,10 @@
#include "DNA_sound_types.h"
#include "BLI_blenlib.h"
+#include "BLI_bpath.h"
#include "BLI_dynstr.h"
#include "BLI_path_util.h"
+#include "BLI_utildefines.h"
#include "IMB_imbuf.h"
@@ -81,16 +82,16 @@
#include "BLO_readfile.h"
#include "BLO_writefile.h"
-#include "BKE_utildefines.h" // O_BINARY FALSE
+#include "BKE_utildefines.h"
#include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie
Global G;
UserDef U;
-ListBase WMlist= {NULL, NULL};
+/* ListBase = {NULL, NULL}; */
short ENDIAN_ORDER;
-char versionstr[48]= "";
+static char versionstr[48]= "";
/* ********** free ********** */
@@ -123,9 +124,9 @@ void initglobals(void)
ENDIAN_ORDER= (((char*)&ENDIAN_ORDER)[0])? L_ENDIAN: B_ENDIAN;
if(BLENDER_SUBVERSION)
- sprintf(versionstr, "www.blender.org %d.%d", BLENDER_VERSION, BLENDER_SUBVERSION);
+ BLI_snprintf(versionstr, sizeof(versionstr), "www.blender.org %d.%d", BLENDER_VERSION, BLENDER_SUBVERSION);
else
- sprintf(versionstr, "www.blender.org %d", BLENDER_VERSION);
+ BLI_snprintf(versionstr, sizeof(versionstr), "www.blender.org %d", BLENDER_VERSION);
#ifdef _WIN32 // FULLSCREEN
G.windowstate = G_WINDOWSTATE_USERDEF;
@@ -155,50 +156,33 @@ static void clear_global(void)
/* make sure path names are correct for OS */
static void clean_paths(Main *main)
{
- Image *image= main->image.first;
- bSound *sound= main->sound.first;
- Scene *scene= main->scene.first;
- Editing *ed;
- Sequence *seq;
- Strip *strip;
-
- while(image) {
- BLI_clean(image->name);
- image= image->id.next;
- }
-
- while(sound) {
- BLI_clean(sound->name);
- sound= sound->id.next;
- }
-
- while(scene) {
- ed= seq_give_editing(scene, 0);
- if(ed) {
- seq= ed->seqbasep->first;
- while(seq) {
- if(seq->plugin) {
- BLI_clean(seq->plugin->name);
- }
- strip= seq->strip;
- while(strip) {
- BLI_clean(strip->dir);
- strip= strip->next;
- }
- seq= seq->next;
- }
- }
+ struct BPathIterator *bpi;
+ char filepath_expanded[1024];
+ Scene *scene;
+
+ for(BLI_bpathIterator_init(&bpi, main, main->name, BPATH_USE_PACKED); !BLI_bpathIterator_isDone(bpi); BLI_bpathIterator_step(bpi)) {
+ BLI_bpathIterator_getPath(bpi, filepath_expanded);
+
+ BLI_clean(filepath_expanded);
+
+ BLI_bpathIterator_setPath(bpi, filepath_expanded);
+ }
+
+ BLI_bpathIterator_free(bpi);
+
+ for(scene= main->scene.first; scene; scene= scene->id.next) {
BLI_clean(scene->r.backbuf);
BLI_clean(scene->r.pic);
-
- scene= scene->id.next;
}
}
/* context matching */
/* handle no-ui case */
-static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
+/* note, this is called on Undo so any slow conversion functions here
+ * should be avoided or check (mode!='u') */
+
+static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filename)
{
bScreen *curscreen= NULL;
Scene *curscene= NULL;
@@ -211,9 +195,12 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
else mode= 0;
recover= (G.fileflags & G_FILE_RECOVER);
-
- clean_paths(bfd->main);
-
+
+ /* Only make filepaths compatible when loading for real (not undo) */
+ if(mode != 'u') {
+ clean_paths(bfd->main);
+ }
+
/* XXX here the complex windowmanager matching */
/* no load screens? */
@@ -238,6 +225,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
}
/* free G.main Main database */
+// CTX_wm_manager_set(C, NULL);
clear_global();
G.main= bfd->main;
@@ -262,7 +250,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
G.winpos= bfd->winpos;
G.displaymode= bfd->displaymode;
G.fileflags= bfd->fileflags;
-
+ CTX_wm_manager_set(C, bfd->main->wm.first);
CTX_wm_screen_set(C, bfd->curscreen);
CTX_data_scene_set(C, bfd->curscreen->scene);
CTX_wm_area_set(C, NULL);
@@ -309,10 +297,8 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
#endif
/* these are the same at times, should never copy to the same location */
- if(G.sce != filename)
- BLI_strncpy(G.sce, filename, FILE_MAX);
-
- BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
+ if(G.main->name != filename)
+ BLI_strncpy(G.main->name, filename, FILE_MAX);
/* baseflags, groups, make depsgraph, etc */
set_scene_bg(G.main, CTX_data_scene(C));
@@ -328,7 +314,7 @@ static int handle_subversion_warning(Main *main)
char str[128];
- sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile);
+ BLI_snprintf(str, sizeof(str), "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile);
// XXX error(str);
}
return 1;
@@ -359,18 +345,12 @@ void BKE_userdef_free(void)
BLI_freelistN(&U.addons);
}
-/* returns:
- 0: no load file
- 1: OK
- 2: OK, and with new user settings
-*/
-
-int BKE_read_file(bContext *C, char *dir, void *unused, ReportList *reports)
+int BKE_read_file(bContext *C, const char *dir, ReportList *reports)
{
BlendFileData *bfd;
int retval= 1;
- if(strstr(dir, BLENDER_STARTUP_FILE)==0) /* dont print user-pref loading */
+ if(strstr(dir, BLENDER_STARTUP_FILE)==NULL) /* dont print user-pref loading */
printf("read blend: %s\n", dir);
bfd= BLO_read_from_file(dir, reports);
@@ -392,7 +372,7 @@ int BKE_read_file(bContext *C, char *dir, void *unused, ReportList *reports)
return (bfd?retval:0);
}
-int BKE_read_file_from_memory(bContext *C, char* filebuf, int filelength, void *unused, ReportList *reports)
+int BKE_read_file_from_memory(bContext *C, char* filebuf, int filelength, ReportList *reports)
{
BlendFileData *bfd;
@@ -410,7 +390,7 @@ int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *report
{
BlendFileData *bfd;
- bfd= BLO_read_from_memfile(CTX_data_main(C), G.sce, memfile, reports);
+ bfd= BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports);
if (bfd)
setup_app_data(C, bfd, "<memory1>");
else
@@ -460,37 +440,38 @@ static UndoElem *curundo= NULL;
static int read_undosave(bContext *C, UndoElem *uel)
{
- char scestr[FILE_MAXDIR+FILE_MAXFILE]; /* we should eventually just use G.main->name */
- char mainstr[FILE_MAXDIR+FILE_MAXFILE];
+ char mainstr[sizeof(G.main->name)];
int success=0, fileflags;
/* This is needed so undoing/redoing doesnt crash with threaded previews going */
WM_jobs_stop_all(CTX_wm_manager(C));
-
- strcpy(scestr, G.sce); /* temporal store */
+
+ BLI_strncpy(mainstr, G.main->name, sizeof(mainstr)); /* temporal store */
+
strcpy(mainstr, G.main->name); /* temporal store */
fileflags= G.fileflags;
G.fileflags |= G_FILE_NO_UI;
if(UNDO_DISK)
- success= BKE_read_file(C, uel->str, NULL, NULL);
+ success= (BKE_read_file(C, uel->str, NULL) != BKE_READ_FILE_FAIL);
else
success= BKE_read_file_from_memfile(C, &uel->memfile, NULL);
/* restore */
- strcpy(G.sce, scestr); /* restore */
- strcpy(G.main->name, mainstr); /* restore */
+ BLI_strncpy(G.main->name, mainstr, sizeof(G.main->name)); /* restore */
G.fileflags= fileflags;
- if(success)
- DAG_on_load_update(G.main);
+ if(success) {
+ /* important not to update time here, else non keyed tranforms are lost */
+ DAG_on_load_update(G.main, FALSE);
+ }
return success;
}
/* name can be a dynamic string */
-void BKE_write_undo(bContext *C, char *name)
+void BKE_write_undo(bContext *C, const char *name)
{
uintptr_t maxmem, totmem, memused;
int nr, success;
@@ -541,12 +522,12 @@ void BKE_write_undo(bContext *C, char *name)
counter++;
counter= counter % U.undosteps;
- sprintf(numstr, "%d.blend", counter);
+ BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
BLI_make_file_string("/", tstr, btempdir, numstr);
success= BLO_write_file(CTX_data_main(C), tstr, G.fileflags, NULL, NULL);
- strcpy(curundo->str, tstr);
+ BLI_strncpy(curundo->str, tstr, sizeof(curundo->str));
}
else {
MemFile *prevfile=NULL;
@@ -554,7 +535,7 @@ void BKE_write_undo(bContext *C, char *name)
if(curundo->prev) prevfile= &(curundo->prev->memfile);
memused= MEM_get_memory_in_use();
- success= BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags, NULL);
+ success= BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags);
curundo->undosize= MEM_get_memory_in_use() - memused;
}
@@ -657,6 +638,22 @@ void BKE_undo_name(bContext *C, const char *name)
}
}
+/* name optional */
+int BKE_undo_valid(const char *name)
+{
+ if(name) {
+ UndoElem *uel;
+
+ for(uel= undobase.last; uel; uel= uel->prev)
+ if(strcmp(name, uel->name)==0)
+ break;
+
+ return uel && uel->prev;
+ }
+
+ return undobase.last != undobase.first;
+}
+
char *BKE_undo_menu_string(void)
{
@@ -726,7 +723,7 @@ void BKE_undo_save(char *fname)
Main *BKE_undo_get_main(Scene **scene)
{
Main *mainp= NULL;
- BlendFileData *bfd= BLO_read_from_memfile(G.main, G.sce, &curundo->memfile, NULL);
+ BlendFileData *bfd= BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL);
if(bfd) {
mainp= bfd->main;
diff --git a/source/blender/blenkernel/intern/bmesh_private.h b/source/blender/blenkernel/intern/bmesh_private.h
index 713194c9806..b14383378ab 100644
--- a/source/blender/blenkernel/intern/bmesh_private.h
+++ b/source/blender/blenkernel/intern/bmesh_private.h
@@ -1,4 +1,4 @@
-/**
+/*
* BME_private.h jan 2007
*
* low level, 'private' function prototypes for bmesh kernel.
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
index e2a6c04450b..1d4bdf8bf44 100644
--- a/source/blender/blenkernel/intern/bmfont.c
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -1,4 +1,4 @@
-/**
+/*
* bmfont.c
*
* 04-10-2000 frank
@@ -54,6 +54,7 @@
#include "BKE_global.h"
#include "IMB_imbuf_types.h"
+#include "BKE_bmfont.h"
#include "BKE_bmfont_types.h"
void printfGlyph(bmGlyph * glyph)
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 54ffda6c0a9..ae4882b0eca 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -41,11 +41,13 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_kdtree.h"
+#include "BLI_utildefines.h"
+
#include "BKE_collision.h"
#include "BKE_effect.h"
#include "BKE_boids.h"
#include "BKE_particle.h"
-#include "BKE_utildefines.h"
+
#include "BKE_modifier.h"
#include "RNA_enum_types.h"
@@ -58,7 +60,7 @@ typedef struct BoidValues {
static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, ParticleData *pa, float fuzziness);
-static int rule_none(BoidRule *rule, BoidBrainData *data, BoidValues *val, ParticleData *pa)
+static int rule_none(BoidRule *UNUSED(rule), BoidBrainData *UNUSED(data), BoidValues *UNUSED(val), ParticleData *UNUSED(pa))
{
return 0;
}
@@ -205,7 +207,9 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
add_v3_v3v3(col.co2, pa->prev_state.co, pa->prev_state.vel);
sub_v3_v3v3(ray_dir, col.co2, col.co1);
mul_v3_fl(ray_dir, acbr->look_ahead);
- col.t = 0.0f;
+ col.f = 0.0f;
+ col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+ col.dfra = bbd->dfra;
hit.index = -1;
hit.dist = col.ray_len = len_v3(ray_dir);
@@ -240,6 +244,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size);
bbd->wanted_speed = sqrt(t) * len_v3(pa->prev_state.vel);
+ bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed);
return 1;
}
@@ -343,7 +348,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
return ret;
}
-static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
+static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
{
KDTreeNearest *ptn = NULL;
ParticleTarget *pt;
@@ -383,7 +388,7 @@ static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Pa
}
return ret;
}
-static int rule_flock(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
+static int rule_flock(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *UNUSED(val), ParticleData *pa)
{
KDTreeNearest ptn[11];
float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
@@ -736,6 +741,7 @@ static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *
val->jump_speed = 0.0f; /* no jumping in air */
}
}
+
static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *ground_co, float *ground_nor)
{
BoidParticle *bpa = pa->boid;
@@ -765,16 +771,17 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
if(!bbd->sim->colliders)
return NULL;
+ /* first try to find below boid */
copy_v3_v3(col.co1, pa->state.co);
- copy_v3_v3(col.co2, pa->state.co);
- add_v3_v3(col.co1, zvec);
+ sub_v3_v3v3(col.co2, pa->state.co, zvec);
sub_v3_v3(col.co2, zvec);
sub_v3_v3v3(ray_dir, col.co2, col.co1);
- col.t = 0.0f;
+ col.f = 0.0f;
+ col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+ col.dfra = bbd->dfra;
hit.index = -1;
hit.dist = col.ray_len = len_v3(ray_dir);
- /* find out upmost deflector object */
for(coll = bbd->sim->colliders->first; coll; coll = coll->next){
col.ob = coll->ob;
col.md = coll->collmd;
@@ -789,17 +796,42 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
normalize_v3_v3(ground_nor, col.nor);
return col.hit_ob;
}
- else {
- /* default to z=0 */
- VECCOPY(ground_co, pa->state.co);
- ground_co[2] = 0;
- ground_nor[0] = ground_nor[1] = 0.0f;
- ground_nor[2] = 1.0f;
- return NULL;
+
+ /* couldn't find below, so find upmost deflector object */
+ add_v3_v3v3(col.co1, pa->state.co, zvec);
+ sub_v3_v3v3(col.co2, pa->state.co, zvec);
+ sub_v3_v3(col.co2, zvec);
+ sub_v3_v3v3(ray_dir, col.co2, col.co1);
+ col.f = 0.0f;
+ col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+ col.dfra = bbd->dfra;
+ hit.index = -1;
+ hit.dist = col.ray_len = len_v3(ray_dir);
+
+ for(coll = bbd->sim->colliders->first; coll; coll = coll->next){
+ col.ob = coll->ob;
+ col.md = coll->collmd;
+
+ if(col.md && col.md->bvhtree)
+ BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col);
+ }
+ /* then use that object */
+ if(hit.index>=0) {
+ t = hit.dist/col.ray_len;
+ interp_v3_v3v3(ground_co, col.co1, col.co2, t);
+ normalize_v3_v3(ground_nor, col.nor);
+ return col.hit_ob;
}
+
+ /* default to z=0 */
+ VECCOPY(ground_co, pa->state.co);
+ ground_co[2] = 0;
+ ground_nor[0] = ground_nor[1] = 0.0f;
+ ground_nor[2] = 1.0f;
+ return NULL;
}
}
-static int boid_rule_applies(ParticleData *pa, BoidSettings *boids, BoidRule *rule)
+static int boid_rule_applies(ParticleData *pa, BoidSettings *UNUSED(boids), BoidRule *rule)
{
BoidParticle *bpa = pa->boid;
@@ -1226,14 +1258,18 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
VECADDFAC(pa->state.vel, pa->state.vel, acc, dtime);
- if(bpa->data.mode != eBoidMode_InAir)
- bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
+ //if(bpa->data.mode != eBoidMode_InAir)
+ bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
/* change modes, constrain movement & keep track of down vector */
switch(bpa->data.mode) {
case eBoidMode_InAir:
{
- float grav[3] = {0.0f, 0.0f, bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f};
+ float grav[3];
+
+ grav[0]= 0.0f;
+ grav[1]= 0.0f;
+ grav[2]= bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;
/* don't take forward acceleration into account (better banking) */
if(dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) {
@@ -1255,17 +1291,29 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
boid_find_ground(bbd, pa, ground_co, ground_nor);
boid_climb(boids, pa, ground_co, ground_nor);
}
- /* land boid when belowg ground */
- else if(boids->options & BOID_ALLOW_LAND && pa->state.co[2] <= ground_co[2] + pa->size * boids->height) {
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- bpa->data.mode = eBoidMode_OnLand;
+ else if(pa->state.co[2] <= ground_co[2] + pa->size * boids->height) {
+ /* land boid when below ground */
+ if(boids->options & BOID_ALLOW_LAND) {
+ pa->state.co[2] = ground_co[2] + pa->size * boids->height;
+ pa->state.vel[2] = 0.0f;
+ bpa->data.mode = eBoidMode_OnLand;
+ }
+ /* fly above ground */
+ else {
+ pa->state.co[2] = ground_co[2] + pa->size * boids->height;
+ pa->state.vel[2] = 0.0f;
+ }
}
break;
}
case eBoidMode_Falling:
{
- float grav[3] = {0.0f, 0.0f, bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f};
+ float grav[3];
+
+ grav[0]= 0.0f;
+ grav[1]= 0.0f;
+ grav[2]= bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;
+
/* gather apparent gravity */
VECADDFAC(bpa->gravity, bpa->gravity, grav, dtime);
@@ -1355,7 +1403,9 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
/* save direction to state.ave unless the boid is falling */
/* (boids can't effect their direction when falling) */
if(bpa->data.mode!=eBoidMode_Falling && len_v3(pa->state.vel) > 0.1*pa->size) {
- normalize_v3_v3(pa->state.ave, pa->state.vel);
+ copy_v3_v3(pa->state.ave, pa->state.vel);
+ pa->state.ave[2] *= bbd->part->boids->pitch;
+ normalize_v3(pa->state.ave);
}
/* apply damping */
@@ -1420,7 +1470,7 @@ BoidRule *boid_new_rule(int type)
rule->type = type;
rule->flag |= BOIDRULE_IN_AIR|BOIDRULE_ON_LAND;
- strcpy(rule->name, boidrule_type_items[type-1].name);
+ BLI_strncpy(rule->name, boidrule_type_items[type-1].name, sizeof(rule->name));
return rule;
}
@@ -1440,6 +1490,7 @@ void boid_default_settings(BoidSettings *boids)
boids->landing_smoothness = 3.0f;
boids->banking = 1.0f;
+ boids->pitch = 1.0f;
boids->height = 1.0f;
boids->health = 1.0f;
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 71a43994363..15404acc105 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -45,6 +45,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_rand.h"
+#include "BLI_utildefines.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
@@ -67,7 +68,7 @@ static void brush_set_defaults(Brush *brush)
brush->blend = 0;
brush->flag = 0;
- brush->ob_mode = (OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT);
+ brush->ob_mode = OB_MODE_ALL_PAINT;
/* BRUSH SCULPT TOOL SETTINGS */
brush->size= 35; /* radius of the brush in pixels */
@@ -147,6 +148,8 @@ Brush *copy_brush(Brush *brush)
if (brush->icon_imbuf)
brushn->icon_imbuf= IMB_dupImBuf(brush->icon_imbuf);
+ brushn->preview = NULL;
+
brushn->curve= curvemapping_copy(brush->curve);
/* enable fake user by default */
@@ -183,13 +186,13 @@ void make_local_brush(Brush *brush)
Scene *scene;
int local= 0, lib= 0;
- if(brush->id.lib==0) return;
+ if(brush->id.lib==NULL) return;
if(brush->clone.image) {
/* special case: ima always local immediately */
- brush->clone.image->id.lib= 0;
+ brush->clone.image->id.lib= NULL;
brush->clone.image->id.flag= LIB_LOCAL;
- new_id(0, (ID *)brush->clone.image, 0);
+ new_id(NULL, (ID *)brush->clone.image, NULL);
}
for(scene= G.main->scene.first; scene; scene=scene->id.next)
@@ -199,9 +202,9 @@ void make_local_brush(Brush *brush)
}
if(local && lib==0) {
- brush->id.lib= 0;
+ brush->id.lib= NULL;
brush->id.flag= LIB_LOCAL;
- new_id(0, (ID *)brush, 0);
+ new_id(NULL, (ID *)brush, NULL);
/* enable fake user by default */
if (!(brush->id.flag & LIB_FAKEUSER)) {
@@ -216,7 +219,7 @@ void make_local_brush(Brush *brush)
for(scene= G.main->scene.first; scene; scene=scene->id.next)
if(paint_brush(&scene->toolsettings->imapaint.paint)==brush)
- if(scene->id.lib==0) {
+ if(scene->id.lib==NULL) {
paint_brush_set(&scene->toolsettings->imapaint.paint, brushn);
brushn->id.us++;
brush->id.us--;
@@ -226,10 +229,8 @@ void make_local_brush(Brush *brush)
void brush_debug_print_state(Brush *br)
{
- Brush def;
-
/* create a fake brush and set it to the defaults */
- memset(&def, 0, sizeof(Brush));
+ Brush def= {{NULL}};
brush_set_defaults(&def);
#define BR_TEST(field, t) \
@@ -423,7 +424,7 @@ int brush_texture_set_nr(Brush *brush, int nr)
id= (ID *)brush->mtex.tex;
idtest= (ID*)BLI_findlink(&G.main->tex, nr-1);
- if(idtest==0) { /* new tex */
+ if(idtest==NULL) { /* new tex */
if(id) idtest= (ID *)copy_texture((Tex *)id);
else idtest= (ID *)add_texture("Tex");
idtest->us--;
@@ -478,7 +479,7 @@ int brush_clone_image_delete(Brush *brush)
}
/* Brush Sampling */
-void brush_sample_tex(Brush *brush, float *xy, float *rgba)
+void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread)
{
MTex *mtex= &brush->mtex;
@@ -491,7 +492,7 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba)
co[1]= xy[1]/radius;
co[2]= 0.0f;
- hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta);
+ hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread);
if (hasrgb) {
rgba[0]= tr;
@@ -528,7 +529,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
if (*outbuf)
ibuf= *outbuf;
else
- ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag, 0);
+ ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag);
if (flt) {
for (y=0; y < ibuf->y; y++) {
@@ -545,12 +546,12 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius);
}
else if (texfall == 1) {
- brush_sample_tex(brush, xy, dstf);
+ brush_sample_tex(brush, xy, dstf, 0);
}
else {
dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
- brush_sample_tex(brush, xy, rgba);
+ brush_sample_tex(brush, xy, rgba, 0);
dstf[0] = rgba[0]*brush->rgb[0];
dstf[1] = rgba[1]*brush->rgb[1];
@@ -581,7 +582,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius));
}
else if (texfall == 1) {
- brush_sample_tex(brush, xy, rgba);
+ brush_sample_tex(brush, xy, rgba, 0);
dst[0]= FTOCHAR(rgba[0]);
dst[1]= FTOCHAR(rgba[1]);
dst[2]= FTOCHAR(rgba[2]);
@@ -590,7 +591,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
else {
dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
- brush_sample_tex(brush, xy, rgba);
+ brush_sample_tex(brush, xy, rgba, 0);
dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
@@ -737,7 +738,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i
xy[0] = x + xoff;
xy[1] = y + yoff;
- brush_sample_tex(brush, xy, tf);
+ brush_sample_tex(brush, xy, tf, 0);
}
bf[0] = tf[0]*mf[0];
@@ -768,7 +769,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i
xy[0] = x + xoff;
xy[1] = y + yoff;
- brush_sample_tex(brush, xy, rgba);
+ brush_sample_tex(brush, xy, rgba, 0);
t[0]= FTOCHAR(rgba[0]);
t[1]= FTOCHAR(rgba[1]);
t[2]= FTOCHAR(rgba[2]);
@@ -794,11 +795,11 @@ static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float
imbflag= (cache->flt)? IB_rectfloat: IB_rect;
if (!cache->ibuf)
- cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag, 0);
+ cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
ibuf= cache->ibuf;
oldtexibuf= cache->texibuf;
- cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag, 0);
+ cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
if (oldtexibuf) {
srcx= srcy= 0;
@@ -906,7 +907,13 @@ static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pres
void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
{
- if(brush->jitter){
+ int use_jitter= brush->jitter != 0;
+
+ /* jitter-ed brush gives wierd and unpredictable result for this
+ kinds of stroke, so manyally disable jitter usage (sergey) */
+ use_jitter&= (brush->flag & (BRUSH_RESTORE_MESH|BRUSH_ANCHORED)) == 0;
+
+ if(use_jitter){
float rand_pos[2];
const int radius= brush_size(brush);
const int diameter= 2*radius;
@@ -1096,11 +1103,9 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
{
unsigned int *texcache = NULL;
MTex *mtex = &br->mtex;
- TexResult texres;
+ TexResult texres= {0};
int hasrgb, ix, iy;
int side = half_side * 2;
-
- memset(&texres, 0, sizeof(TexResult));
if(mtex->tex) {
float x, y, step = 2.0 / side, co[3];
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 0b2f491b28d..7a3c4bd5928 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -1,4 +1,4 @@
-/**
+/*
*
* $Id$
*
@@ -23,7 +23,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): André Pinto.
+ * Contributor(s): Andr Pinto.
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -34,15 +34,18 @@
#include "DNA_meshdata_types.h"
+#include "BLI_editVert.h"
+#include "BLI_utildefines.h"
+
#include "BKE_DerivedMesh.h"
-#include "BKE_utildefines.h"
+
#include "BLI_math.h"
#include "MEM_guardedalloc.h"
/* Math stuff for ray casting on mesh faces and for nearest surface */
-static float ray_tri_intersection(const BVHTreeRay *ray, const float m_dist, const float *v0, const float *v1, const float *v2)
+static float ray_tri_intersection(const BVHTreeRay *ray, const float UNUSED(m_dist), const float *v0, const float *v1, const float *v2)
{
float dist;
@@ -577,16 +580,34 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float
tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
if(tree != NULL)
{
- for(i = 0; i < numFaces; i++)
- {
- float co[4][3];
- VECCOPY(co[0], vert[ face[i].v1 ].co);
- VECCOPY(co[1], vert[ face[i].v2 ].co);
- VECCOPY(co[2], vert[ face[i].v3 ].co);
- if(face[i].v4)
- VECCOPY(co[3], vert[ face[i].v4 ].co);
-
- BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+ /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */
+ EditMesh *em= data->em_evil;
+ if(em) {
+ EditFace *efa= em->faces.first;
+ for(i = 0; i < numFaces; i++, efa= efa->next) {
+ if(!(efa->f & 1) && efa->h==0 && !((efa->v1->f&1)+(efa->v2->f&1)+(efa->v3->f&1)+(efa->v4?efa->v4->f&1:0))) {
+ float co[4][3];
+ VECCOPY(co[0], vert[ face[i].v1 ].co);
+ VECCOPY(co[1], vert[ face[i].v2 ].co);
+ VECCOPY(co[2], vert[ face[i].v3 ].co);
+ if(face[i].v4)
+ VECCOPY(co[3], vert[ face[i].v4 ].co);
+
+ BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+ }
+ }
+ }
+ else {
+ for(i = 0; i < numFaces; i++) {
+ float co[4][3];
+ VECCOPY(co[0], vert[ face[i].v1 ].co);
+ VECCOPY(co[1], vert[ face[i].v2 ].co);
+ VECCOPY(co[2], vert[ face[i].v3 ].co);
+ if(face[i].v4)
+ VECCOPY(co[3], vert[ face[i].v4 ].co);
+
+ BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+ }
}
BLI_bvhtree_balance(tree);
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 0374f4856ca..368e84cce30 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -53,6 +53,13 @@
#include "BLI_pbvh.h"
#include "BLI_array.h"
#include "BLI_smallhash.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_paint.h"
+
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -83,6 +90,7 @@ typedef struct {
/* Cached */
struct PBVH *pbvh;
int pbvh_draw;
+
/* Mesh connectivity */
struct ListBase *fmap;
struct IndexNode *fmap_mem;
@@ -204,7 +212,7 @@ static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
- Mesh *me= (ob)? ob->data: NULL;
+ Mesh *me= ob->data;
if(ob->sculpt->modifiers_active) return 0;
@@ -214,7 +222,6 @@ static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
- Mesh *me= (ob)? ob->data: NULL;
if(!ob) {
cddm->pbvh= NULL;
@@ -232,15 +239,42 @@ static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
this derivedmesh is just original mesh. it's the multires subsurf dm
that this is actually for, to support a pbvh on a modified mesh */
if(!cddm->pbvh && ob->type == OB_MESH) {
+ Mesh *me= ob->data;
cddm->pbvh = BLI_pbvh_new();
cddm->pbvh_draw = can_pbvh_draw(ob, dm);
BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
me->totface, me->totvert);
+
+ if(ob->sculpt->modifiers_active) {
+ float (*vertCos)[3];
+ int totvert;
+
+ totvert= dm->getNumVerts(dm);
+ vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
+ dm->getVertCos(dm, vertCos);
+ BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
+ MEM_freeN(vertCos);
+ }
}
return cddm->pbvh;
}
+/* update vertex normals so that drawing smooth faces works during sculpt
+ TODO: proper fix is to support the pbvh in all drawing modes */
+static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
+ float (*face_nors)[3];
+
+ if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData)
+ return;
+
+ face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+
+ BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
+}
+
static void cdDM_drawVerts(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@ -304,7 +338,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm)
GPU_uvedge_setup(dm);
if( !GPU_buffer_legacy(dm) ) {
for(i = 0; i < dm->numFaceData; i++, mf++) {
- if(mf->flag&ME_LOOSEEDGE) {
+ if(!(mf->flag&ME_HIDE)) {
draw = 1;
}
else {
@@ -433,7 +467,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm)
static void cdDM_drawFacesSolid(DerivedMesh *dm,
float (*partial_redraw_planes)[4],
- int fast, int (*setMaterial)(int, void *attribs))
+ int UNUSED(fast), int (*setMaterial)(int, void *attribs))
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mvert = cddm->mvert;
@@ -553,6 +587,8 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha
if(col1 && col2)
glEnable(GL_CULL_FACE);
+ cdDM_update_normals_from_pbvh(dm);
+
if( GPU_buffer_legacy(dm) ) {
DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
glShadeModel(GL_SMOOTH);
@@ -632,6 +668,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
if(!mcol)
mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
+ cdDM_update_normals_from_pbvh(dm);
+
if( GPU_buffer_legacy(dm) ) {
DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
for(i = 0; i < dm->numFaceData; i++, mf++) {
@@ -712,7 +750,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
GPU_vertex_setup( dm );
GPU_normal_setup( dm );
GPU_uv_setup( dm );
- if( col != 0 ) {
+ if( col != NULL ) {
/*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL ) {
col = 0;
} else if( mcol && dm->drawObject->colType == CD_MCOL ) {
@@ -740,6 +778,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
if( !GPU_buffer_legacy(dm) ) {
glShadeModel( GL_SMOOTH );
+ lastFlag = 0;
for(i = 0; i < dm->drawObject->nelements/3; i++) {
int actualFace = dm->drawObject->faceRemap[i];
int flag = 1;
@@ -750,6 +789,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
else {
if(index) {
orig = index[actualFace];
+ if(orig == ORIGINDEX_NONE) continue;
if(drawParamsMapped)
flag = drawParamsMapped(userData, orig);
}
@@ -792,7 +832,7 @@ static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tfa
cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
}
-static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
+static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs))
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mv = cddm->mvert;
@@ -807,22 +847,24 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
if(!mc)
mc = DM_get_tessface_data_layer(dm, CD_MCOL);
+ cdDM_update_normals_from_pbvh(dm);
+
/* back-buffer always uses legacy since VBO's would need the
* color array temporarily overwritten for drawing, then reset. */
if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
for(i = 0; i < dm->numFaceData; i++, mf++) {
int drawSmooth = (mf->flag & ME_SMOOTH);
+ int draw= 1;
- if(index) {
- orig = *index++;
- if(setDrawOptions && orig == ORIGINDEX_NONE)
- { if(nors) nors += 3; continue; }
- }
- else
- orig = i;
+ orig= (index==NULL) ? i : *index++;
+
+ if(orig == ORIGINDEX_NONE)
+ draw= setMaterial(mf->mat_nr + 1, NULL);
+ else if (setDrawOptions != NULL)
+ draw= setDrawOptions(userData, orig, &drawSmooth);
- if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
+ if(draw) {
unsigned char *cp = NULL;
if(useColors && mc)
@@ -887,34 +929,48 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
if( !GPU_buffer_legacy(dm) ) {
int tottri = dm->drawObject->nelements/3;
glShadeModel(GL_SMOOTH);
-
- for( i = 0; i < tottri; i++ ) {
- int actualFace = dm->drawObject->faceRemap[i];
- int drawSmooth = (mf[actualFace].flag & ME_SMOOTH);
- int draw = 1;
-
- if(index) {
- orig = index[actualFace];
- if(setDrawOptions && orig == ORIGINDEX_NONE)
- draw = 0;
- }
- else
- orig = actualFace;
-
- if(draw && setDrawOptions && !setDrawOptions(userData, orig, &drawSmooth))
- draw = 0;
-
- /* Goal is to draw as long of a contiguous triangle
- array as possible, so draw when we hit either an
- invisible triangle or at the end of the array */
- if(!draw || i == tottri - 1) {
- if(prevstart != i)
- /* Add one to the length (via `draw')
- if we're drawing at the end of the array */
- glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
- prevstart = i + 1;
+
+ if(tottri == 0) {
+ /* avoid buffer problems in following code */
+ }
+ if(setDrawOptions == NULL) {
+ /* just draw the entire face array */
+ glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
+ }
+ else {
+ /* we need to check if the next material changes */
+ int next_actualFace= dm->drawObject->faceRemap[0];
+
+ for( i = 0; i < tottri; i++ ) {
+ //int actualFace = dm->drawObject->faceRemap[i];
+ int actualFace = next_actualFace;
+ MFace *mface= mf + actualFace;
+ int drawSmooth= (mface->flag & ME_SMOOTH);
+ int draw = 1;
+
+ if(i != tottri-1)
+ next_actualFace= dm->drawObject->faceRemap[i+1];
+
+ orig= (index==NULL) ? actualFace : index[actualFace];
+
+ if(orig == ORIGINDEX_NONE)
+ draw= setMaterial(mface->mat_nr + 1, NULL);
+ else if (setDrawOptions != NULL)
+ draw= setDrawOptions(userData, orig, &drawSmooth);
+
+ /* Goal is to draw as long of a contiguous triangle
+ array as possible, so draw when we hit either an
+ invisible triangle or at the end of the array */
+ if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
+ if(prevstart != i)
+ /* Add one to the length (via `draw')
+ if we're drawing at the end of the array */
+ glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
+ prevstart = i + 1;
+ }
}
}
+
glShadeModel(GL_FLAT);
}
GPU_buffer_unbind();
@@ -926,28 +982,6 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
}
-#define PASSVERT(index, vert) { \
- if(attribs.totorco) \
- glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \
- for(b = 0; b < attribs.tottface; b++) { \
- MTFace *tf = &attribs.tface[b].array[a]; \
- glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
- } \
- for(b = 0; b < attribs.totmcol; b++) { \
- MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \
- GLubyte col[4]; \
- col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
- glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
- } \
- if(attribs.tottang) { \
- float *tang = attribs.tang.array[a*4 + vert]; \
- glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
- } \
- if(smoothnormal) \
- glNormal3sv(mvert[index].no); \
- glVertex3fv(mvert[index].co); \
- }
-
static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@ -957,25 +991,27 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
MFace *mface = cddm->mface;
MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
- int a, b, dodraw, smoothnormal, matnr, new_matnr;
+ int a, b, dodraw, matnr, new_matnr;
int transp, new_transp, orig_transp;
int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ cdDM_update_normals_from_pbvh(dm);
+
matnr = -1;
- smoothnormal = 0;
dodraw = 0;
transp = GPU_get_material_blend_mode();
orig_transp = transp;
glShadeModel(GL_SMOOTH);
- if( GPU_buffer_legacy(dm) || setDrawOptions != 0 ) {
+ if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
memset(&attribs, 0, sizeof(attribs));
glBegin(GL_QUADS);
for(a = 0; a < dm->numFaceData; a++, mface++) {
+ const int smoothnormal = (mface->flag & ME_SMOOTH);
new_matnr = mface->mat_nr + 1;
if(new_matnr != matnr) {
@@ -994,8 +1030,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
else if(setDrawOptions) {
orig = (index)? index[a]: a;
- if(orig == ORIGINDEX_NONE)
- continue;
+ if(orig == ORIGINDEX_NONE) {
+ /* since the material is set by setMaterial(), faces with no
+ * origin can be assumed to be generated by a modifier */
+
+ /* continue */
+ }
else if(!setDrawOptions(userData, orig))
continue;
}
@@ -1016,8 +1056,6 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
}
}
- smoothnormal = (mface->flag & ME_SMOOTH);
-
if(!smoothnormal) {
if(nors) {
glNormal3fv(nors[a]);
@@ -1034,6 +1072,28 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
}
}
+#define PASSVERT(index, vert) { \
+ if(attribs.totorco) \
+ glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \
+ for(b = 0; b < attribs.tottface; b++) { \
+ MTFace *tf = &attribs.tface[b].array[a]; \
+ glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
+ } \
+ for(b = 0; b < attribs.totmcol; b++) { \
+ MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \
+ GLubyte col[4]; \
+ col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
+ glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
+ } \
+ if(attribs.tottang) { \
+ float *tang = attribs.tang.array[a*4 + vert]; \
+ glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \
+ } \
+ if(smoothnormal) \
+ glNormal3sv(mvert[index].no); \
+ glVertex3fv(mvert[index].co); \
+ }
+
PASSVERT(mface->v1, 0);
PASSVERT(mface->v2, 1);
PASSVERT(mface->v3, 2);
@@ -1042,13 +1102,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
else
PASSVERT(mface->v3, 2)
-#undef PASSVERT
}
glEnd();
}
else {
- GPUBuffer *buffer = 0;
- char *varray = 0;
+ GPUBuffer *buffer = NULL;
+ char *varray = NULL;
int numdata = 0, elementsize = 0, offset;
int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
int i;
@@ -1085,9 +1144,9 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
if( numdata != 0 ) {
- GPU_buffer_free(buffer,0);
+ GPU_buffer_free(buffer, NULL);
- buffer = 0;
+ buffer = NULL;
}
}
@@ -1119,22 +1178,22 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
}
if(attribs.tottang) {
datatypes[numdata].index = attribs.tang.glIndex;
- datatypes[numdata].size = 3;
+ datatypes[numdata].size = 4;
datatypes[numdata].type = GL_FLOAT;
numdata++;
}
if( numdata != 0 ) {
elementsize = GPU_attrib_element_size( datatypes, numdata );
- buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, 0 );
- if( buffer == 0 ) {
+ buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, NULL );
+ if( buffer == NULL ) {
GPU_buffer_unbind();
dm->drawObject->legacy = 1;
return;
}
varray = GPU_buffer_lock_stream(buffer);
- if( varray == 0 ) {
+ if( varray == NULL ) {
GPU_buffer_unbind();
- GPU_buffer_free(buffer, 0);
+ GPU_buffer_free(buffer, NULL);
dm->drawObject->legacy = 1;
return;
}
@@ -1209,12 +1268,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
}
if(attribs.tottang) {
float *tang = attribs.tang.array[a*4 + 0];
- VECCOPY((float *)&varray[elementsize*curface*3+offset], tang);
+ QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
tang = attribs.tang.array[a*4 + 1];
- VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
+ QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
tang = attribs.tang.array[a*4 + 2];
- VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
- offset += sizeof(float)*3;
+ QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
+ offset += sizeof(float)*4;
}
}
curface++;
@@ -1249,12 +1308,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
}
if(attribs.tottang) {
float *tang = attribs.tang.array[a*4 + 2];
- VECCOPY((float *)&varray[elementsize*curface*3+offset], tang);
+ QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
tang = attribs.tang.array[a*4 + 3];
- VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
+ QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
tang = attribs.tang.array[a*4 + 0];
- VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
- offset += sizeof(float)*3;
+ QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
+ offset += sizeof(float)*4;
}
}
curface++;
@@ -1273,7 +1332,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
}
GPU_buffer_unbind();
}
- GPU_buffer_free( buffer, 0 );
+ GPU_buffer_free( buffer, NULL );
}
glShadeModel(GL_FLAT);
@@ -1406,6 +1465,11 @@ static void cdDM_recalcTesselation(DerivedMesh *dm)
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
}
+void CDDM_recalc_tesselation(DerivedMesh *dm)
+{
+ cdDM_recalcTesselation(dm);
+}
+
/*ignores original poly origindex layer*/
static void cdDM_recalcTesselation2(DerivedMesh *dm)
{
@@ -1531,7 +1595,7 @@ DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, in
return dm;
}
-DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
+DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
{
CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
DerivedMesh *dm = &cddm->dm;
@@ -1570,7 +1634,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
return dm;
}
-DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
+DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
{
DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
BLI_countlist(&em->edges),
@@ -1622,7 +1686,6 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
mv->no[2] = eve->no[2] * 32767.0;
mv->bweight = (unsigned char) (eve->bweight * 255.0f);
- mv->mat_nr = 0;
mv->flag = 0;
*index = i;
@@ -1673,7 +1736,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
DerivedMesh *CDDM_from_curve(Object *ob)
{
- return CDDM_from_curve_customDB(ob, &((Curve *)ob->data)->disp);
+ return CDDM_from_curve_customDB(ob, &ob->disp);
}
DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
@@ -1821,7 +1884,6 @@ DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *me)
mv->no[1] = eve->no[1] * 32767.0;
mv->no[2] = eve->no[2] * 32767.0;
- mv->mat_nr = 0;
mv->flag = BMFlags_To_MEFlags(eve);
if (add_orig) *index = i;
@@ -2076,6 +2138,8 @@ DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces)
return dm;
}
+/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
+ * relationship betwen mesh data this needs to be set by the caller. */
DerivedMesh *CDDM_from_template(DerivedMesh *source,
int numVerts, int numEdges, int numFaces,
int numLoops, int numPolys)
@@ -2679,6 +2743,11 @@ MFace *CDDM_get_tessfaces(DerivedMesh *dm)
return ((CDDerivedMesh*)dm)->mface;
}
+MPoly *CDDM_get_polys(DerivedMesh *dm)
+{
+ return ((CDDerivedMesh*)dm)->mpoly;
+}
+
void CDDM_tessfaces_to_faces(DerivedMesh *dm)
{
/*converts mfaces to mpolys/mloops*/
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 8d4bacb977f..c115f6aa470 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -1,29 +1,29 @@
-/* cloth.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*
-* The Original Code is Copyright (C) Blender Foundation
-* All rights reserved.
-*
-* Contributor(s): Daniel Genrich
-*
-* ***** END GPL LICENSE BLOCK *****
-*/
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * Contributor(s): Daniel Genrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
#include "MEM_guardedalloc.h"
@@ -34,6 +34,7 @@
#include "BLI_math.h"
#include "BLI_edgehash.h"
+#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_cloth.h"
@@ -41,12 +42,6 @@
#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_pointcache.h"
-#include "BKE_utildefines.h"
-
-#include "BKE_pointcache.h"
-
-#include "BLI_kdopbvh.h"
-#include "BLI_cellalloc.h"
#ifdef _WIN32
void tstart ( void )
@@ -54,7 +49,7 @@ void tstart ( void )
void tend ( void )
{
}
-double tval()
+double tval( void )
{
return 0;
}
@@ -70,7 +65,7 @@ void tend ( void )
{
gettimeofday ( &_tend,&tz );
}
-double tval()
+double tval(void)
{
double t1, t2;
t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 );
@@ -92,7 +87,7 @@ static CM_SOLVER_DEF solvers [] =
/* Prototypes for internal functions.
*/
static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm);
-static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
+static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm );
static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first);
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm );
static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm );
@@ -168,7 +163,6 @@ static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float eps
BVHTree *bvhtree;
Cloth *cloth;
ClothVertex *verts;
- MFace *mfaces;
float co[12];
if(!clmd)
@@ -180,7 +174,6 @@ static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float eps
return NULL;
verts = cloth->verts;
- mfaces = cloth->mfaces;
// in the moment, return zero if no faces there
if(!cloth->numverts)
@@ -390,7 +383,8 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
Cloth *cloth;
ListBase *effectors = NULL;
MVert *mvert;
- int i, ret = 0;
+ unsigned int i = 0;
+ int ret = 0;
/* simulate 1 frame forward */
cloth = clmd->clothObject;
@@ -428,13 +422,13 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
/************************************************
* clothModifier_do - main simulation function
************************************************/
-DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
+DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm)
{
DerivedMesh *result;
PointCache *cache;
PTCacheID pid;
float timescale;
- int framedelta, framenr, startframe, endframe;
+ int framenr, startframe, endframe;
int cache_result;
clmd->scene= scene; /* nice to pass on later :) */
@@ -451,7 +445,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
return dm;
}
- if(clmd->sim_parms->reset || (framenr == (startframe - clmd->sim_parms->preroll)))
+ if(clmd->sim_parms->reset
+ || (framenr == (startframe - clmd->sim_parms->preroll) && clmd->sim_parms->preroll != 0)
+ || (clmd->clothObject && result->getNumVerts(result) != clmd->clothObject->numverts))
{
clmd->sim_parms->reset = 0;
cache->flag |= PTCACHE_OUTDATED;
@@ -462,17 +458,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
return result;
}
- /* verify we still have the same number of vertices, if not do nothing.
- * note that this should only happen if the number of vertices changes
- * during an animation due to a preceding modifier, this should not
- * happen because of object changes! */
- if(clmd->clothObject) {
- if(result->getNumVerts(result) != clmd->clothObject->numverts) {
- BKE_ptcache_invalidate(cache);
- return result;
- }
- }
-
// unused in the moment, calculated separately in implicit.c
clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
@@ -481,10 +466,10 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
BKE_ptcache_invalidate(cache);
/* do simulation */
- if(!do_init_cloth(ob, clmd, result, framenr))
+ if(!do_init_cloth(ob, clmd, dm, framenr))
return result;
- do_step_cloth(ob, clmd, result, framenr);
+ do_step_cloth(ob, clmd, dm, framenr);
cloth_to_object(ob, clmd, result);
return result;
@@ -499,25 +484,20 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
framenr= endframe;
}
- if(cache->flag & PTCACHE_SIMULATION_VALID)
- framedelta= framenr - cache->simframe;
- else
- framedelta= -1;
-
/* initialize simulation data if it didn't exist already */
- if(!do_init_cloth(ob, clmd, result, framenr))
+ if(!do_init_cloth(ob, clmd, dm, framenr))
return result;
if((framenr == startframe) && (clmd->sim_parms->preroll == 0)) {
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- do_init_cloth(ob, clmd, result, framenr);
+ do_init_cloth(ob, clmd, dm, framenr);
BKE_ptcache_validate(cache, framenr);
cache->flag &= ~PTCACHE_REDO_NEEDED;
return result;
}
/* try to read from cache */
- cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec);
+ cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe);
if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
implicit_set_positions(clmd);
@@ -526,7 +506,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
BKE_ptcache_validate(cache, framenr);
if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_write_cache(&pid, framenr);
+ BKE_ptcache_write(&pid, framenr);
return result;
}
@@ -541,18 +521,18 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
/* if on second frame, write cache for first frame */
if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
- BKE_ptcache_write_cache(&pid, startframe);
+ BKE_ptcache_write(&pid, startframe);
clmd->sim_parms->timescale *= framenr - cache->simframe;
/* do simulation */
BKE_ptcache_validate(cache, framenr);
- if(!do_step_cloth(ob, clmd, result, framenr)) {
+ if(!do_step_cloth(ob, clmd, dm, framenr)) {
BKE_ptcache_invalidate(cache);
}
else
- BKE_ptcache_write_cache(&pid, framenr);
+ BKE_ptcache_write(&pid, framenr);
cloth_to_object (ob, clmd, result);
@@ -560,7 +540,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
}
/* frees all */
-void cloth_free_modifier ( Object *ob, ClothModifierData *clmd )
+void cloth_free_modifier(ClothModifierData *clmd )
{
Cloth *cloth = NULL;
@@ -818,7 +798,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
}
}
-static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first)
+static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float UNUSED(framenr), int first)
{
int i = 0;
MVert *mvert = NULL;
@@ -831,7 +811,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
// If we have a clothObject, free it.
if ( clmd->clothObject != NULL )
{
- cloth_free_modifier ( ob, clmd );
+ cloth_free_modifier ( clmd );
if(G.rt > 0)
printf("cloth_free_modifier cloth_from_object\n");
}
@@ -855,7 +835,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
if ( !dm )
return 0;
- cloth_from_mesh ( ob, clmd, dm );
+ cloth_from_mesh ( clmd, dm );
// create springs
clmd->clothObject->springs = NULL;
@@ -911,7 +891,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
if ( !cloth_build_springs ( clmd, dm ) )
{
- cloth_free_modifier ( ob, clmd );
+ cloth_free_modifier ( clmd );
modifier_setError ( & ( clmd->modifier ), "Can't build springs." );
printf("cloth_free_modifier cloth_build_springs\n");
return 0;
@@ -945,11 +925,11 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
return 1;
}
-static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
+static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm )
{
unsigned int numverts = dm->getNumVerts ( dm );
unsigned int numfaces = dm->getNumTessFaces ( dm );
- MFace *mface = CDDM_get_tessfaces(dm);
+ MFace *mface = dm->getTessFaceArray( dm );
unsigned int i = 0;
/* Allocate our vertices. */
@@ -957,7 +937,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *
clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" );
if ( clmd->clothObject->verts == NULL )
{
- cloth_free_modifier ( ob, clmd );
+ cloth_free_modifier ( clmd );
modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." );
printf("cloth_free_modifier clmd->clothObject->verts\n");
return;
@@ -968,7 +948,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *
clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" );
if ( clmd->clothObject->mfaces == NULL )
{
- cloth_free_modifier ( ob, clmd );
+ cloth_free_modifier ( clmd );
modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." );
printf("cloth_free_modifier clmd->clothObject->mfaces\n");
return;
@@ -1020,7 +1000,7 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in
return 0;
}
-static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist)
+static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *UNUSED(edgehash), LinkNode **edgelist)
{
unsigned int i = 0;
@@ -1058,12 +1038,12 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
Cloth *cloth = clmd->clothObject;
ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL;
unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0;
- int i = 0;
- int numverts = dm->getNumVerts ( dm );
- int numedges = dm->getNumEdges ( dm );
- int numfaces = dm->getNumTessFaces ( dm );
- MEdge *medge = CDDM_get_edges ( dm );
- MFace *mface = CDDM_get_tessfaces ( dm );
+ unsigned int i = 0;
+ unsigned int numverts = (unsigned int)dm->getNumVerts ( dm );
+ unsigned int numedges = (unsigned int)dm->getNumEdges ( dm );
+ unsigned int numfaces = (unsigned int)dm->getNumTessFaces ( dm );
+ MEdge *medge = dm->getEdgeArray ( dm );
+ MFace *mface = dm->getTessFaceArray ( dm );
int index2 = 0; // our second vertex index
LinkNode **edgelist = NULL;
EdgeHash *edgehash = NULL;
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index af12d23b2c2..623ba26e86d 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -1,31 +1,31 @@
-/* collision.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*
-* The Original Code is Copyright (C) Blender Foundation
-* All rights reserved.
-*
-* The Original Code is: all of this file.
-*
-* Contributor(s): none yet.
-*
-* ***** END GPL LICENSE BLOCK *****
-*/
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
#include "MEM_guardedalloc.h"
@@ -42,6 +42,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
+#include "BLI_utildefines.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
@@ -49,7 +50,7 @@
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_modifier.h"
-#include "BKE_utildefines.h"
+
#include "BKE_DerivedMesh.h"
#ifdef USE_BULLET
#include "Bullet-C-Api.h"
@@ -79,11 +80,11 @@ void collision_move_object ( CollisionModifierData *collmd, float step, float pr
bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
}
-BVHTree *bvhtree_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 UNUSED(numverts), float epsilon )
{
BVHTree *tree;
float co[12];
- int i;
+ unsigned int i;
MFace *tface = mfaces;
tree = BLI_bvhtree_new ( numfaces*2, epsilon, 4, 26 );
@@ -106,7 +107,7 @@ BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert
return tree;
}
-void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving )
+void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int UNUSED(numverts), int moving )
{
int i;
MFace *mfaces = faces;
@@ -163,8 +164,8 @@ Collision modifier code end
*/
#define mySWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0)
-
-int
+#if 0 /* UNUSED */
+static int
gsl_poly_solve_cubic (double a, double b, double c,
double *x0, double *x1, double *x2)
{
@@ -254,7 +255,7 @@ gsl_poly_solve_cubic (double a, double b, double c,
*
* copied from GSL
*/
-int
+static int
gsl_poly_solve_quadratic (double a, double b, double c,
double *x0, double *x1)
{
@@ -312,7 +313,7 @@ gsl_poly_solve_quadratic (double a, double b, double c,
return 0;
}
}
-
+#endif /* UNUSED */
@@ -481,7 +482,7 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float
}
-int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
+static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
{
int result = 0;
Cloth *cloth1;
@@ -597,7 +598,7 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier
}
//Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned
-CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair )
+static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair )
{
ClothModifierData *clmd = ( ClothModifierData * ) md1;
CollisionModifierData *collmd = ( CollisionModifierData * ) md2;
@@ -1307,7 +1308,7 @@ static int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierDa
}
#endif
-static void add_collision_object(Object ***objs, int *numobj, int *maxobj, Object *ob, Object *self, int level)
+static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned int *maxobj, Object *ob, Object *self, int level)
{
CollisionModifierData *cmd= NULL;
@@ -1342,12 +1343,12 @@ static void add_collision_object(Object ***objs, int *numobj, int *maxobj, Objec
// return all collision objects in scene
// collision object will exclude self
-Object **get_collisionobjects(Scene *scene, Object *self, Group *group, int *numcollobj)
+Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj)
{
Base *base;
Object **objs;
GroupObject *go;
- int numobj= 0, maxobj= 100;
+ unsigned int numobj= 0, maxobj= 100;
objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
@@ -1358,9 +1359,9 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, int *num
add_collision_object(&objs, &numobj, &maxobj, go->ob, self, 0);
}
else {
- Scene *sce; /* for SETLOOPER macro */
+ Scene *sce_iter;
/* add objects in same layer in scene */
- for(SETLOOPER(scene, base)) {
+ for(SETLOOPER(scene, sce_iter, base)) {
if(base->lay & self->lay)
add_collision_object(&objs, &numobj, &maxobj, base->object, self, 0);
@@ -1417,11 +1418,11 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
add_collider_cache_object(&objs, go->ob, self, 0);
}
else {
- Scene *sce; /* for SETLOOPER macro */
+ Scene *sce_iter;
Base *base;
/* add objects in same layer in scene */
- for(SETLOOPER(scene, base)) {
+ for(SETLOOPER(scene, sce_iter, base)) {
if(!self || (base->lay & self->lay))
add_collider_cache_object(&objs, base->object, self, 0);
@@ -1456,13 +1457,13 @@ static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, Collis
static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index)
{
Cloth *cloth = clmd->clothObject;
- int i=0, j = 0, numfaces = 0, numverts = 0;
+ int i=0, j = 0, /*numfaces = 0,*/ numverts = 0;
ClothVertex *verts = NULL;
int ret = 0;
int result = 0;
float tnull[3] = {0,0,0};
- numfaces = clmd->clothObject->numfaces;
+ /*numfaces = clmd->clothObject->numfaces;*/ /*UNUSED*/
numverts = clmd->clothObject->numverts;
verts = cloth->verts;
@@ -1503,12 +1504,12 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl
{
Cloth *cloth= clmd->clothObject;
BVHTree *cloth_bvh= cloth->bvhtree;
- int i=0, numfaces = 0, numverts = 0, k, l, j;
+ unsigned int i=0, numfaces = 0, numverts = 0, k, l, j;
int rounds = 0; // result counts applied collisions; ic is for debug output;
ClothVertex *verts = NULL;
int ret = 0, ret2 = 0;
Object **collobjs = NULL;
- int numcollobj = 0;
+ unsigned int numcollobj = 0;
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh==NULL)
return 0;
@@ -1545,7 +1546,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl
Object *collob= collobjs[i];
CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision);
BVHTreeOverlap *overlap = NULL;
- int result = 0;
+ unsigned int result = 0;
if(!collmd->bvhtree)
continue;
@@ -1605,11 +1606,11 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl
////////////////////////////////////////////////////////////
if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF )
{
- for(l = 0; l < clmd->coll_parms->self_loop_count; l++)
+ for(l = 0; l < (unsigned int)clmd->coll_parms->self_loop_count; l++)
{
// TODO: add coll quality rounds again
BVHTreeOverlap *overlap = NULL;
- int result = 0;
+ unsigned int result = 0;
// collisions = 1;
verts = cloth->verts; // needed for openMP
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 90ffa39c88f..7cf6b21e2f1 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -41,19 +41,20 @@
#include "DNA_color_types.h"
#include "DNA_curve_types.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
#include "BKE_colortools.h"
#include "BKE_curve.h"
-#include "BKE_ipo.h"
-#include "BKE_utildefines.h"
+#include "BKE_fcurve.h"
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w)
+void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
{
int x, y;
float *rf= rectf;
@@ -74,7 +75,7 @@ void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, i
}
}
-void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w)
+void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
{
int x, y;
float *rf= rectf;
@@ -356,7 +357,7 @@ void curvemap_sethandle(CurveMap *cuma, int type)
/* *********************** Making the tables and display ************** */
/* reduced copy of garbled calchandleNurb() code in curve.c */
-static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
+static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int UNUSED(mode))
{
float *p1,*p2,*p3,pt[3];
float dx1,dy1, dx,dy, vx,vy, len,len1,len2;
@@ -830,6 +831,10 @@ void colorcorrection_do_ibuf(ImBuf *ibuf, const char *profile)
cmsCloseProfile(proofingProfile);
}
}
+#else
+ /* unused */
+ (void)ibuf;
+ (void)profile;
#endif
}
@@ -865,7 +870,7 @@ void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf)
if(ibuf->channels)
stride= ibuf->channels;
- for(pixel= ibuf->x*ibuf->y; pixel>0; pixel--, pix_in+=stride, pix_out+=4) {
+ for(pixel= ibuf->x*ibuf->y; pixel>0; pixel--, pix_in+=stride, pix_out+=stride) {
if(stride<3) {
col[0]= curvemap_evaluateF(cumap->cm, *pix_in);
@@ -952,13 +957,11 @@ void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size)
DO_INLINE int get_bin_float(float f)
{
- int bin= (int)(f*255);
+ int bin= (int)((f*255) + 0.5); /* 0.5 to prevent quantisation differences */
/* note: clamp integer instead of float to avoid problems with NaN */
CLAMP(bin, 0, 255);
-
- //return (int) (((f + 0.25) / 1.5) * 255);
-
+
return bin;
}
@@ -1000,7 +1003,8 @@ DO_INLINE void save_sample_line(Scopes *scopes, const int idx, const float fx, f
void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
{
- int x, y, c, n, nl;
+ int x, y, c;
+ unsigned int n, nl;
double div, divl;
float *rf=NULL;
unsigned char *rc=NULL;
@@ -1008,6 +1012,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
int savedlines, saveline;
float rgb[3], ycc[3], luma;
int ycc_mode=-1;
+ const short is_float = (ibuf->rect_float != NULL);
+
+ if (ibuf->rect==NULL && ibuf->rect_float==NULL) return;
if (scopes->ok == 1 ) return;
@@ -1015,6 +1022,7 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
/* hmmmm */
if (!(ELEM(ibuf->channels, 3, 4))) return;
+
scopes->hist.channels = 3;
scopes->hist.x_resolution = 256;
@@ -1069,9 +1077,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
scopes->waveform_3= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3");
scopes->vecscope= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel");
- if (ibuf->rect_float)
+ if (is_float)
rf = ibuf->rect_float;
- else if (ibuf->rect)
+ else
rc = (unsigned char *)ibuf->rect;
for (y = 0; y < ibuf->y; y++) {
@@ -1080,13 +1088,13 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
} else saveline=0;
for (x = 0; x < ibuf->x; x++) {
- if (ibuf->rect_float) {
+ if (is_float) {
if (use_color_management)
linearrgb_to_srgb_v3_v3(rgb, rf);
else
copy_v3_v3(rgb, rf);
}
- else if (ibuf->rect) {
+ else {
for (c=0; c<3; c++)
rgb[c] = rc[c] * INV_255;
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index fd8bd67e8f4..36d19b53ed2 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -40,6 +40,7 @@
#include "BLI_math.h"
#include "BLI_editVert.h"
#include "BLI_cellalloc.h"
+#include "BLI_utildefines.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
@@ -54,7 +55,7 @@
#include "DNA_text_types.h"
#include "DNA_windowmanager_types.h"
-#include "BKE_utildefines.h"
+
#include "BKE_action.h"
#include "BKE_anim.h" /* for the curve calculation part */
#include "BKE_armature.h"
@@ -74,7 +75,7 @@
#include "BKE_mesh.h"
#include "BKE_tessmesh.h"
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -375,7 +376,7 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
else {
/* objects */
if (from==CONSTRAINT_SPACE_WORLD && to==CONSTRAINT_SPACE_LOCAL) {
- /* check if object has a parent - otherwise this won't work */
+ /* check if object has a parent */
if (ob->parent) {
/* 'subtract' parent's effects from owner */
mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat);
@@ -383,6 +384,18 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
copy_m4_m4(tempmat, mat);
mul_m4_m4m4(mat, tempmat, imat);
}
+ else {
+ /* Local space in this case will have to be defined as local to the owner's
+ * transform-property-rotated axes. So subtract this rotation component.
+ */
+ object_to_mat4(ob, diff_mat);
+ normalize_m4(diff_mat);
+ zero_v3(diff_mat[3]);
+
+ invert_m4_m4(imat, diff_mat);
+ copy_m4_m4(tempmat, mat);
+ mul_m4_m4m4(mat, tempmat, imat);
+ }
}
else if (from==CONSTRAINT_SPACE_LOCAL && to==CONSTRAINT_SPACE_WORLD) {
/* check that object has a parent - otherwise this won't work */
@@ -392,6 +405,17 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat);
mul_m4_m4m4(mat, tempmat, diff_mat);
}
+ else {
+ /* Local space in this case will have to be defined as local to the owner's
+ * transform-property-rotated axes. So add back this rotation component.
+ */
+ object_to_mat4(ob, diff_mat);
+ normalize_m4(diff_mat);
+ zero_v3(diff_mat[3]);
+
+ copy_m4_m4(tempmat, mat);
+ mul_m4_m4m4(mat, tempmat, diff_mat);
+ }
}
}
}
@@ -399,7 +423,7 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
/* ------------ General Target Matrix Tools ---------- */
/* function that sets the given matrix based on given vertex group in mesh */
-static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, float mat[][4])
+static void contarget_get_mesh_mat (Scene *scene, Object *ob, const char *substring, float mat[][4])
{
DerivedMesh *dm = NULL;
Mesh *me= ob->data;
@@ -502,7 +526,7 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, f
}
/* function that sets the given matrix based on given vertex group in lattice */
-static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][4])
+static void contarget_get_lattice_mat (Object *ob, const char *substring, float mat[][4])
{
Lattice *lt= (Lattice *)ob->data;
@@ -560,7 +584,7 @@ static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][
/* generic function to get the appropriate matrix for most target cases */
/* The cases where the target can be object data have not been implemented */
-static void constraint_target_to_mat4 (Scene *scene, Object *ob, char *substring, float mat[][4], short from, short to, float headtail)
+static void constraint_target_to_mat4 (Scene *scene, Object *ob, const char *substring, float mat[][4], short from, short to, float headtail)
{
/* Case OBJECT */
if (!strlen(substring)) {
@@ -657,7 +681,7 @@ static bConstraintTypeInfo CTI_CONSTRNAME = {
/* This function should be used for the get_target_matrix member of all
* constraints that are not picky about what happens to their target matrix.
*/
-static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
if (VALID_CONS_TARGET(ct))
constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
@@ -676,7 +700,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
\
ct->tar= datatar; \
- strcpy(ct->subtarget, datasubtarget); \
+ BLI_strncpy(ct->subtarget, datasubtarget, sizeof(ct->subtarget)); \
ct->space= con->tarspace; \
ct->flag= CONSTRAINT_TAR_TEMP; \
\
@@ -730,7 +754,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
bConstraintTarget *ctn = ct->next; \
if (nocopy == 0) { \
datatar= ct->tar; \
- strcpy(datasubtarget, ct->subtarget); \
+ BLI_strncpy(datasubtarget, ct->subtarget, sizeof(datasubtarget)); \
con->tarspace= (char)ct->space; \
} \
\
@@ -812,50 +836,75 @@ static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
/* only evaluate if there is a target */
if (VALID_CONS_TARGET(ct)) {
- float parmat[4][4], invmat[4][4], tempmat[4][4];
- float loc[3], eul[3], size[3];
- float loco[3], eulo[3], sizo[3];
-
- /* get offset (parent-inverse) matrix */
- copy_m4_m4(invmat, data->invmat);
-
- /* extract components of both matrices */
- copy_v3_v3(loc, ct->matrix[3]);
- mat4_to_eulO(eul, ct->rotOrder, ct->matrix);
- mat4_to_size(size, ct->matrix);
-
- copy_v3_v3(loco, invmat[3]);
- mat4_to_eulO(eulo, cob->rotOrder, invmat);
- mat4_to_size(sizo, invmat);
-
- /* disable channels not enabled */
- if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f;
- if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f;
- if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f;
- if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f;
- if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f;
- if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f;
- if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f;
- if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f;
- if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f;
-
- /* make new target mat and offset mat */
- loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder);
- loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder);
-
- /* multiply target (parent matrix) by offset (parent inverse) to get
- * the effect of the parent that will be exherted on the owner
- */
- mul_m4_m4m4(parmat, invmat, ct->matrix);
+ float parmat[4][4];
- /* now multiply the parent matrix by the owner matrix to get the
- * the effect of this constraint (i.e. owner is 'parented' to parent)
- */
- copy_m4_m4(tempmat, cob->matrix);
- mul_m4_m4m4(cob->matrix, tempmat, parmat);
+ /* simple matrix parenting */
+ if(data->flag == CHILDOF_ALL) {
+
+ /* multiply target (parent matrix) by offset (parent inverse) to get
+ * the effect of the parent that will be exherted on the owner
+ */
+ mul_m4_m4m4(parmat, data->invmat, ct->matrix);
+
+ /* now multiply the parent matrix by the owner matrix to get the
+ * the effect of this constraint (i.e. owner is 'parented' to parent)
+ */
+ mul_m4_m4m4(cob->matrix, cob->matrix, parmat);
+ }
+ else {
+ float invmat[4][4], tempmat[4][4];
+ float loc[3], eul[3], size[3];
+ float loco[3], eulo[3], sizo[3];
+
+ /* get offset (parent-inverse) matrix */
+ copy_m4_m4(invmat, data->invmat);
+
+ /* extract components of both matrices */
+ copy_v3_v3(loc, ct->matrix[3]);
+ mat4_to_eulO(eul, ct->rotOrder, ct->matrix);
+ mat4_to_size(size, ct->matrix);
+
+ copy_v3_v3(loco, invmat[3]);
+ mat4_to_eulO(eulo, cob->rotOrder, invmat);
+ mat4_to_size(sizo, invmat);
+
+ /* disable channels not enabled */
+ if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f;
+ if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f;
+ if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f;
+ if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f;
+ if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f;
+ if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f;
+ if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f;
+ if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f;
+ if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f;
+
+ /* make new target mat and offset mat */
+ loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder);
+ loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder);
+
+ /* multiply target (parent matrix) by offset (parent inverse) to get
+ * the effect of the parent that will be exherted on the owner
+ */
+ mul_m4_m4m4(parmat, invmat, ct->matrix);
+
+ /* now multiply the parent matrix by the owner matrix to get the
+ * the effect of this constraint (i.e. owner is 'parented' to parent)
+ */
+ copy_m4_m4(tempmat, cob->matrix);
+ mul_m4_m4m4(cob->matrix, tempmat, parmat);
+
+ /* without this, changes to scale and rotation can change location
+ * of a parentless bone or a disconnected bone. Even though its set
+ * to zero above. */
+ if (!(data->flag & CHILDOF_LOCX)) cob->matrix[3][0]= tempmat[3][0];
+ if (!(data->flag & CHILDOF_LOCY)) cob->matrix[3][1]= tempmat[3][1];
+ if (!(data->flag & CHILDOF_LOCZ)) cob->matrix[3][2]= tempmat[3][2];
+ }
}
}
+/* XXX note, con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in readfile.c */
static bConstraintTypeInfo CTI_CHILDOF = {
CONSTRAINT_TYPE_CHILDOF, /* type */
sizeof(bChildOfConstraint), /* size */
@@ -1102,7 +1151,7 @@ static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy
}
}
-static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bKinematicConstraint *data= con->data;
@@ -1190,19 +1239,18 @@ static void followpath_flush_tars (bConstraint *con, ListBase *list, short nocop
}
}
-static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bFollowPathConstraint *data= con->data;
if (VALID_CONS_TARGET(ct)) {
Curve *cu= ct->tar->data;
- float q[4], vec[4], dir[3], quat[4], radius, x1;
- float totmat[4][4];
+ float vec[4], dir[3], radius;
+ float totmat[4][4]= MAT4_UNITY;
float curvetime;
-
- unit_m4(totmat);
+
unit_m4(ct->matrix);
-
+
/* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
@@ -1212,7 +1260,8 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
makeDispListCurveTypes(cob->scene, ct->tar, 0);
if (cu->path && cu->path->data) {
- if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
+ float quat[4];
+ if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
/* animated position along curve depending on time */
if (cob->scene)
curvetime= bsystem_time(cob->scene, ct->tar, cu->ctime, 0.0) - data->offset;
@@ -1233,8 +1282,10 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
curvetime= data->offset_fac;
}
- if ( where_on_path(ct->tar, curvetime, vec, dir, NULL, &radius, NULL) ) {
+ if ( where_on_path(ct->tar, curvetime, vec, dir, (data->followflag & FOLLOWPATH_FOLLOW) ? quat : NULL, &radius, NULL) ) { /* quat_pt is quat or NULL*/
if (data->followflag & FOLLOWPATH_FOLLOW) {
+#if 0
+ float x1, q[4];
vec_to_quat(quat, dir, (short)data->trackflag, (short)data->upflag);
normalize_v3(dir);
@@ -1244,10 +1295,13 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
q[2]= -x1*dir[1];
q[3]= -x1*dir[2];
mul_qt_qtqt(quat, q, quat);
-
+#else
+ quat_apply_track(quat, data->trackflag, data->upflag);
+#endif
+
quat_to_mat4(totmat, quat);
}
-
+
if (data->followflag & FOLLOWPATH_RADIUS) {
float tmat[4][4], rmat[4][4];
scale_m4_fl(tmat, radius);
@@ -1319,7 +1373,7 @@ static bConstraintTypeInfo CTI_FOLLOWPATH = {
/* --------- Limit Location --------- */
-static void loclimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+static void loclimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
{
bLocLimitConstraint *data = con->data;
@@ -1367,7 +1421,7 @@ static bConstraintTypeInfo CTI_LOCLIMIT = {
/* -------- Limit Rotation --------- */
-static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
{
bRotLimitConstraint *data = con->data;
float loc[3];
@@ -1376,9 +1430,9 @@ static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t
copy_v3_v3(loc, cob->matrix[3]);
mat4_to_size(size, cob->matrix);
-
+
mat4_to_eulO(eul, cob->rotOrder, cob->matrix);
-
+
/* constraint data uses radians internally */
/* limiting of euler values... */
@@ -1426,7 +1480,7 @@ static bConstraintTypeInfo CTI_ROTLIMIT = {
/* --------- Limit Scaling --------- */
-static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
{
bSizeLimitConstraint *data = con->data;
float obsize[3], size[3];
@@ -1631,8 +1685,9 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
mat4_to_size(size, cob->matrix);
/* to allow compatible rotations, must get both rotations in the order of the owner... */
- mat4_to_eulO(eul, cob->rotOrder, ct->matrix);
mat4_to_eulO(obeul, cob->rotOrder, cob->matrix);
+ /* we must get compatible eulers from the beginning because some of them can be modified below (see bug #21875) */
+ mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix);
if ((data->flag & ROTLIKE_X)==0)
eul[0] = obeul[0];
@@ -1664,6 +1719,7 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
eul[2] *= -1;
}
+ /* good to make eulers compatible again, since we don't know how much they were changed above */
compatible_eul(eul, obeul);
loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
}
@@ -1818,7 +1874,7 @@ static void translike_flush_tars (bConstraint *con, ListBase *list, short nocopy
}
}
-static void translike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+static void translike_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
{
bConstraintTarget *ct= targets->first;
@@ -1854,7 +1910,7 @@ static void samevolume_new_data (void *cdata)
data->volume = 1.0f;
}
-static void samevolume_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+static void samevolume_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
{
bSameVolumeConstraint *data= con->data;
@@ -1968,9 +2024,9 @@ static void pycon_id_looper (bConstraint *con, ConstraintIDFunc func, void *user
}
/* Whether this approach is maintained remains to be seen (aligorith) */
-static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
bPythonConstraint *data= con->data;
#endif
@@ -1990,7 +2046,7 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT
constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
/* only execute target calculation if allowed */
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
if (G.f & G_SCRIPT_AUTOEXEC)
BPY_pyconstraint_target(data, ct);
#endif
@@ -2001,7 +2057,8 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT
static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
{
-#ifdef DISABLE_PYTHON
+#ifndef WITH_PYTHON
+ (void)con; (void)cob; (void)targets; /* unused */
return;
#else
bPythonConstraint *data= con->data;
@@ -2019,8 +2076,8 @@ static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targ
#endif
/* Now, run the actual 'constraint' function, which should only access the matrices */
- BPY_pyconstraint_eval(data, cob, targets);
-#endif /* DISABLE_PYTHON */
+ BPY_pyconstraint_exec(data, cob, targets);
+#endif /* WITH_PYTHON */
}
static bConstraintTypeInfo CTI_PYTHON = {
@@ -2092,9 +2149,8 @@ static void actcon_flush_tars (bConstraint *con, ListBase *list, short nocopy)
}
}
-static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
- extern void chan_calc_mat(bPoseChannel *chan);
bActionConstraint *data = con->data;
if (VALID_CONS_TARGET(ct)) {
@@ -2162,7 +2218,7 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint
what_does_obaction(cob->scene, cob->ob, &workob, pose, data->act, pchan->name, t);
/* convert animation to matrices for use here */
- chan_calc_mat(tchan);
+ pchan_calc_mat(tchan);
copy_m4_m4(ct->matrix, tchan->chan_mat);
/* Clean up */
@@ -2183,7 +2239,7 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint
}
}
-static void actcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+static void actcon_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
{
bConstraintTarget *ct= targets->first;
@@ -2983,6 +3039,7 @@ static void rbj_id_looper (bConstraint *con, ConstraintIDFunc func, void *userda
/* target only */
func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->child, userdata);
}
static int rbj_get_tars (bConstraint *con, ListBase *list)
@@ -3063,7 +3120,7 @@ static void clampto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
}
}
-static void clampto_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+static void clampto_get_tarmat (bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
if (VALID_CONS_TARGET(ct)) {
Curve *cu= ct->tar->data;
@@ -3092,11 +3149,11 @@ static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
/* only evaluate if there is a target and it is a curve */
if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) {
Curve *cu= data->tar->data;
- float obmat[4][4], targetMatrix[4][4], ownLoc[3];
+ float obmat[4][4], ownLoc[3];
float curveMin[3], curveMax[3];
+ float targetMatrix[4][4]= MAT4_UNITY;
copy_m4_m4(obmat, cob->matrix);
- unit_m4(targetMatrix);
copy_v3_v3(ownLoc, obmat[3]);
INIT_MINMAX(curveMin, curveMax)
@@ -3397,7 +3454,7 @@ static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocop
}
-static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
@@ -3409,12 +3466,11 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
float dist;
SpaceTransform transform;
- DerivedMesh *target = object_get_derived_final(cob->scene, ct->tar, CD_MASK_BAREMESH);
+ DerivedMesh *target = object_get_derived_final(ct->tar);
BVHTreeRayHit hit;
BVHTreeNearest nearest;
- BVHTreeFromMesh treeData;
- memset(&treeData, 0, sizeof(treeData));
+ BVHTreeFromMesh treeData= {NULL};
nearest.index = -1;
nearest.dist = FLT_MAX;
@@ -3449,7 +3505,9 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
dist = len_v3v3(co, nearest.co);
- interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist)/dist); /* linear interpolation */
+ if(dist != 0.0f) {
+ interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist)/dist); /* linear interpolation */
+ }
space_transform_invert(&transform, co);
break;
@@ -3500,7 +3558,7 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
}
}
-static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+static void shrinkwrap_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
{
bConstraintTarget *ct= targets->first;
@@ -3716,7 +3774,7 @@ static void splineik_flush_tars (bConstraint *con, ListBase *list, short nocopy)
}
}
-static void splineik_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+static void splineik_get_tarmat (bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
if (VALID_CONS_TARGET(ct)) {
Curve *cu= ct->tar->data;
@@ -3796,6 +3854,9 @@ static void pivotcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t
float pivot[3], vec[3];
float rotMat[3][3];
+
+ /* pivot correction */
+ float axis[3], angle;
/* firstly, check if pivoting should take place based on the current rotation */
if (data->rotAxis != PIVOTCON_AXIS_NONE) {
@@ -3838,10 +3899,20 @@ static void pivotcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t
// TODO: perhaps we might want to include scaling based on the pivot too?
copy_m3_m4(rotMat, cob->matrix);
normalize_m3(rotMat);
-
+
+
+ /* correct the pivot by the rotation axis otherwise the pivot translates when it shouldnt */
+ mat3_to_axis_angle(axis, &angle, rotMat);
+ if(angle) {
+ float dvec[3];
+ sub_v3_v3v3(vec, pivot, cob->matrix[3]);
+ project_v3_v3v3(dvec, vec, axis);
+ sub_v3_v3(pivot, dvec);
+ }
+
/* perform the pivoting... */
/* 1. take the vector from owner to the pivot */
- sub_v3_v3v3(vec, pivot, cob->matrix[3]);
+ sub_v3_v3v3(vec, cob->matrix[3], pivot);
/* 2. rotate this vector by the rotation of the object... */
mul_m3_v3(rotMat, vec);
/* 3. make the rotation in terms of the pivot now */
@@ -3875,7 +3946,7 @@ static bConstraintTypeInfo *constraintsTypeInfo[NUM_CONSTRAINT_TYPES];
static short CTI_INIT= 1; /* when non-zero, the list needs to be updated */
/* This function only gets called when CTI_INIT is non-zero */
-static void constraints_init_typeinfo () {
+static void constraints_init_typeinfo (void) {
constraintsTypeInfo[0]= NULL; /* 'Null' Constraint */
constraintsTypeInfo[1]= &CTI_CHILDOF; /* ChildOf Constraint */
constraintsTypeInfo[2]= &CTI_TRACKTO; /* TrackTo Constraint */
@@ -4078,6 +4149,21 @@ static bConstraint *add_new_constraint (Object *ob, bPoseChannel *pchan, const c
constraints_set_active(list, con);
}
+ /* set type+owner specific immutable settings */
+ // TODO: does action constraint need anything here - i.e. spaceonce?
+ switch (type) {
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ /* if this constraint is being added to a posechannel, make sure
+ * the constraint gets evaluated in pose-space */
+ if (pchan) {
+ con->ownspace = CONSTRAINT_SPACE_POSE;
+ con->flag |= CONSTRAINT_SPACEONCE;
+ }
+ }
+ break;
+ }
+
return con;
}
@@ -4148,7 +4234,7 @@ void id_loop_constraints (ListBase *conlist, ConstraintIDFunc func, void *userda
/* ......... */
/* helper for copy_constraints(), to be used for making sure that ID's are valid */
-static void con_extern_cb(bConstraint *con, ID **idpoin, void *userdata)
+static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, void *UNUSED(userData))
{
if (*idpoin && (*idpoin)->lib)
id_lib_extern(*idpoin);
@@ -4351,8 +4437,7 @@ void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n,
void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
{
bConstraint *con;
- float solution[4][4], delta[4][4];
- float oldmat[4][4], imat[4][4];
+ float oldmat[4][4];
float enf;
/* check that there is a valid constraint object to evaluate */
@@ -4404,7 +4489,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
}
}
- /* Solve the constraint */
+ /* Solve the constraint and put result in cob->matrix */
cti->evaluate_constraint(con, cob, &targets);
/* clear targets after use
@@ -4416,23 +4501,13 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
}
/* Interpolate the enforcement, to blend result of constraint into final owner transform */
- /* 1. Remove effects of original matrix from constraint solution ==> delta */
- invert_m4_m4(imat, oldmat);
- copy_m4_m4(solution, cob->matrix);
- mul_m4_m4m4(delta, solution, imat);
-
- /* 2. If constraint influence is not full strength, then interpolate
- * identity_matrix --> delta_matrix to get the effect the constraint actually exerts
- */
+ /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate, or did I miss something? -jahka */
if (enf < 1.0) {
- float identity[4][4];
- unit_m4(identity);
- blend_m4_m4m4(delta, identity, delta, enf);
+ float solution[4][4];
+ copy_m4_m4(solution, cob->matrix);
+ blend_m4_m4m4(cob->matrix, oldmat, solution, enf);
}
- /* 3. Now multiply the delta by the matrix in use before the evaluation */
- mul_m4_m4m4(cob->matrix, delta, oldmat);
-
/* move owner back into worldspace for next constraint/other business */
if ((con->flag & CONSTRAINT_SPACEONCE) == 0)
constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD);
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 4b1ea2809bc..6f7188115e0 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -52,8 +52,10 @@
#endif
#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
+#endif
/* struct */
@@ -69,6 +71,7 @@ struct bContext {
struct ARegion *region;
struct ARegion *menu;
struct bContextStore *store;
+ const char *operator_poll_msg; /* reason for poll failing */
} wm;
/* data context */
@@ -95,7 +98,7 @@ struct bContext {
/* context */
-bContext *CTX_create()
+bContext *CTX_create(void)
{
bContext *C;
@@ -174,7 +177,7 @@ void CTX_free(bContext *C)
/* store */
-bContextStore *CTX_store_add(ListBase *contexts, char *name, PointerRNA *ptr)
+bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr)
{
bContextStoreEntry *entry;
bContextStore *ctx, *lastctx;
@@ -245,7 +248,7 @@ void CTX_py_init_set(bContext *C, int value)
C->data.py_init= value;
}
-void *CTX_py_dict_get(bContext *C)
+void *CTX_py_dict_get(const bContext *C)
{
return C->data.py_context;
}
@@ -466,6 +469,16 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu)
C->wm.menu= menu;
}
+void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
+{
+ C->wm.operator_poll_msg= msg;
+}
+
+const char *CTX_wm_operator_poll_msg_get(bContext *C)
+{
+ return C->wm.operator_poll_msg;
+}
+
/* data context utility functions */
struct bContextDataResult {
@@ -481,10 +494,10 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res
int ret= 0;
memset(result, 0, sizeof(bContextDataResult));
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
if(CTX_py_dict_get(C)) {
- return BPY_context_get(C, member, result);
-// if (BPY_context_get(C, member, result))
+ return BPY_context_member_get(C, member, result);
+// if (BPY_context_member_get(C, member, result))
// return 1;
}
#endif
@@ -610,8 +623,7 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member)
return result.list;
}
else {
- ListBase list;
- memset(&list, 0, sizeof(list));
+ ListBase list= {NULL, NULL};
return list;
}
}
@@ -830,7 +842,7 @@ int CTX_data_mode_enum(const bContext *C)
/* would prefer if we can use the enum version below over this one - Campbell */
/* must be aligned with above enum */
-static char *data_mode_strings[] = {
+static const char *data_mode_strings[] = {
"mesh_edit",
"curve_edit",
"surface_edit",
@@ -845,9 +857,9 @@ static char *data_mode_strings[] = {
"texturepaint",
"particlemode",
"objectmode",
- 0
+ NULL
};
-char *CTX_data_mode_string(const bContext *C)
+const char *CTX_data_mode_string(const bContext *C)
{
return data_mode_strings[CTX_data_mode_enum(C)];
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 5f5958f8893..67e988249f5 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -35,8 +35,10 @@
#include <stdlib.h>
#include "MEM_guardedalloc.h"
+
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
#include "DNA_material_types.h"
@@ -58,7 +60,7 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_utildefines.h" // VECCOPY
+
#include "ED_curve.h"
@@ -75,12 +77,22 @@ void unlink_curve(Curve *cu)
for(a=0; a<cu->totcol; a++) {
if(cu->mat[a]) cu->mat[a]->id.us--;
- cu->mat[a]= 0;
+ cu->mat[a]= NULL;
}
if(cu->vfont) cu->vfont->id.us--;
- cu->vfont= 0;
+ cu->vfont= NULL;
+
+ if(cu->vfontb) cu->vfontb->id.us--;
+ cu->vfontb= NULL;
+
+ if(cu->vfonti) cu->vfonti->id.us--;
+ cu->vfonti= NULL;
+
+ if(cu->vfontbi) cu->vfontbi->id.us--;
+ cu->vfontbi= NULL;
+
if(cu->key) cu->key->id.us--;
- cu->key= 0;
+ cu->key= NULL;
}
/* frees editcurve entirely */
@@ -121,7 +133,7 @@ void free_curve(Curve *cu)
if(cu->tb) MEM_freeN(cu->tb);
}
-Curve *add_curve(char *name, int type)
+Curve *add_curve(const char *name, int type)
{
Curve *cu;
@@ -130,7 +142,7 @@ Curve *add_curve(char *name, int type)
cu->size[0]= cu->size[1]= cu->size[2]= 1.0;
cu->flag= CU_FRONT|CU_BACK|CU_DEFORM_BOUNDS_OFF|CU_PATH_RADIUS;
cu->pathlen= 100;
- cu->resolu= cu->resolv= 12;
+ cu->resolu= cu->resolv= (type == OB_SURF) ? 4 : 12;
cu->width= 1.0;
cu->wordspace = 1.0;
cu->spacing= cu->linedist= 1.0;
@@ -146,7 +158,7 @@ Curve *add_curve(char *name, int type)
cu->vfont= cu->vfontb= cu->vfonti= cu->vfontbi= get_builtin_font();
cu->vfont->id.us+=4;
cu->str= MEM_mallocN(12, "str");
- strcpy(cu->str, "Text");
+ BLI_strncpy(cu->str, "Text", 12);
cu->len= cu->pos= 4;
cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo new");
cu->totbox= cu->actbox= 1;
@@ -163,7 +175,7 @@ Curve *copy_curve(Curve *cu)
int a;
cun= copy_libblock(cu);
- cun->nurb.first= cun->nurb.last= 0;
+ cun->nurb.first= cun->nurb.last= NULL;
duplicateNurblist( &(cun->nurb), &(cu->nurb));
cun->mat= MEM_dupallocN(cu->mat);
@@ -179,9 +191,9 @@ Curve *copy_curve(Curve *cu)
cun->key= copy_key(cu->key);
if(cun->key) cun->key->from= (ID *)cun;
- cun->disp.first= cun->disp.last= 0;
- cun->bev.first= cun->bev.last= 0;
- cun->path= 0;
+ cun->disp.first= cun->disp.last= NULL;
+ cun->bev.first= cun->bev.last= NULL;
+ cun->path= NULL;
cun->editnurb= NULL;
cun->editfont= NULL;
@@ -201,7 +213,7 @@ Curve *copy_curve(Curve *cu)
void make_local_curve(Curve *cu)
{
- Object *ob = 0;
+ Object *ob = NULL;
Curve *cun;
int local=0, lib=0;
@@ -210,14 +222,17 @@ void make_local_curve(Curve *cu)
* - mixed: do a copy
*/
- if(cu->id.lib==0) return;
-
- if(cu->vfont) cu->vfont->id.lib= 0;
-
+ if(cu->id.lib==NULL) return;
+
+ if(cu->vfont) cu->vfont->id.lib= NULL;
+ if(cu->vfontb) cu->vfontb->id.lib= NULL;
+ if(cu->vfonti) cu->vfonti->id.lib= NULL;
+ if(cu->vfontbi) cu->vfontbi->id.lib= NULL;
+
if(cu->id.us==1) {
- cu->id.lib= 0;
+ cu->id.lib= NULL;
cu->id.flag= LIB_LOCAL;
- new_id(0, (ID *)cu, 0);
+ new_id(NULL, (ID *)cu, NULL);
return;
}
@@ -231,9 +246,9 @@ void make_local_curve(Curve *cu)
}
if(local && lib==0) {
- cu->id.lib= 0;
+ cu->id.lib= NULL;
cu->id.flag= LIB_LOCAL;
- new_id(0, (ID *)cu, 0);
+ new_id(NULL, (ID *)cu, NULL);
}
else if(local && lib) {
cun= copy_curve(cu);
@@ -243,7 +258,7 @@ void make_local_curve(Curve *cu)
while(ob) {
if(ob->data==cu) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
ob->data= cun;
cun->id.us++;
cu->id.us--;
@@ -367,12 +382,12 @@ int count_curveverts_without_handles(ListBase *nurb)
void freeNurb(Nurb *nu)
{
- if(nu==0) return;
+ if(nu==NULL) return;
if(nu->bezt) MEM_freeN(nu->bezt);
- nu->bezt= 0;
+ nu->bezt= NULL;
if(nu->bp) MEM_freeN(nu->bp);
- nu->bp= 0;
+ nu->bp= NULL;
if(nu->knotsu) MEM_freeN(nu->knotsu);
nu->knotsu= NULL;
if(nu->knotsv) MEM_freeN(nu->knotsv);
@@ -388,7 +403,7 @@ void freeNurblist(ListBase *lb)
{
Nurb *nu, *next;
- if(lb==0) return;
+ if(lb==NULL) return;
nu= lb->first;
while(nu) {
@@ -396,7 +411,7 @@ void freeNurblist(ListBase *lb)
freeNurb(nu);
nu= next;
}
- lb->first= lb->last= 0;
+ lb->first= lb->last= NULL;
}
Nurb *duplicateNurb(Nurb *nu)
@@ -405,7 +420,7 @@ Nurb *duplicateNurb(Nurb *nu)
int len;
newnu= (Nurb*)MEM_mallocN(sizeof(Nurb),"duplicateNurb");
- if(newnu==0) return 0;
+ if(newnu==NULL) return NULL;
memcpy(newnu, nu, sizeof(Nurb));
if(nu->bezt) {
@@ -601,7 +616,7 @@ static void makecyclicknots(float *knots, short pnts, short order)
{
int a, b, order2, c;
- if(knots==0) return;
+ if(knots==NULL) return;
order2=order-1;
@@ -624,7 +639,7 @@ static void makecyclicknots(float *knots, short pnts, short order)
-void makeknots(Nurb *nu, short uv)
+static void makeknots(Nurb *nu, short uv)
{
if(nu->type == CU_NURBS) {
if(uv == 1) {
@@ -656,6 +671,16 @@ void makeknots(Nurb *nu, short uv)
}
}
+void nurbs_knot_calc_u(Nurb *nu)
+{
+ makeknots(nu, 1);
+}
+
+void nurbs_knot_calc_v(Nurb *nu)
+{
+ makeknots(nu, 2);
+}
+
static void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end)
{
float d, e;
@@ -719,16 +744,16 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas
}
-void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride)
+void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv)
/* coord_array has to be 3*4*resolu*resolv in size, and zero-ed */
{
BPoint *bp;
float *basisu, *basis, *basisv, *sum, *fp, *in;
float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv;
- int i, j, iofs, jofs, cycl, len, resolu, resolv;
+ int i, j, iofs, jofs, cycl, len, curu, curv;
int istart, iend, jsta, jen, *jstart, *jend, ratcomp;
- int totu = nu->pntsu*nu->resolu, totv = nu->pntsv*nu->resolv;
+ int totu = nu->pntsu*resolu, totv = nu->pntsv*resolv;
if(nu->knotsu==NULL || nu->knotsv==NULL) return;
if(nu->orderu>nu->pntsu) return;
@@ -785,9 +810,9 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride)
else cycl= 0;
v= vstart;
basis= basisv;
- resolv= totv;
- while(resolv--) {
- basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+resolv, jend+resolv);
+ curv= totv;
+ while(curv--) {
+ basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+curv, jend+curv);
basis+= KNOTSV(nu);
v+= vstep;
}
@@ -796,17 +821,17 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride)
else cycl= 0;
in= coord_array;
u= ustart;
- resolu= totu;
- while(resolu--) {
+ curu= totu;
+ while(curu--) {
basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
basis= basisv;
- resolv= totv;
- while(resolv--) {
+ curv= totv;
+ while(curv--) {
- jsta= jstart[resolv];
- jen= jend[resolv];
+ jsta= jstart[curv];
+ jen= jend[curv];
/* calculate sum */
sumdiv= 0.0;
@@ -894,7 +919,7 @@ void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radiu
if(nu->knotsu==NULL) return;
if(nu->orderu>nu->pntsu) return;
- if(coord_array==0) return;
+ if(coord_array==NULL) return;
/* allocate and initialize */
len= nu->pntsu;
@@ -1034,10 +1059,13 @@ static void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float
float *make_orco_surf(Object *ob)
{
+ /* Note: this function is used in convertblender only atm, so
+ * suppose nonzero curve's render resolution should always be used */
Curve *cu= ob->data;
Nurb *nu;
int a, b, tot=0;
int sizeu, sizev;
+ int resolu, resolv;
float *fp, *coord_array;
/* first calculate the size of the datablock */
@@ -1051,9 +1079,12 @@ float *make_orco_surf(Object *ob)
See also convertblender.c: init_render_surf()
*/
+
+ resolu= cu->resolu_ren ? cu->resolu_ren : nu->resolu;
+ resolv= cu->resolv_ren ? cu->resolv_ren : nu->resolv;
- sizeu = nu->pntsu*nu->resolu;
- sizev = nu->pntsv*nu->resolv;
+ sizeu = nu->pntsu*resolu;
+ sizev = nu->pntsv*resolv;
if (nu->flagu & CU_NURB_CYCLIC) sizeu++;
if (nu->flagv & CU_NURB_CYCLIC) sizev++;
if(nu->pntsv>1) tot+= sizeu * sizev;
@@ -1065,9 +1096,12 @@ float *make_orco_surf(Object *ob)
nu= cu->nurb.first;
while(nu) {
+ resolu= cu->resolu_ren ? cu->resolu_ren : nu->resolu;
+ resolv= cu->resolv_ren ? cu->resolv_ren : nu->resolv;
+
if(nu->pntsv>1) {
- sizeu = nu->pntsu*nu->resolu;
- sizev = nu->pntsv*nu->resolv;
+ sizeu = nu->pntsu*resolu;
+ sizev = nu->pntsv*resolv;
if (nu->flagu & CU_NURB_CYCLIC) sizeu++;
if (nu->flagv & CU_NURB_CYCLIC) sizev++;
@@ -1088,10 +1122,10 @@ float *make_orco_surf(Object *ob)
}
}
else {
- float *_tdata= MEM_callocN((nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv) *3*sizeof(float), "temp data");
+ float *_tdata= MEM_callocN((nu->pntsu*resolu) * (nu->pntsv*resolv) *3*sizeof(float), "temp data");
float *tdata= _tdata;
- makeNurbfaces(nu, tdata, 0);
+ makeNurbfaces(nu, tdata, 0, resolu, resolv);
for(b=0; b<sizeu; b++) {
int use_b= b;
@@ -1103,7 +1137,7 @@ float *make_orco_surf(Object *ob)
if (a==sizev-1 && (nu->flagv & CU_NURB_CYCLIC))
use_a= 0;
- tdata = _tdata + 3 * (use_b * (nu->pntsv*nu->resolv) + use_a);
+ tdata = _tdata + 3 * (use_b * (nu->pntsv*resolv) + use_a);
fp[0]= (tdata[0]-cu->loc[0])/cu->size[0];
fp[1]= (tdata[1]-cu->loc[1])/cu->size[1];
@@ -1181,8 +1215,8 @@ float *make_orco_curve(Scene *scene, Object *ob)
for (u=0; u<sizev; u++) {
for (v=0; v<sizeu; v++,fp+=3) {
if (cu->flag & CU_UV_ORCO) {
- fp[0]= 2.0f*u/(dl->parts-1) - 1.0f;
- fp[1]= 2.0f*v/(dl->nr-1) - 1.0f;
+ fp[0]= 2.0f*u/(sizev - 1) - 1.0f;
+ fp[1]= 2.0f*v/(sizeu - 1) - 1.0f;
fp[2]= 0.0;
} else {
float *vert;
@@ -1235,10 +1269,10 @@ void makebevelcurve(Scene *scene, Object *ob, ListBase *disp, int forRender)
makeDispListCurveTypes_forRender(scene, cu->bevobj, &bevdisp, NULL, 0);
dl= bevdisp.first;
} else {
- dl= bevcu->disp.first;
- if(dl==0) {
+ dl= cu->bevobj->disp.first;
+ if(dl==NULL) {
makeDispListCurveTypes(scene, cu->bevobj, 0);
- dl= bevcu->disp.first;
+ dl= cu->bevobj->disp.first;
}
}
@@ -1713,7 +1747,7 @@ static void bevel_list_smooth(BevList *bl, int smooth_iter)
if(bl->poly== -1) { /* check its not cyclic */
/* skip the first point */
- bevp0= bevp1;
+ /* bevp0= bevp1; */
bevp1= bevp2;
bevp2++;
nr--;
@@ -1744,7 +1778,7 @@ static void bevel_list_smooth(BevList *bl, int smooth_iter)
normalize_qt(bevp1->quat);
- bevp0= bevp1;
+ /* bevp0= bevp1; */ /* UNUSED */
bevp1= bevp2;
bevp2++;
}
@@ -1778,8 +1812,6 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl)
int nr;
float q[4];
- float cross_tmp[3];
-
bevel_list_calc_bisect(bl);
bevp2= (BevPoint *)(bl+1);
@@ -1796,6 +1828,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl)
float angle= angle_normalized_v3v3(bevp0->dir, bevp1->dir);
if(angle > 0.0f) { /* otherwise we can keep as is */
+ float cross_tmp[3];
cross_v3_v3v3(cross_tmp, bevp0->dir, bevp1->dir);
axis_angle_to_quat(q, cross_tmp, angle);
mul_qt_qtqt(bevp1->quat, q, bevp0->quat);
@@ -1923,7 +1956,7 @@ static void make_bevel_list_3D_tangent(BevList *bl)
normalize_v3(cross_tmp);
tri_to_quat( bevp1->quat,zero, cross_tmp, bevp1->tan); /* XXX - could be faster */
- bevp0= bevp1;
+ /* bevp0= bevp1; */ /* UNUSED */
bevp1= bevp2;
bevp2++;
}
@@ -2393,7 +2426,7 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
p2= bezt->vec[1];
- if(prev==0) {
+ if(prev==NULL) {
p3= next->vec[1];
pt[0]= 2*p2[0]- p3[0];
pt[1]= 2*p2[1]- p3[1];
@@ -2402,7 +2435,7 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
}
else p1= prev->vec[1];
- if(next==0) {
+ if(next==NULL) {
pt[0]= 2*p2[0]- p1[0];
pt[1]= 2*p2[1]- p1[1];
pt[2]= 2*p2[2]- p1[2];
@@ -2583,7 +2616,7 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */
a= nu->pntsu;
bezt= nu->bezt;
if(nu->flagu & CU_NURB_CYCLIC) prev= bezt+(a-1);
- else prev= 0;
+ else prev= NULL;
next= bezt+1;
while(a--) {
@@ -2591,7 +2624,7 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */
prev= bezt;
if(a==1) {
if(nu->flagu & CU_NURB_CYCLIC) next= nu->bezt;
- else next= 0;
+ else next= NULL;
}
else next++;
@@ -2650,7 +2683,7 @@ void autocalchandlesNurb(Nurb *nu, int flag)
BezTriple *bezt2, *bezt1, *bezt0;
int i, align, leftsmall, rightsmall;
- if(nu==0 || nu->bezt==0) return;
+ if(nu==NULL || nu->bezt==NULL) return;
bezt2 = nu->bezt;
bezt1 = bezt2 + (nu->pntsu-1);
@@ -2875,38 +2908,41 @@ void switchdirectionNurb(Nurb *nu)
bp2--;
}
if(nu->type == CU_NURBS) {
- /* inverse knots */
- a= KNOTSU(nu);
- fp1= nu->knotsu;
- fp2= fp1+(a-1);
- a/= 2;
- while(fp1!=fp2 && a>0) {
- SWAP(float, *fp1, *fp2);
- a--;
- fp1++;
- fp2--;
- }
- /* and make in increasing order again */
- a= KNOTSU(nu);
- fp1= nu->knotsu;
- fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
- while(a--) {
- fp2[0]= fabs(fp1[1]-fp1[0]);
- fp1++;
- fp2++;
- }
-
- a= KNOTSU(nu)-1;
- fp1= nu->knotsu;
- fp2= tempf;
- fp1[0]= 0.0;
- fp1++;
- while(a--) {
- fp1[0]= fp1[-1]+fp2[0];
+ /* no knots for too short paths */
+ if(nu->knotsu) {
+ /* inverse knots */
+ a= KNOTSU(nu);
+ fp1= nu->knotsu;
+ fp2= fp1+(a-1);
+ a/= 2;
+ while(fp1!=fp2 && a>0) {
+ SWAP(float, *fp1, *fp2);
+ a--;
+ fp1++;
+ fp2--;
+ }
+ /* and make in increasing order again */
+ a= KNOTSU(nu);
+ fp1= nu->knotsu;
+ fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
+ while(a--) {
+ fp2[0]= fabs(fp1[1]-fp1[0]);
+ fp1++;
+ fp2++;
+ }
+
+ a= KNOTSU(nu)-1;
+ fp1= nu->knotsu;
+ fp2= tempf;
+ fp1[0]= 0.0;
fp1++;
- fp2++;
+ while(a--) {
+ fp1[0]= fp1[-1]+fp2[0];
+ fp1++;
+ fp2++;
+ }
+ MEM_freeN(tempf);
}
- MEM_freeN(tempf);
}
}
else {
@@ -2929,7 +2965,7 @@ void switchdirectionNurb(Nurb *nu)
}
-float (*curve_getVertexCos(Curve *cu, ListBase *lb, int *numVerts_r))[3]
+float (*curve_getVertexCos(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r))[3]
{
int i, numVerts = *numVerts_r = count_curveverts(lb);
float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos");
@@ -2957,7 +2993,7 @@ float (*curve_getVertexCos(Curve *cu, ListBase *lb, int *numVerts_r))[3]
return cos;
}
-void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
+void curve_applyVertexCos(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos)[3])
{
float *co = vertexCos[0];
Nurb *nu;
@@ -2982,7 +3018,7 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
}
}
-float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3]
+float (*curve_getKeyVertexCos(Curve *UNUSED(cu), ListBase *lb, float *key))[3]
{
int i, numVerts = count_curveverts(lb);
float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos");
@@ -3013,7 +3049,7 @@ float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3]
return cos;
}
-void curve_applyKeyVertexTilts(Curve *cu, ListBase *lb, float *key)
+void curve_applyKeyVertexTilts(Curve *UNUSED(cu), ListBase *lb, float *key)
{
Nurb *nu;
int i;
@@ -3025,7 +3061,7 @@ void curve_applyKeyVertexTilts(Curve *cu, ListBase *lb, float *key)
for(i=0; i<nu->pntsu; i++,bezt++) {
key+=3*3;
bezt->alfa= *key;
- key++;
+ key+=3;
}
}
else {
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index b067001cb98..0612a57d85d 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -34,7 +34,8 @@
#include <math.h>
#include <string.h>
-#include "BLI_cellalloc.h"
+
+#include <assert.h>
#include "MEM_guardedalloc.h"
@@ -42,13 +43,19 @@
#include "DNA_ID.h"
#include "BLI_blenlib.h"
+#include "BLI_path_util.h"
#include "BLI_linklist.h"
+#include "BLI_math.h"
#include "BLI_mempool.h"
+#include "BLI_cellalloc.h"
+#include "BLI_utildefines.h"
#include "BKE_customdata.h"
#include "BKE_customdata_file.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_utildefines.h"
+#include "BKE_multires.h"
#include "bmesh.h"
@@ -61,9 +68,9 @@
/********************* Layer type information **********************/
typedef struct LayerTypeInfo {
int size; /* the memory size of one element of this layer's data */
- char *structname; /* name of the struct used, for file writing */
+ const char *structname; /* name of the struct used, for file writing */
int structnum; /* number of structs per element, for file writing */
- char *defaultname; /* default layer name */
+ const char *defaultname; /* default layer name */
/* a function to copy count elements of this layer's data
* (deep copy if appropriate)
@@ -113,6 +120,11 @@ typedef struct LayerTypeInfo {
/* a function to determine file size */
size_t (*filesize)(CDataFile *cdf, void *data, int count);
+
+ /* a function to validate layer contents depending on
+ * sub-elements count
+ */
+ void (*validate)(void *source, int sub_elements);
} LayerTypeInfo;
static void layerCopy_mdeformvert(const void *source, void *dest,
@@ -158,7 +170,7 @@ static void linklist_free_simple(void *link)
}
static void layerInterp_mdeformvert(void **sources, float *weights,
- float *sub_weights, int count, void *dest)
+ float *UNUSED(sub_weights), int count, void *dest)
{
MDeformVert *dvert = dest;
LinkNode *dest_dw = NULL; /* a list of lists of MDeformWeight pointers */
@@ -216,7 +228,7 @@ static void layerInterp_mdeformvert(void **sources, float *weights,
static void layerInterp_msticky(void **sources, float *weights,
- float *sub_weights, int count, void *dest)
+ float *UNUSED(sub_weights), int count, void *dest)
{
float co[2], w;
MSticky *mst;
@@ -406,130 +418,149 @@ static void layerDefault_origspace_face(void *data, int count)
osf[i] = default_osf;
}
-#if 0
-/* Adapted from sculptmode.c */
-static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v)
-{
- int x, y, x2, y2;
- const int st_max = st - 1;
- float urat, vrat, uopp;
- float d[4][3], d2[2][3];
-
- if(u < 0)
- u = 0;
- else if(u >= st)
- u = st_max;
- if(v < 0)
- v = 0;
- else if(v >= st)
- v = st_max;
-
- x = floor(u);
- y = floor(v);
- x2 = x + 1;
- y2 = y + 1;
-
- if(x2 >= st) x2 = st_max;
- if(y2 >= st) y2 = st_max;
-
- urat = u - x;
- vrat = v - y;
- uopp = 1 - urat;
-
- copy_v3_v3(d[0], disps[y * st + x]);
- copy_v3_v3(d[1], disps[y * st + x2]);
- copy_v3_v3(d[2], disps[y2 * st + x]);
- copy_v3_v3(d[3], disps[y2 * st + x2]);
- mul_v3_fl(d[0], uopp);
- mul_v3_fl(d[1], urat);
- mul_v3_fl(d[2], uopp);
- mul_v3_fl(d[3], urat);
-
- add_v3_v3v3(d2[0], d[0], d[1]);
- add_v3_v3v3(d2[1], d[2], d[3]);
- mul_v3_fl(d2[0], 1 - vrat);
- mul_v3_fl(d2[1], vrat);
-
- add_v3_v3v3(out, d2[0], d2[1]);
-}
-#endif
-
-static int mdisp_corners(MDisps *s)
-{
- /* silly trick because we don't get it from callback */
- return (s->totdisp % (3*3) == 0)? 3: 4;
-}
-
static void layerSwap_mdisps(void *data, const int *ci)
{
MDisps *s = data;
float (*d)[3] = NULL;
int corners, cornersize, S;
- /* this function is untested .. */
- corners = mdisp_corners(s);
- cornersize = s->totdisp/corners;
+ if(s->disps) {
+ int nverts= (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */
+ corners= multires_mdisp_corners(s);
+ cornersize= s->totdisp/corners;
- d = MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap");
+ if(corners!=nverts) {
+ /* happens when face changed vertex count in edit mode
+ if it happened, just forgot displacement */
- for(S = 0; S < corners; S++)
- memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float));
-
- if(s->disps)
+ MEM_freeN(s->disps);
+ s->totdisp= (s->totdisp/corners)*nverts;
+ s->disps= MEM_callocN(s->totdisp*sizeof(float)*3, "mdisp swap");
+ return;
+ }
+
+ d= MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap");
+
+ for(S = 0; S < corners; S++)
+ memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float));
+
MEM_freeN(s->disps);
- s->disps = d;
+ s->disps= d;
+ }
}
-static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights,
- int count, void *dest)
+static void layerInterp_mdisps(void **sources, float *UNUSED(weights),
+ float *sub_weights, int count, void *dest)
{
- // XXX
-#if 0
MDisps *d = dest;
MDisps *s = NULL;
int st, stl;
int i, x, y;
- float crn[4][2];
- float (*sw)[4] = NULL;
+ int side, S, dst_corners, src_corners;
+ float crn_weight[4][2];
+ float (*sw)[4] = (void*)sub_weights;
+ float (*disps)[3], (*out)[3];
- /* Initialize the destination */
- for(i = 0; i < d->totdisp; ++i) {
- float z[3] = {0,0,0};
- copy_v3_v3(d->disps[i], z);
+ /* happens when flipping normals of newly created mesh */
+ if(!d->totdisp)
+ return;
+
+ s = sources[0];
+ dst_corners = multires_mdisp_corners(d);
+ src_corners = multires_mdisp_corners(s);
+
+ if(sub_weights && count == 2 && src_corners == 3) {
+ src_corners = multires_mdisp_corners(sources[1]);
+
+ /* special case -- converting two triangles to quad */
+ if(src_corners == 3 && dst_corners == 4) {
+ MDisps tris[2];
+ int vindex[4] = {0};
+
+ S = 0;
+ for(i = 0; i < 2; i++)
+ for(y = 0; y < 4; y++)
+ for(x = 0; x < 4; x++)
+ if(sw[x+i*4][y])
+ vindex[x] = y;
+
+ for(i = 0; i < 2; i++) {
+ float sw_m4[4][4] = {{0}};
+ int a = 7 & ~(1 << vindex[i*2] | 1 << vindex[i*2+1]);
+
+ sw_m4[0][vindex[i*2+1]] = 1;
+ sw_m4[1][vindex[i*2]] = 1;
+
+ for(x = 0; x < 3; x++)
+ if(a & (1 << x))
+ sw_m4[2][x] = 1;
+
+ tris[i] = *((MDisps*)sources[i]);
+ tris[i].disps = MEM_dupallocN(tris[i].disps);
+ layerInterp_mdisps(&sources[i], NULL, (float*)sw_m4, 1, &tris[i]);
+ }
+
+ mdisp_join_tris(d, &tris[0], &tris[1]);
+
+ for(i = 0; i < 2; i++)
+ MEM_freeN(tris[i].disps);
+
+ return;
+ }
}
/* For now, some restrictions on the input */
- if(count != 1 || !sub_weights) return;
+ if(count != 1 || !sub_weights) {
+ for(i = 0; i < d->totdisp; ++i)
+ zero_v3(d->disps[i]);
- st = sqrt(d->totdisp);
+ return;
+ }
+
+ /* Initialize the destination */
+ out = disps = MEM_callocN(3*d->totdisp*sizeof(float), "iterp disps");
+
+ side = sqrt(d->totdisp / dst_corners);
+ st = (side<<1)-1;
stl = st - 1;
- sw = (void*)sub_weights;
+ sw= (void*)sub_weights;
for(i = 0; i < 4; ++i) {
- crn[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3];
- crn[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3];
+ crn_weight[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3];
+ crn_weight[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3];
}
- s = sources[0];
- for(y = 0; y < st; ++y) {
- for(x = 0; x < st; ++x) {
- /* One suspects this code could be cleaner. */
- float xl = (float)x / (st - 1);
- float yl = (float)y / (st - 1);
- float mid1[2] = {crn[0][0] * (1 - xl) + crn[1][0] * xl,
- crn[0][1] * (1 - xl) + crn[1][1] * xl};
- float mid2[2] = {crn[3][0] * (1 - xl) + crn[2][0] * xl,
- crn[3][1] * (1 - xl) + crn[2][1] * xl};
- float mid3[2] = {mid1[0] * (1 - yl) + mid2[0] * yl,
- mid1[1] * (1 - yl) + mid2[1] * yl};
-
- float srcdisp[3];
-
- mdisps_bilinear(srcdisp, s->disps, st, mid3[0], mid3[1]);
- copy_v3_v3(d->disps[y * st + x], srcdisp);
+ multires_mdisp_smooth_bounds(s);
+
+ out = disps;
+ for(S = 0; S < dst_corners; S++) {
+ float base[2], axis_x[2], axis_y[2];
+
+ mdisp_apply_weight(S, dst_corners, 0, 0, st, crn_weight, &base[0], &base[1]);
+ mdisp_apply_weight(S, dst_corners, side-1, 0, st, crn_weight, &axis_x[0], &axis_x[1]);
+ mdisp_apply_weight(S, dst_corners, 0, side-1, st, crn_weight, &axis_y[0], &axis_y[1]);
+
+ sub_v2_v2(axis_x, base);
+ sub_v2_v2(axis_y, base);
+ normalize_v2(axis_x);
+ normalize_v2(axis_y);
+
+ for(y = 0; y < side; ++y) {
+ for(x = 0; x < side; ++x, ++out) {
+ int crn;
+ float face_u, face_v, crn_u, crn_v;
+
+ mdisp_apply_weight(S, dst_corners, x, y, st, crn_weight, &face_u, &face_v);
+ crn = mdisp_rot_face_to_crn(src_corners, st, face_u, face_v, &crn_u, &crn_v);
+
+ old_mdisps_bilinear((*out), &s->disps[crn*side*side], side, crn_u, crn_v);
+ mdisp_flip_disp(crn, dst_corners, axis_x, axis_y, *out);
+ }
}
}
-#endif
+
+ MEM_freeN(d->disps);
+ d->disps = disps;
}
static void layerCopy_mdisps(const void *source, void *dest, int count)
@@ -551,7 +582,21 @@ static void layerCopy_mdisps(const void *source, void *dest, int count)
}
}
-static void layerFree_mdisps(void *data, int count, int size)
+static void layerValidate_mdisps(void *data, int sub_elements)
+{
+ MDisps *disps = data;
+ if(disps->disps) {
+ int corners = multires_mdisp_corners(disps);
+
+ if(corners != sub_elements) {
+ MEM_freeN(disps->disps);
+ disps->totdisp = disps->totdisp / corners * sub_elements;
+ disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float), "layerValidate_mdisps");
+ }
+ }
+}
+
+static void layerFree_mdisps(void *data, int count, int UNUSED(size))
{
int i;
MDisps *d = data;
@@ -597,7 +642,7 @@ static int layerWrite_mdisps(CDataFile *cdf, void *data, int count)
return 1;
}
-static size_t layerFilesize_mdisps(CDataFile *cdf, void *data, int count)
+static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count)
{
MDisps *d = data;
size_t size = 0;
@@ -936,7 +981,7 @@ static void layerInterp_shapekey(void **sources, float *weights,
}
}
-const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
+static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL,
NULL},
@@ -966,11 +1011,11 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL,
layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
- {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
- layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps},
+ layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps, layerValidate_mdisps},
{sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
{sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL},
@@ -989,7 +1034,7 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
};
-const char *LAYERTYPENAMES[CD_NUMTYPES] = {
+static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
"CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
"CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV",
@@ -1064,13 +1109,13 @@ void customData_update_typemap(CustomData *data)
void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem)
{
- const LayerTypeInfo *typeInfo;
+ /*const LayerTypeInfo *typeInfo;*/
CustomDataLayer *layer, *newlayer;
int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0;
for(i = 0; i < source->totlayer; ++i) {
layer = &source->layers[i];
- typeInfo = layerType_getInfo(layer->type);
+ /*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/
type = layer->type;
@@ -1195,7 +1240,7 @@ int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n)
return -1;
}
-int CustomData_get_named_layer_index(const CustomData *data, int type, char *name)
+int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name)
{
int i;
@@ -1444,7 +1489,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
data->layers[index].data = newlayerdata;
if(name || (name=typeInfo->defaultname)) {
- strcpy(data->layers[index].name, name);
+ BLI_strncpy(data->layers[index].name, name, 32);
CustomData_set_layer_unique_name(data, index);
}
else
@@ -1586,7 +1631,7 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type)
}
void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
- int type, char *name)
+ int type, const char *name)
{
CustomDataLayer *layer;
int layer_index;
@@ -1841,7 +1886,7 @@ void *CustomData_get_layer_n(const CustomData *data, int type, int n)
}
void *CustomData_get_layer_named(const struct CustomData *data, int type,
- char *name)
+ const char *name)
{
int layer_index = CustomData_get_named_layer_index(data, type, name);
if(layer_index < 0) return NULL;
@@ -1967,6 +2012,18 @@ void CustomData_em_copy_data(const CustomData *source, CustomData *dest,
}
}
+void CustomData_em_validate_data(CustomData *data, void *block, int sub_elements)
+{
+ int i;
+ for(i = 0; i < data->totlayer; i++) {
+ const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
+ char *leayer_data = (char*)block + data->layers[i].offset;
+
+ if(typeInfo->validate)
+ typeInfo->validate(leayer_data, sub_elements);
+ }
+}
+
void *CustomData_em_get(const CustomData *data, void *block, int type)
{
int layer_index;
@@ -2593,7 +2650,7 @@ void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest,
}
-void CustomData_file_write_info(int type, char **structname, int *structnum)
+void CustomData_file_write_info(int type, const char **structname, int *structnum)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -2620,69 +2677,50 @@ static int CustomData_is_property_layer(int type)
return 0;
}
-void CustomData_set_layer_unique_name(CustomData *data, int index)
+static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int index)
{
- char tempname[64];
- int number, i, type;
- char *dot, *name;
- CustomDataLayer *layer, *nlayer= &data->layers[index];
- const LayerTypeInfo *typeInfo= layerType_getInfo(nlayer->type);
-
- if (!typeInfo->defaultname)
- return;
-
- type = nlayer->type;
- name = nlayer->name;
-
- if (name[0] == '\0')
- BLI_strncpy(nlayer->name, typeInfo->defaultname, sizeof(nlayer->name));
-
+ int i;
/* see if there is a duplicate */
for(i=0; i<data->totlayer; i++) {
- layer = &data->layers[i];
-
- if(CustomData_is_property_layer(type)){
- if(i!=index && CustomData_is_property_layer(layer->type) &&
- strcmp(layer->name, name)==0)
- break;
-
- }
- else{
- if(i!=index && layer->type==type && strcmp(layer->name, name)==0)
- break;
- }
- }
-
- if(i == data->totlayer)
- return;
-
- /* strip off the suffix */
- dot = strchr(nlayer->name, '.');
- if(dot) *dot=0;
-
- for(number=1; number <=999; number++) {
- sprintf(tempname, "%s.%03d", nlayer->name, number);
-
- for(i=0; i<data->totlayer; i++) {
- layer = &data->layers[i];
+ if(i != index) {
+ CustomDataLayer *layer= &data->layers[i];
- if(CustomData_is_property_layer(type)){
- if(i!=index && CustomData_is_property_layer(layer->type) &&
- strcmp(layer->name, tempname)==0)
-
- break;
+ if(CustomData_is_property_layer(type)) {
+ if(CustomData_is_property_layer(layer->type) && strcmp(layer->name, name)==0) {
+ return 1;
+ }
}
else{
- if(i!=index && layer->type==type && strcmp(layer->name, tempname)==0)
- break;
+ if(i!=index && layer->type==type && strcmp(layer->name, name)==0) {
+ return 1;
+ }
}
}
+ }
+
+ return 0;
+}
- if(i == data->totlayer) {
- BLI_strncpy(nlayer->name, tempname, sizeof(nlayer->name));
- return;
- }
- }
+static int customdata_unique_check(void *arg, const char *name)
+{
+ struct {CustomData *data; int type; int index;} *data_arg= arg;
+ return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
+}
+
+void CustomData_set_layer_unique_name(CustomData *data, int index)
+{
+ CustomDataLayer *nlayer= &data->layers[index];
+ const LayerTypeInfo *typeInfo= layerType_getInfo(nlayer->type);
+
+ struct {CustomData *data; int type; int index;} data_arg;
+ data_arg.data= data;
+ data_arg.type= nlayer->type;
+ data_arg.index= index;
+
+ if (!typeInfo->defaultname)
+ return;
+
+ BLI_uniquename_cb(customdata_unique_check, &data_arg, typeInfo->defaultname, '.', nlayer->name, sizeof(nlayer->name));
}
int CustomData_verify_versions(struct CustomData *data, int index)
@@ -2715,13 +2753,13 @@ int CustomData_verify_versions(struct CustomData *data, int index)
static void customdata_external_filename(char filename[FILE_MAX], ID *id, CustomDataExternal *external)
{
- char *path = (id->lib)? id->lib->filepath: G.sce;
+ char *path = (id->lib)? id->lib->filepath: G.main->name;
BLI_strncpy(filename, external->filename, FILE_MAX);
BLI_path_abs(filename, path);
}
-void CustomData_external_reload(CustomData *data, ID *id, CustomDataMask mask, int totelem)
+void CustomData_external_reload(CustomData *data, ID *UNUSED(id), CustomDataMask mask, int totelem)
{
CustomDataLayer *layer;
const LayerTypeInfo *typeInfo;
@@ -2891,7 +2929,7 @@ void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, in
cdf_free(cdf);
}
-void CustomData_external_add(CustomData *data, ID *id, int type, int totelem, const char *filename)
+void CustomData_external_add(CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filename)
{
CustomDataExternal *external= data->external;
CustomDataLayer *layer;
diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c
index 65a0d731beb..6fb79a0df28 100644
--- a/source/blender/blenkernel/intern/customdata_file.c
+++ b/source/blender/blenkernel/intern/customdata_file.c
@@ -28,10 +28,11 @@
#include "BLI_fileops.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_customdata_file.h"
#include "BKE_global.h"
-#include "BKE_utildefines.h"
+
/************************* File Format Definitions ***************************/
@@ -379,7 +380,7 @@ int cdf_write_open(CDataFile *cdf, char *filename)
return 1;
}
-int cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay)
+int cdf_write_layer(CDataFile *UNUSED(cdf), CDataFileLayer *UNUSED(blay))
{
return 1;
}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index be28553f347..616bcb17f90 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -51,7 +51,7 @@ void defgroup_copy_list (ListBase *outbase, ListBase *inbase)
{
bDeformGroup *defgroup, *defgroupn;
- outbase->first= outbase->last= 0;
+ outbase->first= outbase->last= NULL;
for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){
defgroupn= defgroup_duplicate(defgroup);
@@ -305,89 +305,65 @@ int defgroup_flip_index(Object *ob, int index, int use_default)
return (flip_index==-1 && use_default) ? index : flip_index;
}
-void defgroup_unique_name (bDeformGroup *dg, Object *ob)
+static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
{
bDeformGroup *curdef;
- int number;
- int exists = 0;
- char tempname[64];
- char *dot;
- if (!ob)
- return;
-
- /* See if we are given an empty string */
- if (dg->name[0] == '\0') {
- /* give it default name first */
- strcpy (dg->name, "Group");
- }
-
- /* See if we even need to do this */
for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
if (dg!=curdef) {
- if (!strcmp(curdef->name, dg->name)) {
- exists = 1;
- break;
+ if (!strcmp(curdef->name, name)) {
+ return 1;
}
}
}
-
- if (!exists)
- return;
- /* Strip off the suffix */
- dot=strchr(dg->name, '.');
- if (dot)
- *dot=0;
-
- for (number = 1; number <=999; number++) {
- sprintf (tempname, "%s.%03d", dg->name, number);
-
- exists = 0;
- for (curdef=ob->defbase.first; curdef; curdef=curdef->next) {
- if (dg!=curdef) {
- if (!strcmp (curdef->name, tempname)) {
- exists = 1;
- break;
- }
- }
- }
- if (!exists) {
- BLI_strncpy (dg->name, tempname, 32);
- return;
- }
- }
+ return 0;
}
+static int defgroup_unique_check(void *arg, const char *name)
+{
+ struct {Object *ob; void *dg;} *data= arg;
+ return defgroup_find_name_dupe(name, data->dg, data->ob);
+}
+
+void defgroup_unique_name (bDeformGroup *dg, Object *ob)
+{
+ struct {Object *ob; void *dg;} data;
+ data.ob= ob;
+ data.dg= dg;
+
+ BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name));
+}
/* finds the best possible flipped name. For renaming; check for unique names afterwards */
-/* if strip_number: removes number extensions */
-void flip_side_name (char *name, const char *from_name, int strip_number)
+/* if strip_number: removes number extensions
+ * note: dont use sizeof() for 'name' or 'from_name' */
+void flip_side_name (char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
{
int len;
- char prefix[sizeof(((bDeformGroup *)NULL)->name)]= {""}; /* The part before the facing */
- char suffix[sizeof(((bDeformGroup *)NULL)->name)]= {""}; /* The part after the facing */
- char replace[sizeof(((bDeformGroup *)NULL)->name)]= {""}; /* The replacement string */
- char number[sizeof(((bDeformGroup *)NULL)->name)]= {""}; /* The number extension string */
+ char prefix[MAX_VGROUP_NAME]= ""; /* The part before the facing */
+ char suffix[MAX_VGROUP_NAME]= ""; /* The part after the facing */
+ char replace[MAX_VGROUP_NAME]= ""; /* The replacement string */
+ char number[MAX_VGROUP_NAME]= ""; /* The number extension string */
char *index=NULL;
- len= strlen(from_name);
+ len= BLI_strnlen(from_name, MAX_VGROUP_NAME);
if(len<3) return; // we don't do names like .R or .L
- strcpy(name, from_name);
+ BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
/* We first check the case with a .### extension, let's find the last period */
if(isdigit(name[len-1])) {
index= strrchr(name, '.'); // last occurrence
if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
if(strip_number==0)
- strcpy(number, index);
+ BLI_strncpy(number, index, sizeof(number));
*index= 0;
- len= strlen(name);
+ len= BLI_strnlen(name, MAX_VGROUP_NAME);
}
}
- strcpy (prefix, name);
+ BLI_strncpy(prefix, name, sizeof(prefix));
#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
@@ -471,10 +447,10 @@ void flip_side_name (char *name, const char *from_name, int strip_number)
#undef IS_SEPARATOR
- sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
+ BLI_snprintf (name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
}
-float defvert_find_weight(const struct MDeformVert *dvert, int group_num)
+float defvert_find_weight(const struct MDeformVert *dvert, const int group_num)
{
MDeformWeight *dw= defvert_find_index(dvert, group_num);
return dw ? dw->weight : 0.0f;
@@ -489,7 +465,7 @@ float defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index,
}
-MDeformWeight *defvert_find_index(const MDeformVert *dvert, int defgroup)
+MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
{
if(dvert && defgroup >= 0) {
MDeformWeight *dw = dvert->dw;
@@ -505,7 +481,7 @@ MDeformWeight *defvert_find_index(const MDeformVert *dvert, int defgroup)
/* Ensures that mv has a deform weight entry for the specified defweight group */
/* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
-MDeformWeight *defvert_verify_index(MDeformVert *dv, int defgroup)
+MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup)
{
MDeformWeight *newdw;
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 382c0690ae3..c437c4fe61f 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -29,22 +29,24 @@
#include <string.h>
#include <math.h>
+#include "MEM_guardedalloc.h"
+
#include "BLI_winstuff.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "DNA_anim_types.h"
#include "DNA_camera_types.h"
#include "DNA_group_types.h"
#include "DNA_lattice_types.h"
#include "DNA_key_types.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
-#include "MEM_guardedalloc.h"
-
-#include "BLI_ghash.h"
-
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_effect.h"
@@ -52,7 +54,9 @@
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_key.h"
+#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_node.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -60,6 +64,7 @@
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_utildefines.h"
#include "depsgraph_private.h"
@@ -273,7 +278,7 @@ int queue_count(struct DagNodeQueue *queue){
}
-DagForest * dag_init()
+DagForest *dag_init(void)
{
DagForest *forest;
/* use callocN to init all zero */
@@ -846,7 +851,7 @@ DagNode * dag_get_sub_node (DagForest *forest,void * fob)
return node;
}
-static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name)
+static void dag_add_parent_relation(DagForest *UNUSED(forest), DagNode *fob1, DagNode *fob2, short rel, const char *name)
{
DagAdjList *itA = fob2->parent;
@@ -868,7 +873,7 @@ static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *f
fob2->parent = itA;
}
-void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name)
+void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name)
{
DagAdjList *itA = fob1->child;
@@ -893,7 +898,7 @@ void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel
fob1->child = itA;
}
-static char *dag_node_name(DagNode *node)
+static const char *dag_node_name(DagNode *node)
{
if(node->ob == NULL)
return "null";
@@ -938,7 +943,7 @@ static int dag_node_print_dependency_recurs(DagNode *node, DagNode *endnode)
return 0;
}
-static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, char *name)
+static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, const char *name)
{
DagNode *node;
@@ -1075,7 +1080,7 @@ void graph_bfs(void)
minheight = pos[node->BFS_dist];
itA = node->child;
while(itA != NULL) {
- if((itA->node->color == DAG_WHITE) ) {
+ if(itA->node->color == DAG_WHITE) {
itA->node->color = DAG_GRAY;
itA->node->BFS_dist = node->BFS_dist + 1;
itA->node->k = (float) minheight;
@@ -1222,7 +1227,7 @@ DagNodeQueue * graph_dfs(void)
itA = node->child;
while(itA != NULL) {
- if((itA->node->color == DAG_WHITE) ) {
+ if(itA->node->color == DAG_WHITE) {
itA->node->DFS_dvtm = time;
itA->node->color = DAG_GRAY;
@@ -1476,7 +1481,7 @@ struct DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob)
itA = node->child;
while(itA != NULL) {
- if((itA->node->color == DAG_WHITE) ) {
+ if(itA->node->color == DAG_WHITE) {
itA->node->DFS_dvtm = time;
itA->node->color = DAG_GRAY;
@@ -1510,7 +1515,7 @@ short are_obs_related(struct DagForest *dag, void *ob1, void *ob2) {
itA = node->child;
while(itA != NULL) {
- if((itA->node->ob == ob2) ) {
+ if(itA->node->ob == ob2) {
return itA->node->type;
}
itA = itA->next;
@@ -1682,7 +1687,7 @@ void DAG_scene_sort(Main *bmain, Scene *sce)
itA = node->child;
while(itA != NULL) {
- if((itA->node->color == DAG_WHITE) ) {
+ if(itA->node->color == DAG_WHITE) {
itA->node->DFS_dvtm = time;
itA->node->color = DAG_GRAY;
@@ -1858,7 +1863,7 @@ static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int
for(itA = node->child; itA; itA= itA->next) {
if(itA->node->type==ID_OB) {
if(itA->node->lasttime!=curtime) {
- ob= (Object*)(node->ob);
+ ob= (Object*)(itA->node->ob);
if(reset || (ob->recalc & OB_RECALC_ALL)) {
if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
@@ -1921,8 +1926,30 @@ static void dag_scene_flush_layers(Scene *sce, int lay)
flush_layer_node(sce, itA->node, lasttime);
}
+static void dag_tag_renderlayers(Scene *sce, unsigned int lay)
+{
+ if(sce->nodetree) {
+ bNode *node;
+ Base *base;
+ unsigned int lay_changed= 0;
+
+ for(base= sce->base.first; base; base= base->next)
+ if(base->lay & lay)
+ if(base->object->recalc)
+ lay_changed |= base->lay;
+
+ for(node= sce->nodetree->nodes.first; node; node= node->next) {
+ if(node->id==(ID *)sce) {
+ SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
+ if(srl && (srl->lay & lay_changed))
+ NodeTagChanged(sce->nodetree, node);
+ }
+ }
+ }
+}
+
/* flushes all recalc flags in objects down the dependency tree */
-void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, int time)
+void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const short time)
{
DagNode *firstnode;
DagAdjList *itA;
@@ -1965,6 +1992,8 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, int time)
}
}
}
+
+ dag_tag_renderlayers(sce, lay);
}
static int object_modifiers_use_time(Object *ob)
@@ -2131,50 +2160,57 @@ static void dag_object_time_update_flags(Object *ob)
}
}
/* flag all objects that need recalc, for changes in time for example */
-void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay)
+/* do_time: make this optional because undo resets objects to their animated locations without this */
+void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const short do_time)
{
Base *base;
Object *ob;
Group *group;
GroupObject *go;
- Scene *sce;
-
+ Scene *sce_iter;
+
/* set ob flags where animated systems are */
- for(SETLOOPER(scene, base)) {
+ for(SETLOOPER(scene, sce_iter, base)) {
ob= base->object;
-
- /* now if DagNode were part of base, the node->lay could be checked... */
- /* we do all now, since the scene_flush checks layers and clears recalc flags even */
- dag_object_time_update_flags(ob);
-
+
+ if(do_time) {
+ /* now if DagNode were part of base, the node->lay could be checked... */
+ /* we do all now, since the scene_flush checks layers and clears recalc flags even */
+ dag_object_time_update_flags(ob);
+ }
+
/* handled in next loop */
- if(ob->dup_group)
+ if(ob->dup_group)
ob->dup_group->id.flag |= LIB_DOIT;
- }
-
- /* we do groups each once */
- for(group= bmain->group.first; group; group= group->id.next) {
- if(group->id.flag & LIB_DOIT) {
- for(go= group->gobject.first; go; go= go->next) {
- dag_object_time_update_flags(go->ob);
+ }
+
+ if(do_time) {
+ /* we do groups each once */
+ for(group= bmain->group.first; group; group= group->id.next) {
+ if(group->id.flag & LIB_DOIT) {
+ for(go= group->gobject.first; go; go= go->next) {
+ dag_object_time_update_flags(go->ob);
+ }
}
}
}
+
+ for(sce_iter= scene; sce_iter; sce_iter= sce_iter->set)
+ DAG_scene_flush_update(bmain, sce_iter, lay, 1);
- for(sce= scene; sce; sce= sce->set)
- DAG_scene_flush_update(bmain, sce, lay, 1);
-
- /* test: set time flag, to disable baked systems to update */
- for(SETLOOPER(scene, base)) {
- ob= base->object;
- if(ob->recalc)
- ob->recalc |= OB_RECALC_TIME;
+ if(do_time) {
+ /* test: set time flag, to disable baked systems to update */
+ for(SETLOOPER(scene, sce_iter, base)) {
+ ob= base->object;
+ if(ob->recalc)
+ ob->recalc |= OB_RECALC_TIME;
+ }
+
+ /* hrmf... an exception to look at once, for invisible camera object we do it over */
+ if(scene->camera)
+ dag_object_time_update_flags(scene->camera);
}
-
- /* hrmf... an exception to look at once, for invisible camera object we do it over */
- if(scene->camera)
- dag_object_time_update_flags(scene->camera);
-
+
/* and store the info in groupobject */
for(group= bmain->group.first; group; group= group->id.next) {
if(group->id.flag & LIB_DOIT) {
@@ -2230,9 +2266,9 @@ void DAG_ids_flush_update(Main *bmain, int time)
DAG_scene_flush_update(bmain, sce, lay, time);
}
-void DAG_on_load_update(Main *bmain)
+void DAG_on_load_update(Main *bmain, const short do_time)
{
- Scene *scene, *sce;
+ Scene *scene;
Base *base;
Object *ob;
Group *group;
@@ -2243,19 +2279,20 @@ void DAG_on_load_update(Main *bmain)
dag_current_scene_layers(bmain, &scene, &lay);
if(scene && scene->theDag) {
+ Scene *sce_iter;
/* derivedmeshes and displists are not saved to file so need to be
remade, tag them so they get remade in the scene update loop,
note armature poses or object matrices are preserved and do not
require updates, so we skip those */
dag_scene_flush_layers(scene, lay);
- for(SETLOOPER(scene, base)) {
+ for(SETLOOPER(scene, sce_iter, base)) {
ob= base->object;
- node= (sce->theDag)? dag_get_node(sce->theDag, ob): NULL;
+ node= (sce_iter->theDag)? dag_get_node(sce_iter->theDag, ob): NULL;
oblay= (node)? node->lay: ob->lay;
if(oblay & lay) {
- if(ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL))
+ if(ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
ob->recalc |= OB_RECALC_DATA;
if(ob->dup_group)
ob->dup_group->id.flag |= LIB_DOIT;
@@ -2265,7 +2302,7 @@ void DAG_on_load_update(Main *bmain)
for(group= bmain->group.first; group; group= group->id.next) {
if(group->id.flag & LIB_DOIT) {
for(go= group->gobject.first; go; go= go->next) {
- if(ELEM5(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL))
+ if(ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
go->ob->recalc |= OB_RECALC_DATA;
if(go->ob->proxy_from)
go->ob->recalc |= OB_RECALC_OB;
@@ -2276,11 +2313,11 @@ void DAG_on_load_update(Main *bmain)
}
/* now tag update flags, to ensure deformers get calculated on redraw */
- DAG_scene_update_flags(bmain, scene, lay);
+ DAG_scene_update_flags(bmain, scene, lay, do_time);
}
}
-static void dag_id_flush_update__isDependentTexture(void *userData, Object *ob, ID **idpoin)
+static void dag_id_flush_update__isDependentTexture(void *userData, Object *UNUSED(ob), ID **idpoin)
{
struct { ID *id; int is_dependent; } *data = userData;
@@ -2290,26 +2327,21 @@ static void dag_id_flush_update__isDependentTexture(void *userData, Object *ob,
}
}
-void DAG_id_flush_update(ID *id, short flag)
+static void dag_id_flush_update(Scene *sce, ID *id)
{
Main *bmain= G.main;
- Scene *sce;
Object *obt, *ob= NULL;
short idtype;
- unsigned int lay;
- dag_current_scene_layers(bmain, &sce, &lay);
-
- if(!id || !sce || !sce->theDag)
- return;
+ /* here we flush a few things before actual scene wide flush, mostly
+ due to only objects and not other datablocks being in the depsgraph */
/* set flags & pointcache for object */
if(GS(id->name) == ID_OB) {
ob= (Object*)id;
- ob->recalc |= (flag & OB_RECALC_ALL);
BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
- if(flag & OB_RECALC_DATA) {
+ if(ob->recalc & OB_RECALC_DATA) {
/* all users of this ob->data should be checked */
id= ob->data;
@@ -2326,23 +2358,10 @@ void DAG_id_flush_update(ID *id, short flag)
idtype= GS(id->name);
if(ELEM7(idtype, ID_ME, ID_CU, ID_MB, ID_LA, ID_LT, ID_CA, ID_AR)) {
- int first_ob= 1;
for(obt=bmain->object.first; obt; obt= obt->id.next) {
if(!(ob && obt == ob) && obt->data == id) {
-
- /* try to avoid displist recalculation for linked curves */
- if (!first_ob && ELEM(obt->type, OB_CURVE, OB_SURF)) {
- /* if curve object has got derivedFinal it means this
- object has got constructive modifiers and object
- should be recalculated anyhow */
- if (!obt->derivedFinal)
- continue;
- }
-
obt->recalc |= OB_RECALC_DATA;
BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
-
- first_ob= 0;
}
}
}
@@ -2350,11 +2369,36 @@ void DAG_id_flush_update(ID *id, short flag)
/* set flags based on textures - can influence depgraph via modifiers */
if(idtype == ID_TE) {
for(obt=bmain->object.first; obt; obt= obt->id.next) {
- struct { ID *id; int is_dependent; } data = {id, 0};
-
+ struct { ID *id; int is_dependent; } data;
+ data.id= id;
+ data.is_dependent= 0;
+
modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data);
if (data.is_dependent)
obt->recalc |= OB_RECALC_DATA;
+
+ /* particle settings can use the texture as well */
+ if(obt->particlesystem.first) {
+ ParticleSystem *psys = obt->particlesystem.first;
+ MTex **mtexp, *mtex;
+ int a;
+ for(; psys; psys=psys->next) {
+ mtexp = psys->part->mtex;
+ for(a=0; a<MAX_MTEX; a++, mtexp++) {
+ mtex = *mtexp;
+ if(mtex && mtex->tex == (Tex*)id) {
+ obt->recalc |= OB_RECALC_DATA;
+
+ if(mtex->mapto & PAMAP_INIT)
+ psys->recalc |= PSYS_RECALC_RESET;
+ if(mtex->mapto & PAMAP_CHILD)
+ psys->recalc |= PSYS_RECALC_CHILD;
+
+ BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
+ }
+ }
+ }
+ }
}
}
@@ -2372,25 +2416,100 @@ void DAG_id_flush_update(ID *id, short flag)
/* set flags based on particle settings */
if(idtype == ID_PA) {
ParticleSystem *psys;
- for(obt=bmain->object.first; obt; obt= obt->id.next) {
- for(psys=obt->particlesystem.first; psys; psys=psys->next) {
- if(&psys->part->id == id) {
+ for(obt=bmain->object.first; obt; obt= obt->id.next)
+ for(psys=obt->particlesystem.first; psys; psys=psys->next)
+ if(&psys->part->id == id)
BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- obt->recalc |= (flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- }
- }
- }
}
/* update editors */
dag_editors_update(bmain, id);
}
+}
+
+void DAG_ids_flush_tagged(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ Scene *sce;
+ unsigned int lay;
+ int a, have_tag = 0;
+
+ dag_current_scene_layers(bmain, &sce, &lay);
+
+ if(!sce || !sce->theDag)
+ return;
+
+ /* loop over all ID types */
+ a = set_listbasepointers(bmain, lbarray);
+
+ while(a--) {
+ ListBase *lb = lbarray[a];
+ ID *id = lb->first;
+
+ /* we tag based on first ID type character to avoid
+ looping over all ID's in case there are no tags */
+ if(id && bmain->id_tag_update[id->name[0]]) {
+ for(; id; id=id->next) {
+ if(id->flag & LIB_ID_RECALC) {
+ dag_id_flush_update(sce, id);
+ id->flag &= ~LIB_ID_RECALC;
+ }
+ }
+
+ have_tag = 1;
+ }
+ }
+
+ if(have_tag) {
+ /* clear tags */
+ memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update));
+
+ /* flush changes to other objects */
+ DAG_scene_flush_update(bmain, sce, lay, 0);
+ }
+}
- /* flush to other objects that depend on this one */
- DAG_scene_flush_update(bmain, sce, lay, 0);
+void DAG_id_tag_update(ID *id, short flag)
+{
+ Main *bmain= G.main;
+
+ if(id==NULL) return;
+
+ /* tag ID for update */
+ id->flag |= LIB_ID_RECALC;
+ bmain->id_tag_update[id->name[0]] = 1;
+
+ /* flag is for objects and particle systems */
+ if(flag) {
+ Object *ob;
+ ParticleSystem *psys;
+ short idtype = GS(id->name);
+
+ if(idtype == ID_OB) {
+ /* only quick tag */
+ ob = (Object*)id;
+ ob->recalc |= (flag & OB_RECALC_ALL);
+ }
+ else if(idtype == ID_PA) {
+ /* this is weak still, should be done delayed as well */
+ for(ob=bmain->object.first; ob; ob=ob->id.next) {
+ for(psys=ob->particlesystem.first; psys; psys=psys->next) {
+ if(&psys->part->id == id) {
+ ob->recalc |= (flag & OB_RECALC_ALL);
+ psys->recalc |= (flag & PSYS_RECALC);
+ }
+ }
+ }
+ }
+ else {
+ /* disable because this is called on various ID types automatically.
+ * where printing warning is not useful. for now just ignore */
+ /* BLI_assert(!"invalid flag for this 'idtype'"); */
+ }
+ }
}
+#if 0 // UNUSED
/* recursively descends tree, each node only checked once */
/* node is checked to be of type object */
static int parent_check_node(DagNode *node, int curtime)
@@ -2420,68 +2539,7 @@ static int parent_check_node(DagNode *node, int curtime)
return DAG_WHITE;
}
-
-/* all nodes that influence this object get tagged, for calculating the exact
- position of this object at a given timeframe */
-void DAG_id_update_flags(ID *id)
-{
- Main *bmain= G.main;
- Scene *sce;
- DagNode *node;
- DagAdjList *itA;
- Object *ob;
- unsigned int lay;
-
- dag_current_scene_layers(bmain, &sce, &lay);
-
- if(!id || !sce || !sce->theDag)
- return;
-
- /* objects only currently */
- if(GS(id->name) != ID_OB)
- return;
-
- ob= (Object*)id;
-
- /* tag nodes unchecked */
- for(node = sce->theDag->DagNode.first; node; node= node->next)
- node->color = DAG_WHITE;
-
- node= dag_find_node(sce->theDag, ob);
-
- /* object not in scene? then handle group exception. needs to be dagged once too */
- if(node==NULL) {
- Group *group= NULL;
- while( (group = find_group(ob, group)) ) {
- GroupObject *go;
- /* primitive; tag all... this call helps building groups for particles */
- for(go= group->gobject.first; go; go= go->next)
- go->ob->recalc= OB_RECALC_ALL;
- }
- }
- else {
-
- node->color = DAG_GRAY;
-
- sce->theDag->time++;
- node= sce->theDag->DagNode.first;
- for(itA = node->child; itA; itA= itA->next) {
- if(itA->node->type==ID_OB && itA->node->lasttime!=sce->theDag->time)
- itA->node->color= parent_check_node(itA->node, sce->theDag->time);
- }
-
- /* set recalcs and flushes */
- DAG_scene_update_flags(bmain, sce, lay);
-
- /* now we clear recalcs, unless color is set */
- for(node = sce->theDag->DagNode.first; node; node= node->next) {
- if(node->type==ID_OB && node->color==DAG_WHITE) {
- Object *ob= node->ob;
- ob->recalc= 0;
- }
- }
- }
-}
+#endif
/* ******************* DAG FOR ARMATURE POSE ***************** */
@@ -2588,7 +2646,7 @@ void DAG_pose_sort(Object *ob)
itA = node->child;
while(itA != NULL) {
- if((itA->node->color == DAG_WHITE) ) {
+ if(itA->node->color == DAG_WHITE) {
itA->node->color = DAG_GRAY;
push_stack(nqueue,itA->node);
skip = 1;
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 666a62d96de..59e5aa7ade6 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -35,7 +35,6 @@
#include "MEM_guardedalloc.h"
-
#include "DNA_curve_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
@@ -45,6 +44,8 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_editVert.h"
+#include "BLI_scanfill.h"
+#include "BLI_utildefines.h"
#include "BKE_global.h"
#include "BKE_displist.h"
@@ -120,7 +121,7 @@ DispList *find_displist(ListBase *lb, int type)
dl= dl->next;
}
- return 0;
+ return NULL;
}
int displist_has_faces(ListBase *lb)
@@ -137,7 +138,7 @@ void copy_displist(ListBase *lbn, ListBase *lb)
{
DispList *dln, *dl;
- lbn->first= lbn->last= 0;
+ freedisplist(lbn);
dl= lb->first;
while(dl) {
@@ -149,7 +150,10 @@ void copy_displist(ListBase *lbn, ListBase *lb)
dln->index= MEM_dupallocN(dl->index);
dln->col1= MEM_dupallocN(dl->col1);
dln->col2= MEM_dupallocN(dl->col2);
-
+
+ if(dl->bevelSplitFlag)
+ dln->bevelSplitFlag= MEM_dupallocN(dl->bevelSplitFlag);
+
dl= dl->next;
}
}
@@ -289,7 +293,7 @@ static void init_fastshade_shadeinput(Render *re)
shi.combinedflag= -1;
}
-static Render *fastshade_get_render(Scene *scene)
+static Render *fastshade_get_render(Scene *UNUSED(scene))
{
// XXX 2.5: this crashes combined with previewrender
// due to global R so disabled for now
@@ -621,7 +625,6 @@ void shadeDispList(Scene *scene, Base *base)
Object *ob= base->object;
DispList *dl, *dlob;
Material *ma = NULL;
- Curve *cu;
Render *re;
float imat[3][3], mat[4][4], vec[3];
float *fp, *nor, n1[3];
@@ -655,8 +658,7 @@ void shadeDispList(Scene *scene, Base *base)
if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
/* now we need the normals */
- cu= ob->data;
- dl= cu->disp.first;
+ dl= ob->disp.first;
while(dl) {
extern Material defmaterial; /* material.c */
@@ -788,7 +790,7 @@ void reshadeall_displist(Scene *scene)
/* ****************** make displists ********************* */
-static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
+static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, int forRender)
{
Nurb *nu;
DispList *dl;
@@ -801,7 +803,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
while(nu) {
if(nu->hide==0) {
- if(G.rendering && cu->resolu_ren!=0)
+ if(forRender && cu->resolu_ren!=0)
resolu= cu->resolu_ren;
else
resolu= nu->resolu;
@@ -928,55 +930,58 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal)
{
EditVert *eve, *v1, *vlast;
EditFace *efa;
- DispList *dlnew=0, *dl;
+ DispList *dlnew=NULL, *dl;
float *f1;
- int colnr=0, charidx=0, cont=1, tot, a, *index;
+ int colnr=0, charidx=0, cont=1, tot, a, *index, nextcol= 0;
intptr_t totvert;
- if(dispbase==0) return;
- if(dispbase->first==0) return;
+ if(dispbase==NULL) return;
+ if(dispbase->first==NULL) return;
while(cont) {
cont= 0;
- totvert=0;
+ totvert= 0;
+ nextcol= 0;
dl= dispbase->first;
while(dl) {
if(dl->type==DL_POLY) {
if(charidx<dl->charidx) cont= 1;
- else if(charidx==dl->charidx) {
-
- colnr= dl->col;
- charidx= dl->charidx;
-
- /* make editverts and edges */
- f1= dl->verts;
- a= dl->nr;
- eve= v1= 0;
-
- while(a--) {
- vlast= eve;
-
- eve= BLI_addfillvert(f1);
- totvert++;
+ else if(charidx==dl->charidx) { /* character with needed index */
+ if(colnr==dl->col) {
+ /* make editverts and edges */
+ f1= dl->verts;
+ a= dl->nr;
+ eve= v1= NULL;
- if(vlast==0) v1= eve;
- else {
- BLI_addfilledge(vlast, eve);
+ while(a--) {
+ vlast= eve;
+
+ eve= BLI_addfillvert(f1);
+ totvert++;
+
+ if(vlast==NULL) v1= eve;
+ else {
+ BLI_addfilledge(vlast, eve);
+ }
+ f1+=3;
}
- f1+=3;
- }
-
- if(eve!=0 && v1!=0) {
- BLI_addfilledge(eve, v1);
+
+ if(eve!=NULL && v1!=NULL) {
+ BLI_addfilledge(eve, v1);
+ }
+ } else if (colnr<dl->col) {
+ /* got poly with next material at current char */
+ cont= 1;
+ nextcol= 1;
}
}
}
dl= dl->next;
}
- if(totvert && BLI_edgefill(0, 0)) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) {
+ if(totvert && BLI_edgefill(0)) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) {
/* count faces */
tot= 0;
@@ -1032,7 +1037,14 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal)
}
BLI_end_edgefill();
- charidx++;
+ if(nextcol) {
+ /* stay at current char but fill polys with next material */
+ colnr++;
+ } else {
+ /* switch to next char and start filling from first material */
+ charidx++;
+ colnr= 0;
+ }
}
/* do not free polys, needed for wireframe display */
@@ -1046,7 +1058,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
float *fp, *fp1;
int a, dpoly;
- front.first= front.last= back.first= back.last= 0;
+ front.first= front.last= back.first= back.last= NULL;
dl= dispbase->first;
while(dl) {
@@ -1107,7 +1119,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
}
-static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
+static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
{
if(cu->flag & CU_3D) return;
@@ -1126,16 +1138,14 @@ static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
*/
float calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
{
- Curve *cu;
DispList *dl;
if(taperobj==NULL || taperobj->type!=OB_CURVE) return 1.0;
- cu= taperobj->data;
- dl= cu->disp.first;
+ dl= taperobj->disp.first;
if(dl==NULL) {
makeDispListCurveTypes(scene, taperobj, 0);
- dl= cu->disp.first;
+ dl= taperobj->disp.first;
}
if(dl) {
float fac= ((float)cur)/(float)(tot-1);
@@ -1192,6 +1202,8 @@ void makeDispListMBall(Scene *scene, Object *ob)
void makeDispListMBall_forRender(Scene *scene, Object *ob, ListBase *dispbase)
{
metaball_polygonize(scene, ob, dispbase);
+ tex_space_mball(ob);
+
object_deform_mball(ob, dispbase);
}
@@ -1208,10 +1220,20 @@ static ModifierData *curve_get_tesselate_point(Scene *scene, Object *ob, int for
preTesselatePoint = NULL;
for (; md; md=md->next) {
+ ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
if (!modifier_isEnabled(scene, md, required_mode)) continue;
+ if (mti->type == eModifierTypeType_Constructive) return preTesselatePoint;
if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
- preTesselatePoint = md;
+ preTesselatePoint = md;
+
+ /* this modifiers are moving point of tesselation automatically
+ (some of them even can't be applied on tesselated curve), set flag
+ for incformation button in modifier's header */
+ md->mode |= eModifierMode_ApplyOnSpline;
+ } else if(md->mode&eModifierMode_ApplyOnSpline) {
+ preTesselatePoint = md;
}
}
@@ -1603,8 +1625,15 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
for (nu=nubase->first; nu; nu=nu->next) {
if(forRender || nu->hide==0) {
+ int resolu= nu->resolu, resolv= nu->resolv;
+
+ if(forRender){
+ if(cu->resolu_ren) resolu= cu->resolu_ren;
+ if(cu->resolv_ren) resolv= cu->resolv_ren;
+ }
+
if(nu->pntsv==1) {
- len= SEGMENTSU(nu)*nu->resolu;
+ len= SEGMENTSU(nu)*resolu;
dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
@@ -1623,10 +1652,10 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
else dl->type= DL_SEGM;
- makeNurbcurve(nu, data, NULL, NULL, NULL, nu->resolu, 3*sizeof(float));
+ makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float));
}
else {
- len= (nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv);
+ len= (nu->pntsu*resolu) * (nu->pntsv*resolv);
dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
@@ -1642,12 +1671,12 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
data= dl->verts;
dl->type= DL_SURF;
- dl->parts= (nu->pntsu*nu->resolu); /* in reverse, because makeNurbfaces works that way */
- dl->nr= (nu->pntsv*nu->resolv);
+ dl->parts= (nu->pntsu*resolu); /* in reverse, because makeNurbfaces works that way */
+ dl->nr= (nu->pntsv*resolv);
if(nu->flagv & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_U; /* reverse too! */
if(nu->flagu & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_V;
- makeNurbfaces(nu, data, 0);
+ makeNurbfaces(nu, data, 0, resolu, resolv);
/* gl array drawing: using indices */
displist_surf_indices(dl);
@@ -1655,6 +1684,11 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
}
}
+ /* make copy of 'undeformed" displist for texture space calculation
+ actually, it's not totally undeformed -- pre-tesselation modifiers are
+ already applied, thats how it worked for years, so keep for compatibility (sergey) */
+ copy_displist(&cu->disp, dispbase);
+
if (!forRender) {
tex_space_curve(cu);
}
@@ -1700,7 +1734,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
/* no bevel or extrude, and no width correction? */
if (!dlbev.first && cu->width==1.0f) {
- curve_to_displist(cu, nubase, dispbase);
+ curve_to_displist(cu, nubase, dispbase, forRender);
} else {
float widfac= cu->width-1.0;
BevList *bl= cu->bev.first;
@@ -1770,8 +1804,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
/* CU_2D conflicts with R_NOPUNOFLIP */
dl->rt= nu->flag & ~CU_2D;
- dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "col2");
- bevp= (BevPoint *)(bl+1);
+ dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "bevelSplitFlag");
/* for each point of poly make a bevel piece */
bevp= (BevPoint *)(bl+1);
@@ -1828,6 +1861,11 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if(cu->flag & CU_PATH) calc_curvepath(ob);
+ /* make copy of 'undeformed" displist for texture space calculation
+ actually, it's not totally undeformed -- pre-tesselation modifiers are
+ already applied, thats how it worked for years, so keep for compatibility (sergey) */
+ copy_displist(&cu->disp, dispbase);
+
if (!forRender) {
tex_space_curve(cu);
}
@@ -1842,13 +1880,16 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco)
{
- Curve *cu = ob->data;
+ Curve *cu= ob->data;
ListBase *dispbase;
freedisplist(&(ob->disp));
- dispbase= &(cu->disp);
+ dispbase= &(ob->disp);
freedisplist(dispbase);
+ /* free displist used for textspace */
+ freedisplist(&cu->disp);
+
do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco);
if (ob->derivedFinal) {
@@ -1895,15 +1936,10 @@ float *makeOrcoDispList(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int
return orco;
}
-void imagestodisplist(void)
-{
- /* removed */
-}
-
/* this is confusing, there's also min_max_object, appplying the obmat... */
static void boundbox_displist(Object *ob)
{
- BoundBox *bb=0;
+ BoundBox *bb=NULL;
float min[3], max[3];
DispList *dl;
float *vert;
@@ -1915,10 +1951,10 @@ static void boundbox_displist(Object *ob)
Curve *cu= ob->data;
int doit= 0;
- if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
bb= cu->bb;
- dl= cu->disp.first;
+ dl= ob->disp.first;
while (dl) {
if(dl->type==DL_INDEX3) tot= dl->nr;
diff --git a/source/blender/blenkernel/intern/editderivedbmesh.c b/source/blender/blenkernel/intern/editderivedbmesh.c
index 168e0e566de..b38521b0a23 100644
--- a/source/blender/blenkernel/intern/editderivedbmesh.c
+++ b/source/blender/blenkernel/intern/editderivedbmesh.c
@@ -61,6 +61,7 @@
#include "BLI_scanfill.h"
#include "BLI_ghash.h"
#include "BLI_array.h"
+#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_customdata.h"
@@ -201,7 +202,7 @@ static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
/*complete the loop*/
BLI_addfilledge(firstv, v);
- BLI_edgefill(0, 0);
+ BLI_edgefill(0);
for (efa = fillfacebase.first; efa; efa=efa->next) {
BMLoop *l1, *l2, *l3;
@@ -534,39 +535,44 @@ static void bmDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(vo
static void bmDM_drawUVEdges(DerivedMesh *dm)
{
-#if 0
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEditMesh *em = bmdm->tc;
BMFace *efa;
- MTFace *tf;
+ BMIter iter;
glBegin(GL_LINES);
- for(efa= bmdm->tc->bm->faces.first; efa; efa= efa->next) {
- tf = CustomData_bm_get(&bmdm->tc->bm->pdata, efa->data, CD_MTFACE);
-
- if(tf && !(efa->h)) {
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
-
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
-
- if (!efa->v4) {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[0]);
- } else {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[3]);
- glVertex2fv(tf->uv[3]);
- glVertex2fv(tf->uv[0]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BMIter liter;
+ BMLoop *l;
+ MLoopUV *lastluv = NULL, *firstluv = NULL;
+
+ if (BM_TestHFlag(efa, BM_HIDDEN))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv) {
+ if (lastluv)
+ glVertex2fv(luv->uv);
+ glVertex2fv(luv->uv);
+
+ lastluv = luv;
+ if (!firstluv)
+ firstluv = luv;
}
}
+
+ if (lastluv) {
+ glVertex2fv(lastluv->uv);
+ glVertex2fv(firstluv->uv);
+ }
}
glEnd();
-#endif
}
-static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3],
- float (*vertexCos)[3])
+static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3],
+ float (*vertexCos)[3])
{
BMIter iter;
BMLoop *l;
@@ -591,7 +597,7 @@ static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3],
}
if (tot==0) return;
- VECMUL(cent, 1.0f/(float)tot);
+ mul_v3_fl(cent, 1.0f/(float)tot);
}
static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
@@ -1159,9 +1165,7 @@ static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
vert_r->no[1] = (short)(ev->no[1] * 32767.0f);
vert_r->no[2] = (short)(ev->no[2] * 32767.0f);
- /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
vert_r->flag = BMFlags_To_MEFlags(ev);
- vert_r->mat_nr = 0;
if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
@@ -1255,8 +1259,6 @@ static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
vert_r->no[1] = (short) (ev->no[1] * 32767.0);
vert_r->no[2] = (short) (ev->no[2] * 32767.0);
- /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
- vert_r->mat_nr = 0;
vert_r->flag = BMFlags_To_MEFlags(ev);
if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index fba96d2fd8f..5d8401d7a43 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -29,6 +29,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#include <stddef.h>
#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
#include <math.h>
@@ -58,6 +59,7 @@
#include "BLI_listbase.h"
#include "BLI_noise.h"
#include "BLI_rand.h"
+#include "BLI_utildefines.h"
#include "PIL_time.h"
@@ -85,8 +87,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_utildefines.h"
+
#include "RE_render_ext.h"
#include "RE_shader_ext.h"
@@ -165,7 +166,7 @@ PartEff *give_parteff(Object *ob)
if(paf->type==EFF_PARTICLE) return paf;
paf= paf->next;
}
- return 0;
+ return NULL;
}
void free_effect(Effect *eff)
@@ -264,6 +265,9 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector
eff = new_effector_cache(scene, ob, NULL, ob->pd);
+ /* make sure imat is up to date */
+ invert_m4_m4(ob->imat, ob->obmat);
+
BLI_addtail(*effectors, eff);
}
static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src)
@@ -410,7 +414,7 @@ void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, Effecte
/************************************************/
// triangle - ray callback function
-static void eff_tri_ray_hit(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+static void eff_tri_ray_hit(void *UNUSED(userData), int UNUSED(index), const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit)
{
// whenever we hit a bounding box, we don't check further
hit->dist = -1;
@@ -429,7 +433,7 @@ static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, Effect
return visibility;
if(!colls)
- colls = get_collider_cache(eff->scene, NULL, NULL);
+ colls = get_collider_cache(eff->scene, eff->ob, NULL);
if(!colls)
return visibility;
@@ -515,7 +519,7 @@ static float falloff_func_rad(PartDeflect *pd, float fac)
return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r);
}
-float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, EffectorWeights *weights)
+float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *UNUSED(point), EffectorWeights *weights)
{
float temp[3];
float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f;
@@ -625,7 +629,6 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
}
}
else if(eff->psys) {
- ParticleSimulationData sim = {eff->scene, eff->ob, eff->psys, NULL, NULL};
ParticleData *pa = eff->psys->particles + *efd->index;
ParticleKey state;
@@ -633,6 +636,11 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
if(eff->psys == point->psys && *efd->index == point->index)
;
else {
+ ParticleSimulationData sim= {NULL};
+ sim.scene= eff->scene;
+ sim.ob= eff->ob;
+ sim.psys= eff->psys;
+
/* TODO: time from actual previous calculated frame (step might not be 1) */
state.time = cfra - 1.0;
ret = psys_get_particle_state(&sim, *efd->index, &state, 0);
@@ -643,11 +651,15 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
// eff->flag |= PE_VELOCITY_TO_IMPULSE;
//}
- VECCOPY(efd->loc, state.co);
- VECCOPY(efd->nor, state.vel);
- if(real_velocity) {
- VECCOPY(efd->vel, state.vel);
- }
+ copy_v3_v3(efd->loc, state.co);
+
+ /* rather than use the velocity use rotated x-axis (defaults to velocity) */
+ efd->nor[0] = 1.f;
+ efd->nor[1] = efd->nor[2] = 0.f;
+ mul_qt_v3(state.rot, efd->nor);
+
+ if(real_velocity)
+ copy_v3_v3(efd->vel, state.vel);
efd->size = pa->size;
}
@@ -667,10 +679,10 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
/* for vortex the shape chooses between old / new force */
if(eff->pd && eff->pd->shape == PFIELD_SHAPE_PLANE) {
/* efd->loc is closes point on effector xy-plane */
- float temp[3];
+ float temp[3], translate[3];
sub_v3_v3v3(temp, point->loc, ob->obmat[3]);
- project_v3_v3v3(efd->loc, temp, efd->nor);
- sub_v3_v3v3(efd->loc, point->loc, efd->loc);
+ project_v3_v3v3(translate, temp, efd->nor);
+ add_v3_v3v3(efd->loc, ob->obmat[3], translate);
}
else {
VECCOPY(efd->loc, ob->obmat[3]);
@@ -712,7 +724,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
return ret;
}
-static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p)
+static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p, int *step)
{
if(eff->pd->shape == PFIELD_SHAPE_POINTS) {
efd->index = p;
@@ -745,6 +757,13 @@ static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoin
*p= point->index % eff->psys->totpart;
*tot= *p + 1;
}
+
+ if(eff->psys->part->effector_amount) {
+ int totpart = eff->psys->totpart;
+ int amount = eff->psys->part->effector_amount;
+
+ *step = (totpart > amount) ? totpart/amount : 1;
+ }
}
else {
*p = 0;
@@ -762,7 +781,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP
if(!eff->pd->tex)
return;
- result[0].nor = result[1].nor = result[2].nor = result[3].nor = 0;
+ result[0].nor = result[1].nor = result[2].nor = result[3].nor = NULL;
strength= eff->pd->f_strength * efd->falloff;
@@ -774,7 +793,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP
}
if(eff->pd->flag & PFIELD_TEX_OBJECT) {
- mul_m4_v3(eff->ob->obmat, tex_co);
+ mul_m4_v3(eff->ob->imat, tex_co);
}
hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL,NULL, 0, result);
@@ -826,7 +845,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP
add_v3_v3(total_force, force);
}
-void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force)
+static void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force)
{
PartDeflect *pd = eff->pd;
RNG *rng = pd->rng;
@@ -982,7 +1001,7 @@ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *we
*/
EffectorCache *eff;
EffectorData efd;
- int p=0, tot = 1;
+ int p=0, tot = 1, step = 1;
/* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
/* Check for min distance here? (yes would be cool to add that, ton) */
@@ -990,9 +1009,9 @@ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *we
if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
/* object effectors were fully checked to be OK to evaluate! */
- get_effector_tot(eff, &efd, point, &tot, &p);
+ get_effector_tot(eff, &efd, point, &tot, &p, &step);
- for(; p<tot; p++) {
+ for(; p<tot; p+=step) {
if(get_effector_data(eff, &efd, point, 0)) {
efd.falloff= effector_falloff(eff, &efd, point, weights);
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
index deae6d2808b..4afce1e56c4 100644
--- a/source/blender/blenkernel/intern/exotic.c
+++ b/source/blender/blenkernel/intern/exotic.c
@@ -1,4 +1,5 @@
-/* exotic.c
+/*
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -20,21 +21,24 @@
* All rights reserved.
*
*
- * Contributor(s):
+ * Contributor(s):
* - Martin DeMello
* Added dxf_read_arc, dxf_read_ellipse and dxf_read_lwpolyline
* Copyright (C) 2004 by Etheract Software Labs
*
* - Blender Foundation
*
- * ***** END GPL LICENSE BLOCK *****/
+ * ***** END GPL LICENSE BLOCK ****
+ */
+#include <stddef.h>
#include "BLI_storage.h"
+#include <stdlib.h>
#include <ctype.h> /* isdigit, isspace */
#include <math.h>
#include <stdio.h>
-#include <stdlib.h>
+
#include <fcntl.h>
#include <string.h>
#include <errno.h>
@@ -59,9 +63,11 @@
#include "DNA_camera_types.h"
#include "DNA_scene_types.h"
-#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_storage.h"
+#include "BLI_utildefines.h"
+
#include "BKE_blender.h"
#include "BKE_global.h"
@@ -71,22 +77,22 @@
#include "BKE_object.h"
#include "BKE_material.h"
#include "BKE_report.h"
-
+#include "BKE_exotic.h"
#include "BKE_displist.h"
#include "BKE_DerivedMesh.h"
#include "BKE_curve.h"
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
#include "zlib.h"
-static int is_dxf(char *str);
-static void dxf_read(Scene *scene, char *filename);
-static int is_stl(char *str);
+static int is_dxf(const char *str);
+static void dxf_read(Scene *scene, const char *filename);
+static int is_stl(const char *str);
-static int is_stl_ascii(char *str)
+static int is_stl_ascii(const char *str)
{
FILE *fpSTL;
char buffer[1000];
@@ -111,7 +117,7 @@ static int is_stl_ascii(char *str)
return 1;
}
-static int is_stl(char *str)
+static int is_stl(const char *str)
{
int i;
i = strlen(str) - 3;
@@ -187,7 +193,7 @@ static void mesh_add_normals_flags(Mesh *me)
}
}
-static void read_stl_mesh_binary(Scene *scene, char *str)
+static void read_stl_mesh_binary(Scene *scene, const char *str)
{
FILE *fpSTL;
Object *ob;
@@ -311,7 +317,7 @@ static void read_stl_mesh_binary(Scene *scene, char *str)
STLBAILOUT("Bad vertex!"); \
++totvert; \
}
-static void read_stl_mesh_ascii(Scene *scene, char *str)
+static void read_stl_mesh_ascii(Scene *scene, const char *str)
{
FILE *fpSTL;
char buffer[2048], *cp;
@@ -360,10 +366,16 @@ static void read_stl_mesh_ascii(Scene *scene, char *str)
* sure we have enough storage for some more faces
*/
if ( (totface) && ( (totface % 10000) == 0 ) ) {
+ float *vertdata_old= vertdata;
++numtenthousand;
vertdata = realloc(vertdata,
numtenthousand*3*30000*sizeof(float));
- if (!vertdata) { STLALLOCERROR; }
+ if (!vertdata) {
+ if(vertdata_old) {
+ free(vertdata_old);
+ }
+ STLALLOCERROR;
+ }
}
/* Don't read normal, but check line for proper syntax anyway
@@ -449,1400 +461,60 @@ static void read_stl_mesh_ascii(Scene *scene, char *str)
#undef STLREADLINE
#undef STLREADVERT
-/* ***************** INVENTOR ******************* */
-
-
-#define IV_MAXSTACK 3000000
-#define IV_MAXFIELD 10
-#define IV_MAXCOL 16
-
-static float *iv_data_stack;
-static float ivcolors[IV_MAXCOL][3];
-static Object *ivsurf;
-static ListBase ivbase;
-
-struct IvNode {
- struct IvNode *next, *prev;
- char *nodename;
- char *fieldname[IV_MAXFIELD];
- int datalen[IV_MAXFIELD];
- float *data[IV_MAXFIELD];
-};
-
-static int iv_curcol=0;
-
-static int iv_colornumber(struct IvNode *iv)
-{
- float *fp, fr = 0.0, fg = 0.0, fb = 0.0;
- int a;
- char *cp;
-
- /* search back to last material */
- while(iv) {
- if( strcmp(iv->nodename, "Material")==0) {
- fp= iv->data[0];
- if(fp==0) fp= iv->data[1];
- if(fp) {
- fr= fp[0];
- fg= fp[1];
- fb= fp[2];
- }
- break;
- }
- else if( strcmp(iv->nodename, "BaseColor")==0) {
- fp= iv->data[0];
- fr= fp[0];
- fg= fp[1];
- fb= fp[2];
- break;
- }
- else if( strcmp(iv->nodename, "PackedColor")==0) {
- cp= (char *)iv->data[0];
- fr= cp[3]/255.0f;
- fg= cp[2]/255.0f;
- fb= cp[1]/255.0f;
- break;
- }
- iv= iv->prev;
-
- }
- if(iv==0) return 0;
- if(iv->datalen[0]<3) return 0;
-
- for(a=0; a<iv_curcol; a++) {
-
- if(ivcolors[a][0]== fr)
- if(ivcolors[a][1]== fg)
- if(ivcolors[a][2]== fb) return a+1
- ;
- }
-
- if(a>=IV_MAXCOL) a= IV_MAXCOL-1;
- iv_curcol= a+1;
- ivcolors[a][0]= fr;
- ivcolors[a][1]= fg;
- ivcolors[a][2]= fb;
-
- return iv_curcol;
-}
-
-static int iv_finddata(struct IvNode *iv, char *field, int fieldnr)
-{
- /* search for "field", count data size and make datablock. return skipdata */
- float *fp;
- int len, stackcount, skipdata=0;
- char *cpa, terminator, str[64];
- intptr_t i;
-
- len= strlen(field);
-
- cpa= iv->nodename+1;
- while( *cpa != '}' ) {
-
- if( *cpa == *field ) {
- if( strncmp(cpa, field, len)==0 ) {
- iv->fieldname[fieldnr]= cpa;
-
- /* read until first character */
- cpa+= len;
- skipdata+= len;
- *cpa= 0;
- cpa++;
- skipdata++;
-
- while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) cpa++;
- if( *cpa=='[' ) {
- terminator= ']';
- cpa++;
- skipdata++;
- }
- else terminator= 13;
-
- stackcount= 0;
- fp= iv_data_stack;
-
- while( *cpa!=terminator && *cpa != '}' ) {
-
- /* in fact, isdigit should include the dot and minus */
- if( (isdigit(*cpa) || *cpa=='.' || *cpa=='-') && (isspace(cpa[-1]) || cpa[-1]==0 || cpa[-1]==',') ) {
- if(cpa[1]=='x') {
- memcpy(str, cpa, 16);
- str[16]= 0;
-
- sscanf(str, "%x", (int *)fp);
- }
- else {
- /* atof doesn't stop after the first float
- * in a long string at Windows... so we copy
- * the float to a new string then atof... */
- char *cpa_temp = strpbrk(cpa, ", \n");
- i = cpa_temp - cpa;
-
- if (i>63) *fp= 0.0;
- else {
- memcpy(str, cpa, i);
- str[i]=0;
-
- *fp= (float) atof(str);
- }
- }
-
- stackcount++;
- if(stackcount>=IV_MAXSTACK) {
- printf("stackoverflow in IV read\n");
- break;
- }
- fp++;
- }
- cpa++;
- skipdata++;
- }
-
- iv->datalen[fieldnr]= stackcount;
- if(stackcount) {
- iv->data[fieldnr]= MEM_mallocN(sizeof(float)*stackcount, "iv_finddata");
- memcpy(iv->data[fieldnr], iv_data_stack, sizeof(float)*stackcount);
- }
- else iv->data[fieldnr]= 0;
-
- return skipdata;
- }
- }
- cpa++;
- skipdata++;
- }
-
- return skipdata;
-}
-
-static void read_iv_index(float *data, float *baseadr, float *index, int nr, int coordtype)
-{
- /* write in data: baseadr with offset index (and number nr) */
- float *fp;
- int ofs;
-
- while(nr--) {
- ofs= (int) *index;
- fp= baseadr+coordtype*ofs;
- VECCOPY(data, fp);
- data+= 3;
- index++;
- }
-}
-
-
-
-static void read_inventor(Scene *scene, char *str, struct ListBase *listb)
-{
- struct IvNode *iv, *ivp, *ivn;
- char *maindata, *md, *cpa;
- float *index, *data, *fp;
- int file, filelen, count, lll, face, nr = 0;
- int skipdata, ok, a, b, tot, first, colnr, coordtype, polytype, *idata;
- struct DispList *dl;
- ReportList *reports= NULL; /* XXX */
-
- ivbase.first= ivbase.last= 0;
- iv_curcol= 0;
- ivsurf= 0;
-
- file= open(str, O_BINARY|O_RDONLY);
- if(file== -1) {
- BKE_reportf(reports, RPT_ERROR, "Can't read file: %s.", strerror(errno));
- return;
- }
-
- filelen= BLI_filesize(file);
- if(filelen < 1) {
- close(file);
- return;
- }
-
- maindata= MEM_mallocN(filelen, "leesInventor");
- if(read(file, maindata, filelen) < filelen) {
- BKE_reportf(reports, RPT_ERROR, "Failed reading file: premature end of file.");
- close(file);
- return;
- }
- close(file);
-
- iv_data_stack= MEM_mallocN(sizeof(float)*IV_MAXSTACK, "ivstack");
-
- /* preprocess: remove comments */
- md= maindata+20;
- count= 20;
- while(count<filelen) {
- if( *md=='#' ) { /* comment */
- while( *md!=13 && *md!=10) { /* enters */
- *md= 32;
- md++;
- count++;
- if(count>=filelen) break;
- }
- }
- md++;
- count++;
- }
-
-
- /* now time to collect: which are the nodes and fields? */
- md= maindata;
- count= 0;
- while(count<filelen) {
- if( *md=='{' ) { /* read back */
-
- cpa= md-1;
- while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) { /* remove spaces/enters/tab */
- *cpa= 0;
- cpa--;
- }
-
- while( *cpa>32 && *cpa<128) cpa--;
- cpa++;
- *md= 0;
-
- ok= 0;
- skipdata= 0;
- iv= MEM_callocN(sizeof(struct IvNode), "leesInventor");
- iv->nodename= cpa;
-
- if(strcmp(cpa, "Coordinate3")==0 || strcmp(cpa, "Coordinate4")==0) {
- skipdata= iv_finddata(iv, "point", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "VertexProperty")==0) {
- skipdata= iv_finddata(iv, "vertex", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "IndexedLineSet")==0) {
- skipdata= iv_finddata(iv, "coordIndex", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "IndexedTriangleMesh")==0) {
- skipdata= iv_finddata(iv, "coordIndex", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "IndexedFaceSet")==0) {
- skipdata= iv_finddata(iv, "coordIndex", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "FaceSet")==0) {
- skipdata= iv_finddata(iv, "numVertices", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "Material")==0) {
- iv_finddata(iv, "diffuseColor", 0);
- iv_finddata(iv, "ambientColor", 1);
- ok= 1;
- }
- else if(strcmp(cpa, "BaseColor")==0) {
- iv_finddata(iv, "rgb", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "PackedColor")==0) {
- iv_finddata(iv, "rgba", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "QuadMesh")==0) {
- iv_finddata(iv, "verticesPerColumn", 0);
- iv_finddata(iv, "verticesPerRow", 1);
-
- ok= 1;
- }
- else if(strcmp(cpa, "IndexedTriangleStripSet")==0) {
- skipdata= iv_finddata(iv, "coordIndex", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "TriangleStripSet")==0) {
- skipdata= iv_finddata(iv, "numVertices", 0);
- ok= 1;
- }
- else if(strcmp(cpa, "IndexedNurbsSurface")==0 || strcmp(cpa, "NurbsSurface")==0) {
- iv_finddata(iv, "numUControlPoints", 0);
- iv_finddata(iv, "numVControlPoints", 1);
- iv_finddata(iv, "uKnotVector", 2);
- iv_finddata(iv, "vKnotVector", 3);
- ok= 1;
- }
- else {
- /* to the end */
- while( *md != '}') {
- md++;
- count++;
- if(count<filelen) break;
- }
- }
-
-
- if(ok) {
- BLI_addtail(&ivbase, iv);
- md+= skipdata;
- count+= skipdata;
- }
- else MEM_freeN(iv);
-
- }
- md++;
- count++;
- }
-
- /* join nodes */
- iv= ivbase.first;
-
- while(iv) {
- ivn= iv->next;
-
- if( strncmp(iv->nodename, "Indexed", 7)==0) {
- /* seek back: same name? */
-
- ivp= iv->prev;
- while(ivp) {
- if(strcmp(iv->nodename, ivp->nodename)==0) break;
-
- if(strcmp(ivp->nodename, "Coordinate3")==0 ||
- strcmp(ivp->nodename, "Coordinate4")==0 ||
- strcmp(ivp->nodename, "VertexProperty")==0) {
- ivp= 0;
- break;
- }
- ivp= ivp->prev;
- }
-
- if(ivp) {
- /* add iv to ivp */
-
- tot= iv->datalen[0] + ivp->datalen[0];
- if(tot) {
- data= MEM_mallocN(tot*sizeof(float), "samenvoeg iv");
- memcpy(data, ivp->data[0], sizeof(float)*ivp->datalen[0]);
- memcpy(data+ivp->datalen[0], iv->data[0], sizeof(float)*iv->datalen[0]);
-
- ivp->datalen[0]+= iv->datalen[0];
- MEM_freeN(ivp->data[0]);
- ivp->data[0]= data;
-
- BLI_remlink(&ivbase, iv);
- MEM_freeN(iv->data[0]);
- MEM_freeN(iv);
- }
- }
- }
-
- iv= ivn;
- }
-
-
- /* convert Nodes to DispLists */
- iv= ivbase.first;
- while(iv) {
-
- /* printf(" Node: %s\n", iv->nodename); */
- /* if(iv->fieldname[0]) printf(" Field: %s len %d\n", iv->fieldname[0], iv->datalen[0]); */
- coordtype= 3;
-
- if( strcmp(iv->nodename, "IndexedLineSet")==0 ) {
-
- colnr= iv_colornumber(iv);
-
- /* seek back to data */
- ivp= iv;
- while(ivp->prev) {
- ivp= ivp->prev;
- if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
- coordtype= 3;
- break;
- }
- if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
- coordtype= 4;
- break;
- }
- }
- if(ivp) {
-
- /* count the nr of lines */
- tot= 0;
- index= iv->data[0];
- lll = iv->datalen[0]-1;
- for(a=0; a<lll; a++) {
- if(index[0]!= -1 && index[1]!= -1) tot++;
- index++;
- }
-
- tot*= 2; /* nr of vertices */
- dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor1");
- BLI_addtail(listb, dl);
- dl->type= DL_SEGM;
- dl->nr= 2;
- dl->parts= tot/2;
- dl->col= colnr;
- data= (float *)(dl+1);
-
- index= iv->data[0];
- for(a=0; a<lll; a++) {
- if(index[0]!= -1 && index[1]!= -1) {
- read_iv_index(data, ivp->data[0], index, 2, coordtype);
- data+= 6;
- }
- index++;
- }
- }
- }
- else if( strcmp(iv->nodename, "FaceSet")==0 ) {
-
- colnr= iv_colornumber(iv);
-
- /* seek back to data */
- ivp= iv;
- while(ivp->prev) {
- ivp= ivp->prev;
- if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
- coordtype= 3;
- break;
- }
- if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
- coordtype= 4;
- break;
- }
- }
-
- if(ivp) {
- /* count triangles */
- tot= 0;
-
- index= iv->data[0];
- polytype= (int) index[0];
-
- for(a=0; a<iv->datalen[0]; a++) {
- if(index[0]== polytype) tot++; /* one kind? */
- index++;
- }
-
-
- tot*= polytype; /* nr of vertices */
- dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor4");
- BLI_addtail(listb, dl);
- dl->type= DL_POLY;
- dl->nr= polytype;
- dl->parts= tot/polytype;
- dl->col= colnr;
- data= (float *)(dl+1);
-
- index= ivp->data[0];
- first= 1;
- for(a=0; a<iv->datalen[0]; a++) {
-
- VECCOPY(data, index);
- data+= 3;
- index+= 3;
-
- VECCOPY(data, index);
- data+= 3;
- index+= 3;
-
- VECCOPY(data, index);
- data+= 3;
- index+= 3;
-
- if(polytype==4) {
- VECCOPY(data, index);
- data+= 3;
- index+= 3;
- }
- }
- }
- }
- else if( strcmp(iv->nodename, "TriangleStripSet")==0 ) {
-
- colnr= iv_colornumber(iv);
-
- /* seek back to data */
- ivp= iv;
- while(ivp->prev) {
- ivp= ivp->prev;
- if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
- coordtype= 3;
- break;
- }
- if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
- coordtype= 4;
- break;
- }
- }
-
- if(ivp) {
- /* count triangles */
- tot= 0;
- face= 0;
-
- index= iv->data[0]; /* strip size */
-
- for(a=0; a<iv->datalen[0]; a++) {
- tot+= (int) index[0];
- face+= ((int) index[0]) - 2;
- index++;
- }
-
- dl= MEM_callocN(sizeof(struct DispList), "leesInventor4");
- dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
- dl->index= MEM_callocN( face*3*sizeof(int), "dl index");
-
- dl->type= DL_INDEX3;
- dl->nr= tot;
- dl->parts= face;
-
- BLI_addtail(listb, dl);
- dl->col= colnr;
-
- index= iv->data[0]; /* strip size */
- fp= ivp->data[0]; /* vertices */
- data= dl->verts;
- idata= dl->index;
- first= 0;
-
- for(a=0; a<iv->datalen[0]; a++) {
-
- /* vertices */
- for(b=0; b<index[0]; b++) {
- VECCOPY(data, fp);
- data+= 3;
- fp+= coordtype;
- }
-
- /* indices */
- lll = index[0] - 2;
- for(b=0; b<lll; b++) {
- idata[0]= first;
- idata[1]= first+1;
- idata[2]= first+2;
- first++;
- idata+= 3;
- }
- first+= 2;
-
- index++;
- }
- }
- }
- else if( strcmp(iv->nodename, "IndexedFaceSet")==0 ) {
-
- colnr= iv_colornumber(iv);
-
- /* seek back to data */
- ivp= iv;
- while(ivp->prev) {
- ivp= ivp->prev;
- if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
- coordtype= 3;
- break;
- }
- if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
- coordtype= 4;
- break;
- }
- }
- if(ivp) {
-
- /* count triangles */
- face= 0;
- index= iv->data[0];
- lll = iv->datalen[0]-2;
- for(a=0; a<lll; a++) {
- if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
- index++;
- }
-
- /*number of vertices */
- tot= ivp->datalen[0]/coordtype;
-
- if(tot) {
- dl= MEM_callocN(sizeof(struct DispList), "leesInventor5");
- BLI_addtail(listb, dl);
- dl->type= DL_INDEX3;
- dl->nr= tot;
- dl->parts= face;
- dl->col= colnr;
-
- dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
- dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
-
- /* vertices */
- fp= ivp->data[0];
- data= dl->verts;
- for(b=tot; b>0; b--) {
- VECCOPY(data, fp);
- data+= 3;
- fp+= coordtype;
- }
-
- /* indices */
- index= iv->data[0];
- idata= dl->index;
- first= 1;
- lll=iv->datalen[0]-2;
- for(a=0; a<lll; a++) {
-
- if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
-
- /* this trick is to fill poly's with more than 3 vertices correctly */
- if(first) {
- nr= (int) index[0];
- first= 0;
- }
- idata[0]= nr;
- idata[1]= (int) index[1];
- idata[2]= (int) index[2];
- idata+= 3;
- }
- else first= 1;
-
- index++;
- }
- }
- }
- }
- else if( strcmp(iv->nodename, "IndexedTriangleMesh")==0 ||
- strcmp(iv->nodename, "IndexedTriangleStripSet")==0 ) {
-
- colnr= iv_colornumber(iv);
-
- /* seek back to data */
- ivp= iv;
- while(ivp->prev) {
- ivp= ivp->prev;
- if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
- coordtype= 3;
- break;
- }
- if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
- coordtype= 4;
- break;
- }
- }
- if(ivp) {
-
- /* count triangles */
- face= 0;
- index= iv->data[0];
- lll=iv->datalen[0]-2;
- for(a=0; a<lll; a++) {
- if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
- index++;
- }
-
- /* nr of vertices */
- tot= ivp->datalen[0]/coordtype;
-
- dl= MEM_callocN(sizeof(struct DispList), "leesInventor6");
- BLI_addtail(listb, dl);
- dl->type= DL_INDEX3;
- dl->nr= tot;
- dl->parts= face;
- dl->col= colnr;
-
- dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
- dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
-
- /* vertices */
- fp= ivp->data[0];
- data= dl->verts;
- for(b=tot; b>0; b--) {
- VECCOPY(data, fp);
- data+= 3;
- fp+= coordtype;
- }
-
- /* indices */
- index= iv->data[0];
- idata= dl->index;
-
- lll=iv->datalen[0]-2;
- for(a=lll; a>0; a--) {
-
- if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
- idata[0]= (int) index[0];
- idata[1]= (int) index[1];
- idata[2]= (int) index[2];
- idata+= 3;
- }
- index++;
- }
- }
- }
- else if( strcmp(iv->nodename, "QuadMesh")==0 ) {
-
- colnr= iv_colornumber(iv);
-
- /* seek back to data */
- ivp= iv;
- while(ivp->prev) {
- ivp= ivp->prev;
- if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
- coordtype= 3;
- break;
- }
- if( strcmp(ivp->nodename, "VertexProperty")==0 ) {
- coordtype= 3;
- break;
- }
- if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
- coordtype= 4;
- break;
- }
- }
-
- if(ivp) {
- tot= (int) (floor(*(iv->data[0])+0.5) * floor(*(iv->data[1])+0.5));
-
- if(tot>0) {
- dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor8");
- BLI_addtail(listb, dl);
- dl->type= DL_SURF;
- dl->parts= (int) floor(*(iv->data[0])+0.5);
- dl->nr= (int) floor(*(iv->data[1])+0.5);
- dl->col= colnr;
- data= (float *)(dl+1);
- memcpy(data, ivp->data[0], tot*3*sizeof(float));
- }
- }
- }
- else if(strcmp(iv->nodename, "IndexedNurbsSurface")==0 || strcmp(iv->nodename, "NurbsSurface")==0) {
-
- colnr= iv_colornumber(iv);
-
- /* sek back to data */
- ivp= iv;
- while(ivp->prev) {
- ivp= ivp->prev;
- if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
- coordtype= 3;
- break;
- }
- if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
- coordtype= 4;
- break;
- }
- }
- if(ivp) {
- a= (int) *(iv->data[0]);
- b= (int) *(iv->data[1]);
-
- tot= a*b;
-
- if( (a>=4 || b>=4) && tot>6) {
- Object *ob;
- Curve *cu;
- Nurb *nu;
- BPoint *bp;
-
- if(ivsurf==0) {
- ob= add_object(scene, OB_SURF);
- ivsurf= ob;
- }
- else ob= ivsurf;
- cu= ob->data;
- nu = (Nurb*) MEM_callocN(sizeof(Nurb),"addNurbprim") ;
- BLI_addtail(&cu->nurb, nu);
- nu->type= CU_NURBS;
-
- nu->pntsu= a;
- nu->pntsv= b;
- nu->resolu= 2*a;
- nu->resolv= 2*b;
-
- nu->flagu= 0;
- nu->flagv= 0;
-
- nu->bp = bp =
- (BPoint*)MEM_callocN(tot * sizeof(BPoint), "addNurbprim3");
- a= tot;
- data= ivp->data[0];
- while(a--) {
- VECCOPY(bp->vec, data);
- if(coordtype==4) {
- bp->vec[3]= data[3];
- mul_v3_fl(bp->vec, 1.0f/data[3]);
- }
- else bp->vec[3]= 1.0;
- data+= coordtype;
- bp++;
- }
-
- /* iv->datalen[2] / [3] is number of knots */
- nu->orderu= iv->datalen[2] - nu->pntsu;
- nu->orderv= iv->datalen[3] - nu->pntsv;
-
- nu->knotsu= MEM_mallocN( sizeof(float)*(iv->datalen[2]), "knots");
- memcpy(nu->knotsu, iv->data[2], sizeof(float)*(iv->datalen[2]));
- nu->knotsv= MEM_mallocN( sizeof(float)*(iv->datalen[3]), "knots");
- memcpy(nu->knotsv, iv->data[3], sizeof(float)*(iv->datalen[3]));
-
- switchdirectionNurb(nu);
-
- }
- else {
- dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor3");
- BLI_addtail(listb, dl);
- dl->type= DL_SURF;
- dl->nr= (int) *(iv->data[0]);
- dl->parts= (int) *(iv->data[1]);
- dl->col= colnr;
- data= (float *)(dl+1);
-
- a= tot;
- fp= ivp->data[0];
- while(a--) {
- VECCOPY(data, fp);
- fp+= coordtype;
- data+= 3;
- }
- }
- }
- }
- iv= iv->next;
- }
-
- /* free */
- iv= ivbase.first;
- while(iv) {
- for(a=0; a<IV_MAXFIELD; a++) {
- if(iv->data[a]) MEM_freeN(iv->data[a]);
- }
- iv= iv->next;
- }
-
- BLI_freelistN(&ivbase);
- MEM_freeN(maindata);
- MEM_freeN(iv_data_stack);
-
-}
-
/* ************************************************************ */
-static void displist_to_mesh(Scene *scene, DispList *dlfirst)
-{
- Object *ob;
- Mesh *me;
- Material *ma;
- DispList *dl;
- MVert *mvert;
- MFace *mface;
- float *data, vec[3], min[3], max[3];
- int a, b, startve, *idata, totedge=0, tottria=0, totquad=0, totvert=0, totface, totcol=0, colnr;
- int p1, p2, p3, p4;
- unsigned int maxvertidx;
-
- /* count first */
- INIT_MINMAX(min, max);
-
- dl= dlfirst;
- while(dl) {
-
- /* PATCH 1 (polyfill) can't be done, there's no listbase here. do that first! */
- /* PATCH 2 */
- if(dl->type==DL_SEGM && dl->nr>2) {
- data= (float *)(dl+1);
- if(data[0]==data[3*(dl->nr-1)]) {
- if(data[1]==data[3*(dl->nr-1)+1]) {
- if(data[2]==data[3*(dl->nr-1)+2]) {
- dl->type= DL_POLY;
- dl->nr--;
- }
- }
- }
- }
-
- /* colors */
- if(dl->col > totcol) totcol= dl->col;
-
- /* size and count */
- if(dl->type==DL_SURF) {
- a= dl->nr;
- b= dl->parts;
- if(dl->flag & DL_CYCL_U) a++;
- if(dl->flag & DL_CYCL_V) b++;
-
- totquad+= a*b;
-
- totvert+= dl->nr*dl->parts;
-
- data= (float *)(dl+1);
- for(a= dl->nr*dl->parts; a>0; a--) {
- DO_MINMAX(data, min, max);
- data+= 3;
- }
- }
- else if(dl->type==DL_POLY) {
- if(dl->nr==3 || dl->nr==4) {
- if(dl->nr==3) tottria+= dl->parts;
- else totquad+= dl->parts;
-
- totvert+= dl->nr*dl->parts;
-
- data= (float *)(dl+1);
- for(a= dl->nr*dl->parts; a>0; a--) {
- DO_MINMAX(data, min, max);
- data+= 3;
- }
- }
- else if(dl->nr>4) {
-
- tottria+= dl->nr*dl->parts;
- totvert+= dl->nr*dl->parts;
-
- data= (float *)(dl+1);
- for(a= dl->nr*dl->parts; a>0; a--) {
- DO_MINMAX(data, min, max);
- data+= 3;
- }
-
- }
- }
- else if(dl->type==DL_INDEX3) {
- tottria+= dl->parts;
- totvert+= dl->nr;
-
- data= dl->verts;
- for(a= dl->nr; a>0; a--) {
- DO_MINMAX(data, min, max);
- data+= 3;
- }
- }
- else if(dl->type==DL_SEGM) {
-
- tottria+= (dl->nr-1)*dl->parts;
- totvert+= dl->nr*dl->parts;
-
- data= (float *)(dl+1);
- for(a= dl->nr*dl->parts; a>0; a--) {
- DO_MINMAX(data, min, max);
- data+= 3;
- }
- }
-
- dl= dl->next;
- }
-
- if(totvert==0) {
- return;
- }
-
- vec[0]= (min[0]+max[0])/2;
- vec[1]= (min[1]+max[1])/2;
- vec[2]= (min[2]+max[2])/2;
-
- ob= add_object(scene, OB_MESH);
- VECCOPY(ob->loc, vec);
- where_is_object(scene, ob);
-
- me= ob->data;
-
- /* colors */
- if(totcol) {
- ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
- ob->matbits= MEM_callocN(sizeof(char)*totcol, "ob->matbits");
- me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
- me->totcol= totcol;
- ob->totcol= (unsigned char) me->totcol;
- ob->actcol= 1;
- }
-
- /* materials */
- for(a=0; a<totcol; a++) {
- ma= G.main->mat.first;
- while(ma) {
- if(ma->mtex[0]==0) {
- if(ivcolors[a][0]==ma->r && ivcolors[a][1]==ma->g && ivcolors[a][2]==ma->b) {
- me->mat[a]= ma;
- ma->id.us++;
- break;
- }
- }
- ma= ma->id.next;
- }
- if(ma==0) {
- ma= add_material("ext");
- me->mat[a]= ma;
- ma->r= ivcolors[a][0];
- ma->g= ivcolors[a][1];
- ma->b= ivcolors[a][2];
- automatname(ma);
- }
- }
-
- totface= totquad+tottria+totedge;
-
- printf("Import: %d vertices %d faces\n", totvert, totface);
-
- me->totvert= totvert;
- me->totface= totface;
- me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC,
- NULL, me->totvert);
- me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC,
- NULL, me->totface);
- maxvertidx= totvert-1;
-
- mvert= me->mvert;
- mface= me->mface;
-
- startve= 0;
-
- dl= dlfirst;
- while(dl) {
-
- colnr= dl->col;
- if(colnr) colnr--;
-
- if(dl->type==DL_SURF) {
- data= (float *)(dl+1);
-
- for(a=dl->parts*dl->nr; a>0; a--) {
- mvert->co[0]= data[0] -vec[0];
- mvert->co[1]= data[1] -vec[1];
- mvert->co[2]= data[2] -vec[2];
-
- data+=3;
- mvert++;
- }
-
- for(a=0; a<dl->parts; a++) {
-
- if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
- break;
-
- p1+= startve;
- p2+= startve;
- p3+= startve;
- p4+= startve;
-
- for(; b<dl->nr; b++) {
-
- mface->v1= p1;
- mface->v2= p2;
- mface->v3= p4;
- mface->v4= p3;
-
- mface->mat_nr= colnr;
- test_index_face(mface, NULL, 0, 4);
-
- mface++;
-
- p4= p3;
- p3++;
- p2= p1;
- p1++;
- }
- }
-
- startve += dl->parts*dl->nr;
-
- }
- else if(dl->type==DL_POLY) {
-
- if(dl->nr==3 || dl->nr==4) {
- data= (float *)(dl+1);
-
- for(a=dl->parts*dl->nr; a>0; a--) {
- mvert->co[0]= data[0] -vec[0];
- mvert->co[1]= data[1] -vec[1];
- mvert->co[2]= data[2] -vec[2];
- data+=3;
- mvert++;
- }
-
- for(a=0; a<dl->parts; a++) {
- if(dl->nr==3) {
- mface->v1= startve+a*dl->nr;
- mface->v2= startve+a*dl->nr+1;
- mface->v3= startve+a*dl->nr+2;
- mface->mat_nr= colnr;
- test_index_face(mface, NULL, 0, 3);
- mface++;
- }
- else {
- mface->v1= startve+a*dl->nr;
- mface->v2= startve+a*dl->nr+1;
- mface->v3= startve+a*dl->nr+2;
- mface->v4= startve+a*dl->nr+3;
- mface->mat_nr= colnr;
- test_index_face(mface, NULL, 0, 4);
- mface++;
- }
- }
- startve += dl->parts*dl->nr;
- }
- else if(dl->nr>4) {
- data= (float *)(dl+1);
-
- for(a=dl->parts*dl->nr; a>0; a--) {
- mvert->co[0]= data[0] -vec[0];
- mvert->co[1]= data[1] -vec[1];
- mvert->co[2]= data[2] -vec[2];
-
- data+=3;
- mvert++;
- }
-
- for(b=0; b<dl->parts; b++) {
- for(a=0; a<dl->nr; a++) {
- mface->v1= startve+a;
-
- if(a==dl->nr-1) mface->v2= startve;
- else mface->v2= startve+a+1;
-
- mface->mat_nr= colnr;
-
- mface++;
- }
- startve += dl->nr;
- }
- }
- }
- else if(dl->type==DL_INDEX3) {
- data= dl->verts;
-
- for(a=dl->nr; a>0; a--) {
- mvert->co[0]= data[0] -vec[0];
- mvert->co[1]= data[1] -vec[1];
- mvert->co[2]= data[2] -vec[2];
- data+=3;
- mvert++;
- }
-
- idata= dl->index;
- for(b=dl->parts; b>0; b--) {
- mface->v1= startve+idata[0];
- mface->v2= startve+idata[1];
- mface->v3= startve+idata[2];
- mface->mat_nr= colnr;
-
- if (mface->v1>maxvertidx) mface->v1= maxvertidx;
- if (mface->v2>maxvertidx) mface->v2= maxvertidx;
- if (mface->v3>maxvertidx) mface->v3= maxvertidx;
-
- test_index_face(mface, NULL, 0, 3);
- mface++;
- idata+= 3;
- }
- startve += dl->nr;
- }
- else if(dl->type==DL_SEGM) {
- data= (float *)(dl+1);
-
- for(a=dl->parts*dl->nr; a>0; a--) {
- mvert->co[0]= data[0] -vec[0];
- mvert->co[1]= data[1] -vec[1];
- mvert->co[2]= data[2] -vec[2];
- data+=3;
- mvert++;
- }
-
- for(b=0; b<dl->parts; b++) {
- for(a=0; a<dl->nr-1; a++) {
- mface->v1= startve+a;
- mface->v2= startve+a+1;
- mface->mat_nr= colnr;
- mface++;
- }
- startve += dl->nr;
- }
- }
- dl= dl->next;
- }
-
- mesh_add_normals_flags(me);
- make_edges(me, 0);
-}
-
-static void displist_to_objects(Scene *scene, ListBase *lbase)
-{
- DispList *dl, *first, *prev, *next;
- ListBase tempbase;
- int maxaantal, curcol, totvert=0, vert;
-
- /* irst this: is still active */
- if(ivsurf) {
- where_is_object(scene, ivsurf);
-// XXX docenter_new();
- }
-
- dl= lbase->first;
- while(dl) {
- next= dl->next;
-
- /* PATCH 1: polyfill */
- if(dl->type==DL_POLY && dl->nr>4) {
- /* solution: put them together in separate listbase */
- ;
- }
- /* PATCH 2: poly's of 2 points */
- if(dl->type==DL_POLY && dl->nr==2) dl->type= DL_SEGM;
-
- dl= next;
- }
-
- /* count vertices */
-
- dl= lbase->first;
- while(dl) {
-
- if(dl->type==DL_SURF) totvert+= dl->nr*dl->parts;
- else if(dl->type==DL_POLY) {
- if(dl->nr==3 || dl->nr==4) totvert+= dl->nr*dl->parts;
- else if(dl->nr>4) totvert+= dl->nr*dl->parts;
- }
- else if(dl->type==DL_INDEX3) totvert+= dl->nr;
- else if(dl->type==DL_SEGM) totvert+= dl->nr*dl->parts;
-
- dl= dl->next;
- }
-
- if(totvert==0) {
-
- if(ivsurf==0) {}; //XXX error("Found no data");
- if(lbase->first) BLI_freelistN(lbase);
-
- return;
- }
-
- maxaantal= 32000;
-
- if(totvert>maxaantal) {
-
- /* try to put colors together */
- curcol= 0;
- tempbase.first= tempbase.last= 0;
-
- while(lbase->first) {
- dl= lbase->first;
- while(dl) {
- next= dl->next;
- if(dl->col==curcol) {
- BLI_remlink(lbase, dl);
- BLI_addtail(&tempbase, dl);
- dl->col= 0;
- }
-
- dl= next;
- }
-
- /* in tempbase are all 'curcol' */
- totvert= 0;
- dl= first= tempbase.first;
- while(dl) {
- vert= 0;
-
- if(dl->type==DL_SURF) vert= dl->nr*dl->parts;
- else if(dl->type==DL_POLY) {
- if(dl->nr==3 || dl->nr==4) vert= dl->nr*dl->parts;
- else if(dl->nr>4) vert= dl->nr*dl->parts;
- }
- else if(dl->type==DL_INDEX3) totvert+= dl->nr;
- else if(dl->type==DL_SEGM) vert= dl->nr*dl->parts;
-
- totvert+= vert;
- if(totvert > maxaantal || dl->next==0) {
- if(dl->next==0) {
- displist_to_mesh(scene, first);
- }
- else if(dl->prev) {
- prev= dl->prev;
- prev->next= 0;
- displist_to_mesh(scene, first);
- prev->next= dl;
- first= dl;
- totvert= 0;
- }
- }
-
- dl= dl->next;
- }
-
- freedisplist(&tempbase);
-
- curcol++;
- }
- }
- else displist_to_mesh(scene, lbase->first);
-
- freedisplist(lbase);
-
-}
-
-int BKE_read_exotic(Scene *scene, char *name)
+int BKE_read_exotic(Scene *scene, const char *name)
{
- ListBase lbase={0, 0};
int len;
gzFile gzfile;
- char str[32];
- int *s0 = (int*) str;
- int retval = 0;
+ char header[7];
+ int retval;
// make sure we're not trying to read a directory....
len= strlen(name);
- if (name[len-1] !='/' && name[len-1] != '\\') {
+ if (ELEM(name[len-1], '/', '\\')) {
+ retval= BKE_READ_EXOTIC_FAIL_PATH;
+ }
+ else {
gzfile = gzopen(name,"rb");
- if (NULL == gzfile ) {
- //XXX error("Can't open file: %s", name);
- retval= -1;
- } else {
- gzread(gzfile, str, 31);
+ if (gzfile == NULL) {
+ retval= BKE_READ_EXOTIC_FAIL_OPEN;
+ }
+ else {
+ len= gzread(gzfile, header, sizeof(header));
gzclose(gzfile);
-
- if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) {
-
+ if (len == sizeof(header) && strncmp(header, "BLENDER", 7) == 0) {
+ retval= BKE_READ_EXOTIC_OK_BLEND;
+ }
+ else {
//XXX waitcursor(1);
- if(strncmp(str, "#Inventor V1.0", 14)==0) {
- if( strncmp(str+15, "ascii", 5)==0) {
- read_inventor(scene, name, &lbase);
- displist_to_objects(scene, &lbase);
- retval = 1;
- } else {
- //XXX error("Can only read Inventor 1.0 ascii");
- }
- }
- else if((strncmp(str, "#VRML V1.0 asc", 14)==0)) {
- read_inventor(scene, name, &lbase);
- displist_to_objects(scene, &lbase);
- retval = 1;
- }
- else if(is_dxf(name)) {
+ if(is_dxf(name)) {
dxf_read(scene, name);
- retval = 1;
+ retval= BKE_READ_EXOTIC_OK_OTHER;
}
else if(is_stl(name)) {
if (is_stl_ascii(name))
read_stl_mesh_ascii(scene, name);
else
read_stl_mesh_binary(scene, name);
- retval = 1;
+ retval= BKE_READ_EXOTIC_OK_OTHER;
}
-#ifndef DISABLE_PYTHON
- // TODO: this should not be in the kernel...
- else { // unknown format, call Python importloader
- if (BPY_call_importloader(name)) {
- retval = 1;
- } else {
- //XXX error("Unknown file type or error, check console");
- }
-
+ else {
+ retval= BKE_READ_EXOTIC_FAIL_FORMAT;
}
-#endif /* DISABLE_PYTHON */
//XXX waitcursor(0);
}
}
}
- return (retval);
+ return retval;
}
/* ************************ WRITE ************************** */
-
-char temp_dir[160]= {0, 0};
-
static void write_vert_stl(Object *ob, MVert *verts, int index, FILE *fpSTL)
{
float vert[3];
@@ -1887,7 +559,7 @@ static int write_derivedmesh_stl(FILE *fpSTL, Object *ob, DerivedMesh *dm)
return numfacets;
}
-static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob, Mesh *me)
+static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob)
{
int numfacets = 0;
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
@@ -1902,20 +574,12 @@ static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob, Mesh *me)
void write_stl(Scene *scene, char *str)
{
Object *ob;
- Mesh *me;
Base *base;
FILE *fpSTL;
int numfacets = 0;
ReportList *reports= NULL; /* XXX */
-
- if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
- if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
- if(BLI_testextensie(str,".stl")==0) strcat(str, ".stl");
- if (BLI_exists(str)) {
- ; //XXX if(saveover(str)==0)
- //XXX return;
- }
+ /* XXX, operator needs to manage filename extension */
fpSTL= fopen(str, "wb");
@@ -1923,7 +587,6 @@ void write_stl(Scene *scene, char *str)
BKE_reportf(reports, RPT_ERROR, "Can't open file: %s.", strerror(errno));
return;
}
- strcpy(temp_dir, str);
//XXX waitcursor(1);
@@ -1942,9 +605,8 @@ void write_stl(Scene *scene, char *str)
if (base->flag & SELECT) {
ob = base->object;
if (ob->type == OB_MESH) {
- me = ob->data;
- if (me)
- numfacets += write_object_stl(fpSTL, scene, ob, me);
+ if(ob->data)
+ numfacets += write_object_stl(fpSTL, scene, ob);
}
}
base= base->next;
@@ -1965,7 +627,6 @@ void write_stl(Scene *scene, char *str)
//XXX waitcursor(0);
}
-/* ******************************* WRITE VRML ***************************** */
static void replace_chars(char *str1, char *str2)
{
@@ -1978,354 +639,6 @@ static void replace_chars(char *str1, char *str2)
}
}
-
-static void write_material_vrml(FILE *fp, Material *ma)
-{
- char str[32];
-
- replace_chars(str, ma->id.name+2);
-
- fprintf(fp, "\tDEF %s\n", str);
- fprintf(fp, "\tMaterial {\n");
-
- fprintf(fp, "\t\tdiffuseColor %f %f %f\n", ma->r, ma->g, ma->b);
- fprintf(fp, "\t\tspecularColor %f %f %f\n", ma->specr, ma->specg, ma->specb);
- fprintf(fp, "\t\tshininess %f \n", ((float)ma->har)/100.0);
- fprintf(fp, "\t\ttransparency %f \n", 1.0-ma->alpha);
-
- fprintf(fp, "\t}\n");
-
-}
-
-unsigned int *mcol_to_vcol(Mesh *me)
-{
- MFace *mface;
- unsigned int *mcol, *mcoln, *mcolmain;
- int a;
-
- if(me->totface==0 || me->mcol==0) return 0;
-
- mcoln= mcolmain= MEM_mallocN(sizeof(int)*me->totvert, "mcoln");
- mcol = (unsigned int *)me->mcol;
- mface= me->mface;
-
- for(a=me->totface; a>0; a--, mface++) {
- mcoln[mface->v1]= mcol[0];
- mcoln[mface->v2]= mcol[1];
- mcoln[mface->v3]= mcol[2];
- if(mface->v4) mcoln[mface->v4]= mcol[3];
-
- mcol+= 4;
- }
-
- return mcolmain;
-}
-
-void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a)
-{
- char *cp;
-
- cp = (char *)&col;
-
- *r= cp[3];
- *r /= 255.0;
-
- *g= cp[2];
- *g /= 255.0;
-
- *b= cp[1];
- *b /= 255.0;
-
- *a= cp[0];
- *a /= 255.0;
-}
-
-static void write_mesh_vrml(FILE *fp, Mesh *me)
-{
- Material *ma;
- MVert *mvert;
- MFace *mface;
- MTFace *tface;
- Image *ima;
- int a, b, totcol, texind;
- char str[32];
-
- replace_chars(str, me->id.name+2);
-
- fprintf(fp, "\tDEF %s\n", str);
- fprintf(fp, "\tSeparator {\n");
-
- if(me->mtface) {
- ima= ((MTFace *)me->mtface)->tpage;
- if(ima) {
- fprintf(fp, "\t\tTexture2 {\n");
- fprintf(fp, "\t\t\tfilename %s\n", ima->name);
- fprintf(fp, "\t\t\twrapS REPEAT \n");
- fprintf(fp, "\t\t\twrapT REPEAT \n");
- fprintf(fp, "\t\t}\n");
- }
- }
-
- if(me->mcol) {
- unsigned int *mcol, *mcolmain;
- float r, g, b, cola;
-
- fprintf(fp, "\t\tMaterial {\n");
- fprintf(fp, "\t\t\tdiffuseColor [\n");
-
- a= me->totvert;
- mcol= mcolmain= mcol_to_vcol(me);
- if(mcol) {
- while(a--) {
- mcol_to_rgba(*mcol, &r, &g, &b, &cola);
- fprintf(fp, "\t\t\t\t %f %f %f,\n", r, g, b);
- mcol++;
- }
- MEM_freeN(mcolmain);
- }
- fprintf(fp, "\t\t\t]\n");
- fprintf(fp, "\t\t}\n");
-
- fprintf(fp, "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n");
- }
-
-
- fprintf(fp, "\t\tCoordinate3 {\n");
- fprintf(fp, "\t\t\tpoint [\n");
-
- a= me->totvert;
- mvert= me->mvert;
- while(a--) {
- fprintf(fp, "\t\t\t\t %f %f %f,\n", mvert->co[0], mvert->co[1], mvert->co[2]);
- mvert++;
- }
- fprintf(fp, "\t\t\t]\n");
- fprintf(fp, "\t\t}\n");
-
-
- totcol= me->totcol;
- if(totcol==0) totcol= 1;
- texind= 0; // index for uv coords
-
- for(b=0; b<totcol; b++) {
-
- if(me->mcol==0) {
- if(me->mat) {
- ma= me->mat[b];
- if(ma) {
- replace_chars(str, ma->id.name+2);
-
- fprintf(fp, "\t\tUSE %s\n\n", str);
- }
- }
- }
-
- if(me->mtface) {
- fprintf(fp, "\t\tTextureCoordinate2 {\n");
- fprintf(fp, "\t\t\tpoint [\n");
-
- a= me->totface;
- mface= me->mface;
- tface= me->mtface;
- while(a--) {
- if(mface->mat_nr==b) {
- fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[0][0], tface->uv[0][1]);
- fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[1][0], tface->uv[1][1]);
- fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[2][0], tface->uv[2][1]);
- if(mface->v4) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[3][0], tface->uv[3][1]);
- }
- mface++;
- tface++;
- }
- fprintf(fp, "\t\t\t]\n");
- fprintf(fp, "\t\t}\n");
- }
-
- fprintf(fp, "\t\tIndexedFaceSet {\n");
- fprintf(fp, "\t\t\tcoordIndex [\n");
-
- a= me->totface;
- mface= me->mface;
- while(a--) {
- if(mface->mat_nr==b) {
- if(mface->v4) fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3, mface->v4);
- else fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3);
- }
- mface++;
- }
- fprintf(fp, "\t\t\t]\n");
-
- if(me->mtface) {
- fprintf(fp, "\t\t\ttextureCoordIndex [\n");
-
- a= me->totface;
- mface= me->mface;
- while(a--) {
- if(mface->mat_nr==b) {
- if(mface->v4) {
- fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", texind, texind+1, texind+2, texind+3);
- texind+= 4;
- }
- else {
- fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", texind, texind+1, texind+2);
- texind+= 3;
- }
- }
- mface++;
- }
- fprintf(fp, "\t\t\t]\n");
- }
- fprintf(fp, "\t\t}\n");
- }
-
- fprintf(fp, "\t}\n");
-}
-
-static void write_camera_vrml(FILE *fp, Object *ob)
-{
- Camera *cam;
-
- if(ob==0) return;
- invert_m4_m4(ob->imat, ob->obmat);
-
- fprintf(fp, "\tMatrixTransform {\n");
-
- fprintf(fp, "\tmatrix \n");
-
- fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[0][0], ob->imat[0][1], ob->imat[0][2], ob->imat[0][3]);
- fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[1][0], ob->imat[1][1], ob->imat[1][2], ob->imat[1][3]);
- fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[2][0], ob->imat[2][1], ob->imat[2][2], ob->imat[2][3]);
- fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[3][0], ob->imat[3][1], ob->imat[3][2], ob->imat[3][3]);
-
- fprintf(fp, "\t}\n");
-
- cam= ob->data;
-
- fprintf(fp, "\tPerspectiveCamera {\n");
- fprintf(fp, "\t\tfocalDistance %f\n", cam->lens/10.0);
-
- fprintf(fp, "\t}\n");
-
-}
-
-static void write_object_vrml(FILE *fp, Object *ob)
-{
- ID *id;
- char str[32];
-
- fprintf(fp, "\tSeparator {\n");
- fprintf(fp, "\t\tMatrixTransform {\n");
-
- fprintf(fp, "\t\tmatrix \n");
-
- fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[0][0], ob->obmat[0][1], ob->obmat[0][2], ob->obmat[0][3]);
- fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[1][0], ob->obmat[1][1], ob->obmat[1][2], ob->obmat[1][3]);
- fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[2][0], ob->obmat[2][1], ob->obmat[2][2], ob->obmat[2][3]);
- fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2], ob->obmat[3][3]);
-
- fprintf(fp, "\t\t}\n");
-
- id= ob->data;
-
- replace_chars(str, id->name+2);
-
- fprintf(fp, "\t\tUSE %s\n", str);
- fprintf(fp, "\t}\n");
-}
-
-
-void write_vrml(Scene *scene, char *str)
-{
- Mesh *me;
- Material *ma;
- Base *base;
- FILE *fp;
-
- if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
- if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
- if(BLI_testextensie(str,".wrl")==0) strcat(str, ".wrl");
- //XXX saveover() if(saveover(str)==0) return;
-
- fp= fopen(str, "w");
-
- if(fp==NULL) {
- //XXX error("Can't write file");
- return;
- }
- strcpy(temp_dir, str);
-
- //XXX waitcursor(1);
-
- /* FIRST: write all the datablocks */
-
- fprintf(fp, "#VRML V1.0 ascii\n\n# Blender V%d\n\n# 'Switch' is used as a hack, to ensure it is not part of the drawing\n\n", BLENDER_VERSION);
- fprintf(fp, "Separator {\n");
- fprintf(fp, "Switch {\n");
-
- ma= G.main->mat.first;
- while(ma) {
- if(ma->id.us) {
- write_material_vrml(fp, ma);
- }
- ma= ma->id.next;
- }
-
- /* only write meshes we're using in this scene */
- flag_listbase_ids(&G.main->mesh, LIB_DOIT, 0);
-
- for(base= scene->base.first; base; base= base->next)
- if(base->object->type== OB_MESH)
- ((ID *)base->object->data)->flag |= LIB_DOIT;
-
- me= G.main->mesh.first;
- while(me) {
- if(me->id.flag & LIB_DOIT) { /* is the mesh used in this scene ? */
- write_mesh_vrml(fp, me);
- }
- me= me->id.next;
- }
-
- /* THEN:Hidden Objects */
- fprintf(fp, "\n\t# Hidden Objects, in invisible layers\n\n");
- base= scene->base.first;
- while(base) {
- if(base->object->type== OB_MESH) {
- if( (base->lay & scene->lay)==0 ) {
- write_object_vrml(fp, base->object);
- }
- }
- base= base->next;
- }
-
- fprintf(fp, "}\n");
- fprintf(fp, "\n# Visible Objects\n\n");
- fprintf(fp, "Separator {\n");
-
- /* The camera */
-
- write_camera_vrml(fp, scene->camera);
-
- /* THEN:The Objects */
-
- base= scene->base.first;
- while(base) {
- if(base->object->type== OB_MESH) {
- if(base->lay & scene->lay) {
- write_object_vrml(fp, base->object);
- }
- }
- base= base->next;
- }
-
- fprintf(fp, "}\n");
- fprintf(fp, "}\n");
-
- fclose(fp);
-
- //XXX waitcursor(0);
-}
-
-
/* ******************************* WRITE DXF ***************************** */
#define write_group(id,data) fprintf(fp, "%d\n%s\n", id, data)
@@ -2551,15 +864,7 @@ void write_dxf(struct Scene *scene, char *str)
Base *base;
FILE *fp;
- if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
- if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
- if(BLI_testextensie(str,".dxf")==0) strcat(str, ".dxf");
-
-
- if (BLI_exists(str)) {
- ; //XXX if(saveover(str)==0)
- // return;
- }
+ /* XXX, operator needs to handle overwrite & rename */
fp= fopen(str, "w");
@@ -2567,7 +872,6 @@ void write_dxf(struct Scene *scene, char *str)
//XXX error("Can't write file");
return;
}
- strcpy(temp_dir, str);
//XXX waitcursor(1);
@@ -2672,7 +976,7 @@ static int all_digits(char *str)
return 1;
}
-static int dxf_get_layer_col(char *layer)
+static int dxf_get_layer_col(char *UNUSED(layer))
{
return 1;
}
@@ -2710,8 +1014,8 @@ static void myfgets(char *str, int len, FILE *fp)
/* three types of enters, \n \r and \r\n */
if(c == '\n') break;
if(c=='\r') {
- c= getc(dxf_fp); // read the linefeed from stream
- if(c != 10) ungetc(c, dxf_fp); // put back, if it's not one...
+ c= getc(fp); // read the linefeed from stream
+ if(c != 10) ungetc(c, fp); // put back, if it's not one...
break;
}
}
@@ -2764,7 +1068,7 @@ static char val[256];
static short error_exit=0;
static short hasbumped=0;
-static int is_dxf(char *str)
+static int is_dxf(const char *str)
{
dxf_line=0;
@@ -2827,7 +1131,7 @@ static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer)
ma= G.main->mat.first;
while(ma) {
- if(ma->mtex[0]==0) {
+ if(ma->mtex[0]==NULL) {
if(color[0]==ma->r && color[1]==ma->g && color[2]==ma->b) {
me->mat[0]= ma;
ma->id.us++;
@@ -2836,7 +1140,7 @@ static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer)
}
ma= ma->id.next;
}
- if(ma==0) {
+ if(ma==NULL) {
ma= add_material("ext");
me->mat[0]= ma;
ma->r= color[0];
@@ -2866,10 +1170,10 @@ static void dxf_get_mesh(Scene *scene, Mesh** m, Object** o, int noob)
*o = add_object(scene, OB_MESH);
ob = *o;
- if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
- else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+ if (entname[0]) new_id(&G.main->object, (ID *)ob, entname);
+ else if (layname[0]) new_id(&G.main->object, (ID *)ob, layname);
- if (strlen(layname)) ob->lay= dxf_get_layer_num(scene, layname);
+ if (layname[0]) ob->lay= dxf_get_layer_num(scene, layname);
else ob->lay= scene->lay;
// not nice i know... but add_object() sets active base, which needs layer setting too (ton)
scene->basact->lay= ob->lay;
@@ -2888,8 +1192,8 @@ static void dxf_get_mesh(Scene *scene, Mesh** m, Object** o, int noob)
((ID *)me)->us=0;
- if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
- else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+ if (entname[0]) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (layname[0]) new_id(&G.main->mesh, (ID *)me, layname);
vcenter = zerovec;
}
@@ -3345,7 +1649,7 @@ static void dxf_read_arc(Scene *scene, int noob)
cent[2]= center[2];
dxf_get_mesh(scene, &me, &ob, noob);
- strcpy(oldllay, layname);
+ BLI_strncpy(oldllay, layname, sizeof(oldllay));
if(ob) VECCOPY(ob->loc, cent);
dxf_add_mat (ob, me, color, layname);
@@ -3902,7 +2206,7 @@ static void dxf_read_3dface(Scene *scene, int noob)
hasbumped=1;
}
-static void dxf_read(Scene *scene, char *filename)
+static void dxf_read(Scene *scene, const char *filename)
{
Mesh *lastMe = G.main->mesh.last;
@@ -4071,7 +2375,7 @@ static void dxf_read(Scene *scene, char *filename)
ob->dupon= 1; ob->dupoff= 0;
ob->dupsta= 1; ob->dupend= 100;
- ob->recalc= OB_RECALC_ALL; /* needed because of weird way of adding libdata directly */
+ ob->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; /* needed because of weird way of adding libdata directly */
ob->data= obdata;
((ID*)ob->data)->us++;
@@ -4090,7 +2394,7 @@ static void dxf_read(Scene *scene, char *filename)
I leave it commented out here as warning (ton) */
//for (i=0; i<ob->totcol; i++) ob->mat[i]= ((Mesh*)ob->data)->mat[i];
- if (strlen(layname)) ob->lay= dxf_get_layer_num(scene, layname);
+ if (layname[0]) ob->lay= dxf_get_layer_num(scene, layname);
else ob->lay= scene->lay;
/* link to scene */
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 43f01199b69..b50943ba9f1 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -41,6 +41,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_fcurve.h"
#include "BKE_animsys.h"
@@ -53,7 +54,7 @@
#include "RNA_access.h"
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -163,10 +164,10 @@ void copy_fcurves (ListBase *dst, ListBase *src)
}
}
-/* --------------------- Finding -------------------------- */
+/* ----------------- Finding F-Curves -------------------------- */
/* high level function to get an fcurve from C without having the rna */
-FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, char *prop_name, int index)
+FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index)
{
/* anim vars */
AnimData *adt= BKE_animdata_from_id(id);
@@ -220,7 +221,7 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array
for (fcu= list->first; fcu; fcu= fcu->next) {
/* simple string-compare (this assumes that they have the same root...) */
if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) {
- /* now check indicies */
+ /* now check indices */
if (fcu->array_index == array_index)
return fcu;
}
@@ -298,36 +299,36 @@ int list_find_data_fcurves (ListBase *dst, ListBase *src, const char *dataPrefix
return matches;
}
-FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, int *driven)
+FCurve *rna_get_fcurve (PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, int *driven)
{
FCurve *fcu= NULL;
*driven= 0;
/* there must be some RNA-pointer + property combon */
- if(prop && ptr->id.data && RNA_property_animateable(ptr, prop)) {
+ if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) {
AnimData *adt= BKE_animdata_from_id(ptr->id.data);
char *path;
- if(adt) {
- if((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
+ if (adt) {
+ if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
/* XXX this function call can become a performance bottleneck */
path= RNA_path_from_ID_to_property(ptr, prop);
- if(path) {
+ if (path) {
/* animation takes priority over drivers */
- if(adt->action && adt->action->curves.first)
+ if (adt->action && adt->action->curves.first)
fcu= list_find_fcurve(&adt->action->curves, path, rnaindex);
/* if not animated, check if driven */
- if(!fcu && (adt->drivers.first)) {
+ if (!fcu && (adt->drivers.first)) {
fcu= list_find_fcurve(&adt->drivers, path, rnaindex);
- if(fcu)
+ if (fcu)
*driven= 1;
}
- if(fcu && action)
+ if (fcu && action)
*action= adt->action;
MEM_freeN(path);
@@ -339,6 +340,8 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction
return fcu;
}
+/* ----------------- Finding Keyframes/Extents -------------------------- */
+
/* threshold for binary-searching keyframes - threshold here should be good enough for now, but should become userpref */
#define BEZT_BINARYSEARCH_THRESH 0.01f /* was 0.00001, but giving errors */
@@ -469,11 +472,7 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
foundvert=1;
}
- /* minimum sizes are 1.0f */
if (foundvert) {
- if (xminv == xmaxv) xmaxv += 1.0f;
- if (yminv == ymaxv) ymaxv += 1.0f;
-
if (xmin) *xmin= xminv;
if (xmax) *xmax= xmaxv;
@@ -481,10 +480,13 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
if (ymax) *ymax= ymaxv;
}
else {
+ if (G.f & G_DEBUG)
+ printf("F-Curve calc bounds didn't find anything, so assuming minimum bounds of 1.0\n");
+
if (xmin) *xmin= 0.0f;
- if (xmax) *xmax= 0.0f;
+ if (xmax) *xmax= 1.0f;
- if (ymin) *ymin= 1.0f;
+ if (ymin) *ymin= 0.0f;
if (ymax) *ymax= 1.0f;
}
}
@@ -520,6 +522,87 @@ void calc_fcurve_range (FCurve *fcu, float *start, float *end)
}
}
+/* ----------------- Status Checks -------------------------- */
+
+/* Are keyframes on F-Curve of any use?
+ * Usability of keyframes refers to whether they should be displayed,
+ * and also whether they will have any influence on the final result.
+ */
+short fcurve_are_keyframes_usable (FCurve *fcu)
+{
+ /* F-Curve must exist */
+ if (fcu == NULL)
+ return 0;
+
+ /* F-Curve must not have samples - samples are mutually exclusive of keyframes */
+ if (fcu->fpt)
+ return 0;
+
+ /* if it has modifiers, none of these should "drastically" alter the curve */
+ if (fcu->modifiers.first) {
+ FModifier *fcm;
+
+ /* check modifiers from last to first, as last will be more influential */
+ // TODO: optionally, only check modifier if it is the active one...
+ for (fcm = fcu->modifiers.last; fcm; fcm = fcm->prev) {
+ /* ignore if muted/disabled */
+ if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED))
+ continue;
+
+ /* type checks */
+ switch (fcm->type) {
+ /* clearly harmless - do nothing */
+ case FMODIFIER_TYPE_CYCLES:
+ case FMODIFIER_TYPE_STEPPED:
+ case FMODIFIER_TYPE_NOISE:
+ break;
+
+ /* sometimes harmful - depending on whether they're "additive" or not */
+ case FMODIFIER_TYPE_GENERATOR:
+ {
+ FMod_Generator *data = (FMod_Generator *)fcm->data;
+
+ if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
+ return 0;
+ }
+ break;
+ case FMODIFIER_TYPE_FN_GENERATOR:
+ {
+ FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data;
+
+ if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
+ return 0;
+ }
+ break;
+
+ /* always harmful - cannot allow */
+ default:
+ return 0;
+ }
+ }
+ }
+
+ /* keyframes are usable */
+ return 1;
+}
+
+/* Can keyframes be added to F-Curve?
+ * Keyframes can only be added if they are already visible
+ */
+short fcurve_is_keyframable (FCurve *fcu)
+{
+ /* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */
+ if (fcurve_are_keyframes_usable(fcu) == 0)
+ return 0;
+
+ /* F-Curve must currently be editable too */
+ if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) )
+ return 0;
+
+ /* F-Curve is keyframable */
+ return 1;
+}
+
/* ***************************** Keyframe Column Tools ********************************* */
/* add a BezTriple to a column */
@@ -556,7 +639,7 @@ void bezt_add_to_cfra_elem (ListBase *lb, BezTriple *bezt)
/* Basic sampling callback which acts as a wrapper for evaluate_fcurve()
* 'data' arg here is unneeded here...
*/
-float fcurve_samplingcb_evalcurve (FCurve *fcu, void *data, float evaltime)
+float fcurve_samplingcb_evalcurve (FCurve *fcu, void *UNUSED(data), float evaltime)
{
/* assume any interference from drivers on the curve is intended... */
return evaluate_fcurve(fcu, evaltime);
@@ -801,7 +884,7 @@ typedef struct DriverVarTypeInfo {
/* allocation of target slots */
int num_targets; /* number of target slots required */
- char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */
+ const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */
int target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */
} DriverVarTypeInfo;
@@ -851,31 +934,44 @@ static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar)
/* get property to read from, and get value as appropriate */
if (RNA_path_resolve_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) {
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- if (RNA_property_array_length(&ptr, prop))
+ if(RNA_property_array_check(&ptr, prop)) {
+ /* array */
+ if (index < RNA_property_array_length(&ptr, prop)) {
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
value= (float)RNA_property_boolean_get_index(&ptr, prop, index);
- else
- value= (float)RNA_property_boolean_get(&ptr, prop);
+ break;
+ case PROP_INT:
+ value= (float)RNA_property_int_get_index(&ptr, prop, index);
+ break;
+ case PROP_FLOAT:
+ value= RNA_property_float_get_index(&ptr, prop, index);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else {
+ /* not an array */
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ value= (float)RNA_property_boolean_get(&ptr, prop);
break;
case PROP_INT:
- if (RNA_property_array_length(&ptr, prop))
- value= (float)RNA_property_int_get_index(&ptr, prop, index);
- else
- value= (float)RNA_property_int_get(&ptr, prop);
+ value= (float)RNA_property_int_get(&ptr, prop);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(&ptr, prop))
- value= RNA_property_float_get_index(&ptr, prop, index);
- else
- value= RNA_property_float_get(&ptr, prop);
+ value= RNA_property_float_get(&ptr, prop);
break;
case PROP_ENUM:
value= (float)RNA_property_enum_get(&ptr, prop);
break;
default:
break;
+ }
}
+
}
else {
if (G.f & G_DEBUG)
@@ -1106,7 +1202,7 @@ static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar)
/* ......... */
/* Table of Driver Varaiable Type Info Data */
-DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
+static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP)
dvar_eval_singleProp, /* eval callback */
1, /* number of targets used */
@@ -1137,7 +1233,7 @@ DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
};
/* Get driver variable typeinfo */
-DriverVarTypeInfo *get_dvar_typeinfo (int type)
+static DriverVarTypeInfo *get_dvar_typeinfo (int type)
{
/* check if valid type */
if ((type >= 0) && (type < MAX_DVAR_TYPES))
@@ -1174,7 +1270,7 @@ void driver_free_variable (ChannelDriver *driver, DriverVar *dvar)
else
MEM_freeN(dvar);
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
/* since driver variables are cached, the expression needs re-compiling too */
if(driver->type==DRIVER_TYPE_PYTHON)
driver->flag |= DRIVER_FLAG_RENAMEVAR;
@@ -1231,9 +1327,9 @@ DriverVar *driver_add_new_variable (ChannelDriver *driver)
/* set the default type to 'single prop' */
driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP);
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
/* since driver variables are cached, the expression needs re-compiling too */
- if(driver->type==DRIVER_TYPE_PYTHON)
+ if (driver->type==DRIVER_TYPE_PYTHON)
driver->flag |= DRIVER_FLAG_RENAMEVAR;
#endif
@@ -1258,7 +1354,7 @@ void fcurve_free_driver(FCurve *fcu)
driver_free_variable(driver, dvar);
}
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
/* free compiled driver expression */
if (driver->expr_comp)
BPY_DECREF(driver->expr_comp);
@@ -1331,7 +1427,7 @@ float driver_get_variable_value (ChannelDriver *driver, DriverVar *dvar)
* - "evaltime" is the frame at which F-Curve is being evaluated
* - has to return a float value
*/
-static float evaluate_driver (ChannelDriver *driver, float evaltime)
+static float evaluate_driver (ChannelDriver *driver, float UNUSED(evaltime))
{
DriverVar *dvar;
@@ -1406,7 +1502,7 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime)
case DRIVER_TYPE_PYTHON: /* expression */
{
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
/* check for empty or invalid expression */
if ( (driver->expression[0] == '\0') ||
(driver->flag & DRIVER_FLAG_INVALID) )
@@ -1418,9 +1514,9 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime)
/* this evaluates the expression using Python,and returns its result:
* - on errors it reports, then returns 0.0f
*/
- driver->curval= BPY_eval_driver(driver);
+ driver->curval= BPY_driver_exec(driver);
}
-#endif /* DISABLE_PYTHON*/
+#endif /* WITH_PYTHON*/
}
break;
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 834fd09aac2..810c56dbe5d 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -1,6 +1,5 @@
-/**
- * fluidsim.c
- *
+/*
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -28,6 +27,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#include <stddef.h>
#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
#include "MEM_guardedalloc.h"
@@ -42,6 +42,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_customdata.h"
@@ -50,7 +51,7 @@
#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
-#include "BKE_utildefines.h"
+
// headers for fluidsim bobj meshes
#include <stdlib.h>
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 1642fadf33d..804c26295bd 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id: fmodifier.c 21537 2009-07-11 22:22:53Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -38,10 +38,11 @@
#include "BLI_blenlib.h"
#include "BLI_math.h" /* windows needs for M_PI */
+#include "BLI_utildefines.h"
#include "BKE_fcurve.h"
#include "BKE_idprop.h"
-#include "BKE_utildefines.h"
+
#define SMALL -1.0e-10
#define SELECT 1
@@ -146,7 +147,7 @@ static void fcm_generator_verify (FModifier *fcm)
nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs");
if (data->coefficients) {
- if (data->arraysize > (data->poly_order+1))
+ if ((int)data->arraysize > (data->poly_order+1))
memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1));
else
memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
@@ -172,7 +173,7 @@ static void fcm_generator_verify (FModifier *fcm)
nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs");
if (data->coefficients) {
- if (data->arraysize > (data->poly_order * 2))
+ if (data->arraysize > (unsigned int)(data->poly_order * 2))
memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2));
else
memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
@@ -190,7 +191,7 @@ static void fcm_generator_verify (FModifier *fcm)
}
}
-static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+static void fcm_generator_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime)
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
@@ -240,7 +241,7 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
unsigned int i;
/* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */
- for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++)
+ for (cp=data->coefficients, i=0; (cp) && (i < (unsigned int)data->poly_order); cp+=2, i++)
value *= (cp[0]*evaltime + cp[1]);
/* only if something changed, write *cvalue in one go */
@@ -303,7 +304,7 @@ static double sinc (double x)
return sin(M_PI * x) / (M_PI * x);
}
-static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+static void fcm_fn_generator_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime)
{
FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data;
double arg= data->phase_multiplier*evaltime + data->phase_offset;
@@ -432,7 +433,7 @@ static void fcm_envelope_verify (FModifier *fcm)
}
}
-static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+static void fcm_envelope_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime)
{
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
FCM_EnvelopeData *fed, *prevfed, *lastfed;
@@ -524,12 +525,12 @@ static void fcm_cycles_new_data (void *mdata)
data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC;
}
-static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
+static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float UNUSED(cvalue), float evaltime)
{
FMod_Cycles *data= (FMod_Cycles *)fcm->data;
float prevkey[2], lastkey[2], cycyofs=0.0f;
short side=0, mode=0;
- int cycles=0;
+ int cycles=0, ofs=0;
/* check if modifier is first in stack, otherwise disable ourself... */
// FIXME...
@@ -571,6 +572,7 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e
side= -1;
mode= data->before_mode;
cycles= data->before_cycles;
+ ofs= prevkey[0];
}
}
else if (evaltime > lastkey[0]) {
@@ -578,6 +580,7 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e
side= 1;
mode= data->after_mode;
cycles= data->after_cycles;
+ ofs= lastkey[0];
}
}
if ELEM(0, side, mode)
@@ -585,11 +588,8 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e
/* find relative place within a cycle */
{
- float cycdx=0, cycdy=0, ofs=0;
- float cycle= 0;
-
- /* ofs is start frame of cycle */
- ofs= prevkey[0];
+ float cycdx=0, cycdy=0;
+ float cycle= 0, cyct=0;
/* calculate period and amplitude (total height) of a cycle */
cycdx= lastkey[0] - prevkey[0];
@@ -601,6 +601,9 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e
/* calculate the 'number' of the cycle */
cycle= ((float)side * (evaltime - ofs) / cycdx);
+
+ /* calculate the time inside the cycle */
+ cyct= fmod(evaltime - ofs, cycdx);
/* check that cyclic is still enabled for the specified time */
if (cycles == 0) {
@@ -608,7 +611,7 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e
* as this indicates infinite cycles...
*/
}
- else if (cycle > (cycles+1)) {
+ else if (cycle > cycles) {
/* we are too far away from range to evaluate
* TODO: but we should still hold last value...
*/
@@ -617,26 +620,36 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e
/* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
- cycyofs = (float)floor((evaltime - ofs) / cycdx);
+ if(side < 0)
+ cycyofs = (float)floor((evaltime - ofs) / cycdx);
+ else
+ cycyofs = (float)ceil((evaltime - ofs) / cycdx);
cycyofs *= cycdy;
}
-
+
+ /* special case for cycle start/end */
+ if(cyct == 0.0f) {
+ evaltime = (side == 1 ? lastkey[0] : prevkey[0]);
+
+ if((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)cycle % 2))
+ evaltime = (side == 1 ? prevkey[0] : lastkey[0]);
+ }
/* calculate where in the cycle we are (overwrite evaltime to reflect this) */
- if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) {
+ else if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle+1) % 2)) {
/* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse
* - for 'before' extrapolation, we need to flip in a different way, otherwise values past
* then end of the curve get referenced (result of fmod will be negative, and with different phase)
*/
if (side < 0)
- evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx));
+ evaltime= prevkey[0] - cyct;
else
- evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx));
+ evaltime= lastkey[0] - cyct;
}
else {
/* the cycle is played normally... */
- evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
+ evaltime= prevkey[0] + cyct;
}
- if (evaltime < ofs) evaltime += cycdx;
+ if (evaltime < prevkey[0]) evaltime += cycdx;
}
/* store temp data if needed */
@@ -652,7 +665,7 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e
return evaltime;
}
-static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+static void fcm_cycles_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float UNUSED(evaltime))
{
tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata;
@@ -696,7 +709,7 @@ static void fcm_noise_new_data (void *mdata)
data->modification = FCM_NOISE_MODIF_REPLACE;
}
-static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+static void fcm_noise_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime)
{
FMod_Noise *data= (FMod_Noise *)fcm->data;
float noise;
@@ -788,15 +801,15 @@ static void fcm_python_copy (FModifier *fcm, FModifier *src)
pymod->prop = IDP_CopyProperty(opymod->prop);
}
-static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+static void fcm_python_evaluate (FCurve *UNUSED(fcu), FModifier *UNUSED(fcm), float *UNUSED(cvalue), float UNUSED(evaltime))
{
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
//FMod_Python *data= (FMod_Python *)fcm->data;
/* FIXME... need to implement this modifier...
* It will need it execute a script using the custom properties
*/
-#endif /* DISABLE_PYTHON */
+#endif /* WITH_PYTHON */
}
static FModifierTypeInfo FMI_PYTHON = {
@@ -817,7 +830,7 @@ static FModifierTypeInfo FMI_PYTHON = {
/* Limits F-Curve Modifier --------------------------- */
-static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
+static float fcm_limits_time (FCurve *UNUSED(fcu), FModifier *fcm, float UNUSED(cvalue), float evaltime)
{
FMod_Limits *data= (FMod_Limits *)fcm->data;
@@ -831,7 +844,7 @@ static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float e
return evaltime;
}
-static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+static void fcm_limits_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float UNUSED(evaltime))
{
FMod_Limits *data= (FMod_Limits *)fcm->data;
@@ -868,7 +881,7 @@ static void fcm_stepped_new_data (void *mdata)
data->step_size = 2.0f;
}
-static float fcm_stepped_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
+static float fcm_stepped_time (FCurve *UNUSED(fcu), FModifier *fcm, float UNUSED(cvalue), float evaltime)
{
FMod_Stepped *data= (FMod_Stepped *)fcm->data;
int snapblock;
@@ -920,7 +933,7 @@ static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
/* This function only gets called when FMI_INIT is non-zero */
-static void fmods_init_typeinfo ()
+static void fmods_init_typeinfo (void)
{
fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */
fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */
@@ -997,9 +1010,13 @@ FModifier *add_fmodifier (ListBase *modifiers, int type)
fcm->flag = FMODIFIER_FLAG_EXPANDED;
BLI_addtail(modifiers, fcm);
+ /* tag modifier as "active" if no other modifiers exist in the stack yet */
+ if (modifiers->first == modifiers->last)
+ fcm->flag |= FMODIFIER_FLAG_ACTIVE;
+
/* add modifier's data */
fcm->data= MEM_callocN(fmi->size, fmi->structName);
-
+
/* init custom settings if necessary */
if (fmi->new_data)
fmi->new_data(fcm->data);
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 501de668000..05988605b4c 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -41,6 +41,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_vfontdata.h"
+#include "BLI_utildefines.h"
#include "DNA_packedFile_types.h"
#include "DNA_curve_types.h"
@@ -49,9 +50,7 @@
#include "DNA_object_types.h"
#include "BKE_utildefines.h"
-
#include "BKE_packedFile.h"
-
#include "BKE_library.h"
#include "BKE_font.h"
#include "BKE_global.h"
@@ -97,13 +96,14 @@ chtoutf8(unsigned long c, char *o)
void
wcs2utf8s(char *dst, wchar_t *src)
{
- char ch[5];
+ /* NULL terminator not needed */
+ char ch[4];
while(*src)
{
- memset(ch, 0, 5);
+ memset(ch, 0, sizeof(ch));
chtoutf8(*src++, ch);
- strcat(dst, ch);
+ dst= strncat(dst, ch, sizeof(ch));
}
}
@@ -124,31 +124,27 @@ wcsleninu8(wchar_t *src)
}
static int
-utf8slen(char *src)
+utf8slen(const char *strc)
{
- int size = 0, index = 0;
- unsigned char c;
-
- c = src[index++];
- while(c)
- {
- if((c & 0x80) == 0)
- {
- index += 0;
- }
- else if((c & 0xe0) == 0xe0)
- {
- index += 2;
- }
- else
- {
- index += 1;
+ int len=0;
+
+ while(*strc) {
+ if ((*strc & 0xe0) == 0xc0) {
+ if((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00)
+ strc++;
+ } else if ((*strc & 0xf0) == 0xe0) {
+ if((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00)
+ strc += 2;
+ } else if ((*strc & 0xf8) == 0xf0) {
+ if((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00)
+ strc += 3;
}
- size += 1;
- c = src[index++];
+
+ strc++;
+ len++;
}
-
- return size;
+
+ return len;
}
@@ -212,7 +208,7 @@ int utf8towchar(wchar_t *w, char *c)
/* The vfont code */
void free_vfont(struct VFont *vf)
{
- if (vf == 0) return;
+ if (vf == NULL) return;
if (vf->data) {
while(vf->data->characters.first)
@@ -305,7 +301,7 @@ static VFontData *vfont_get_data(VFont *vfont)
if (!vfont->data) {
PackedFile *pf;
- if (BLI_streq(vfont->name, "<builtin>")) {
+ if (strcmp(vfont->name, FO_BUILTIN_NAME)==0) {
pf= get_builtin_packedfile();
} else {
if (vfont->packedfile) {
@@ -342,7 +338,7 @@ static VFontData *vfont_get_data(VFont *vfont)
if(!pf) {
printf("Font file doesn't exist: %s\n", vfont->name);
- strcpy(vfont->name, "<builtin>");
+ strcpy(vfont->name, FO_BUILTIN_NAME);
pf= get_builtin_packedfile();
}
}
@@ -358,7 +354,7 @@ static VFontData *vfont_get_data(VFont *vfont)
return vfont->data;
}
-VFont *load_vfont(char *name)
+VFont *load_vfont(const char *name)
{
char filename[FILE_MAXFILE];
VFont *vfont= NULL;
@@ -367,15 +363,15 @@ VFont *load_vfont(char *name)
int is_builtin;
struct TmpFont *tmpfnt;
- if (BLI_streq(name, "<builtin>")) {
- strcpy(filename, name);
+ if (strcmp(name, FO_BUILTIN_NAME)==0) {
+ BLI_strncpy(filename, name, sizeof(filename));
pf= get_builtin_packedfile();
is_builtin= 1;
} else {
char dir[FILE_MAXDIR];
- strcpy(dir, name);
+ BLI_strncpy(dir, name, sizeof(dir));
BLI_splitdirstring(dir, filename);
pf= newPackedFile(NULL, name);
@@ -394,7 +390,7 @@ VFont *load_vfont(char *name)
/* if there's a font name, use it for the ID name */
if (strcmp(vfd->name, "")!=0) {
- BLI_strncpy(vfont->id.name+2, vfd->name, 21);
+ BLI_strncpy(vfont->id.name+2, vfd->name, sizeof(vfont->id.name)-2);
}
BLI_strncpy(vfont->name, name, sizeof(vfont->name));
@@ -403,8 +399,8 @@ VFont *load_vfont(char *name)
vfont->packedfile = pf;
}
- // Do not add <builtin> to temporary listbase
- if(strcmp(filename, "<builtin>"))
+ // Do not add FO_BUILTIN_NAME to temporary listbase
+ if(strcmp(filename, FO_BUILTIN_NAME))
{
tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
tmpfnt->pf= tpf;
@@ -443,10 +439,10 @@ VFont *get_builtin_font(void)
VFont *vf;
for (vf= G.main->vfont.first; vf; vf= vf->id.next)
- if (BLI_streq(vf->name, "<builtin>"))
+ if (strcmp(vf->name, FO_BUILTIN_NAME)==0)
return vf;
- return load_vfont("<builtin>");
+ return load_vfont(FO_BUILTIN_NAME);
}
static VChar *find_vfont_char(VFontData *vfd, intptr_t character)
@@ -480,7 +476,7 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i
nu2->flagu = CU_NURB_CYCLIC;
bp = (BPoint*)MEM_callocN(4 * sizeof(BPoint),"underline_bp");
- if (bp == 0){
+ if (bp == NULL){
MEM_freeN(nu2);
return;
}
@@ -514,11 +510,12 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
float *fp, fsize, shear, x, si, co;
VFontData *vfd = NULL;
VChar *che = NULL;
- int i, sel=0;
+ int i;
vfd= vfont_get_data(which_vfont(cu, info));
if (!vfd) return;
+ /*
if (cu->selend < cu->selstart) {
if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart-2)))
sel= 1;
@@ -527,6 +524,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
if ((charidx >= (cu->selstart-1)) && (charidx <= (cu->selend-1)))
sel= 1;
}
+ */
/* make a copy at distance ofsx,ofsy with shear*/
fsize= cu->fsize;
@@ -546,10 +544,10 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
bezt1 = nu1->bezt;
if (bezt1){
nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb");
- if (nu2 == 0) break;
+ if (nu2 == NULL) break;
memcpy(nu2, nu1, sizeof(struct Nurb));
nu2->resolu= cu->resolu;
- nu2->bp = 0;
+ nu2->bp = NULL;
nu2->knotsu = nu2->knotsv = NULL;
nu2->flag= CU_SMOOTH;
nu2->charidx = charidx;
@@ -564,7 +562,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
i = nu2->pntsu;
bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2");
- if (bezt2 == 0){
+ if (bezt2 == NULL){
MEM_freeN(nu2);
break;
}
@@ -672,7 +670,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
VFont *vfont, *oldvfont;
VFontData *vfd= NULL;
Curve *cu;
- CharInfo *info, *custrinfo;
+ CharInfo *info = NULL, *custrinfo;
TextBox *tb;
VChar *che;
struct chartrans *chartransdata=NULL, *ct;
@@ -688,18 +686,18 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
/* renark: do calculations including the trailing '\0' of a string
because the cursor can be at that location */
- if(ob->type!=OB_FONT) return 0;
+ if(ob->type!=OB_FONT) return NULL;
// Set font data
cu= (Curve *) ob->data;
vfont= cu->vfont;
- if(cu->str == NULL) return 0;
- if(vfont == NULL) return 0;
+ if(cu->str == NULL) return NULL;
+ if(vfont == NULL) return NULL;
// Create unicode string
utf8len = utf8slen(cu->str);
- tmp = mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
+ mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
utf8towchar(mem, cu->str);
@@ -725,7 +723,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
if(!vfd) {
if(mem)
MEM_freeN(mem);
- return 0;
+ return NULL;
}
/* calc offset and rotation of each char */
@@ -760,7 +758,6 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
for (i = 0 ; i<=slen ; i++) {
makebreak:
// Characters in the list
- che = vfd->characters.first;
info = &(custrinfo[i]);
ascii = mem[i];
if(info->flag & CU_CHINFO_SMALLCAPS) {
@@ -779,10 +776,10 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
/*
* The character wasn't in the current curve base so load it
- * But if the font is <builtin> then do not try loading since
+ * But if the font is FO_BUILTIN_NAME then do not try loading since
* whole font is in the memory already
*/
- if(che == NULL && strcmp(vfont->name, "<builtin>")) {
+ if(che == NULL && strcmp(vfont->name, FO_BUILTIN_NAME)) {
BLI_vfontchar_from_freetypefont(vfont, ascii);
}
@@ -790,11 +787,11 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
che= find_vfont_char(vfd, ascii);
/* No VFont found */
- if (vfont==0) {
+ if (vfont==NULL) {
if(mem)
MEM_freeN(mem);
MEM_freeN(chartransdata);
- return 0;
+ return NULL;
}
if (vfont != oldvfont) {
@@ -807,7 +804,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
if(mem)
MEM_freeN(mem);
MEM_freeN(chartransdata);
- return 0;
+ return NULL;
}
twidth = char_width(cu, che, info);
@@ -862,12 +859,15 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
yof= cu->yof + tb->y/cu->fsize;
}
+ /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
+#if 0
if(ascii == '\n' || ascii == '\r')
xof = cu->xof;
else
xof= cu->xof + (tb->x/cu->fsize);
-
+#else
xof= cu->xof + (tb->x/cu->fsize);
+#endif
lnr++;
cnr= 0;
wsnr= 0;
@@ -1042,10 +1042,9 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
che= find_vfont_char(vfd, ascii);
twidth = char_width(cu, che, info);
-
- dtime= distfac*0.35f*twidth; /* why not 0.5? */
- dtime= distfac*0.5f*twidth; /* why not 0.5? */
-
+
+ dtime= distfac*0.5f*twidth;
+
ctime= timeofs + distfac*( ct->xof - minx);
CLAMP(ctime, 0.0, 1.0);
@@ -1146,16 +1145,14 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
return NULL;
}
- if(mode==0) {
+ if(mode == FO_EDIT) {
/* make nurbdata */
- unsigned long cha;
-
freeNurblist(&cu->nurb);
ct= chartransdata;
if (cu->sepchar==0) {
for (i= 0; i<slen; i++) {
- cha = (uintptr_t) mem[i];
+ unsigned long cha = (uintptr_t) mem[i];
info = &(custrinfo[i]);
if (info->mat_nr > (ob->totcol)) {
/* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
@@ -1193,8 +1190,12 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
ascii = mem[i];
info = &(custrinfo[i]);
if (cu->sepchar == (i+1)) {
- float vecyo[3]= {ct->xof, ct->yof, 0.0f};
-
+ float vecyo[3];
+
+ vecyo[0]= ct->xof;
+ vecyo[1]= ct->yof;
+ vecyo[2]= 0.0f;
+
mem[0] = ascii;
mem[1] = 0;
custrinfo[0]= *info;
@@ -1218,7 +1219,5 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
MEM_freeN(mem);
MEM_freeN(chartransdata);
- return 0;
+ return NULL;
}
-
-
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 5612d69ed76..abd7c12ff70 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -33,8 +33,8 @@
#include "MEM_guardedalloc.h"
-
#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "DNA_gpencil_types.h"
@@ -42,7 +42,7 @@
#include "BKE_gpencil.h"
#include "BKE_library.h"
#include "BKE_main.h"
-#include "BKE_utildefines.h"
+
/* ************************************************** */
@@ -190,7 +190,7 @@ bGPDlayer *gpencil_layer_addnew (bGPdata *gpd)
}
/* add a new gp-datablock */
-bGPdata *gpencil_data_addnew (char name[])
+bGPdata *gpencil_data_addnew (const char name[])
{
bGPdata *gpd;
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index bdf203119c3..e48ec8ac288 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -41,6 +41,8 @@
#include "DNA_particle_types.h"
#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
#include "BKE_global.h"
#include "BKE_group.h"
@@ -127,7 +129,7 @@ void unlink_group(Group *group)
group->id.us= 0;
}
-Group *add_group(char *name)
+Group *add_group(const char *name)
{
Group *group;
@@ -327,7 +329,7 @@ static void group_replaces_nla(Object *parent, Object *target, char mode)
you can draw everything, leaves tags in objects to signal it needs further updating */
/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
-void group_handle_recalc_and_update(Scene *scene, Object *parent, Group *group)
+void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group *group)
{
GroupObject *go;
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 78306705d6b..8ce3847bf08 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -40,6 +40,7 @@
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
+#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BKE_icons.h"
@@ -76,7 +77,7 @@ static void icon_free(void *val)
/* create an id for a new icon and make sure that ids from deleted icons get reused
after the integer number range is used up */
-static int get_next_free_id()
+static int get_next_free_id(void)
{
int startId = gFirstIconId;
@@ -105,14 +106,14 @@ void BKE_icons_init(int first_dyn_id)
gIcons = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "icons_init gh");
}
-void BKE_icons_free()
+void BKE_icons_free(void)
{
if(gIcons)
- BLI_ghash_free(gIcons, 0, icon_free);
+ BLI_ghash_free(gIcons, NULL, icon_free);
gIcons = NULL;
}
-struct PreviewImage* BKE_previewimg_create()
+struct PreviewImage* BKE_previewimg_create(void)
{
PreviewImage* prv_img = NULL;
int i;
@@ -218,7 +219,7 @@ PreviewImage* BKE_previewimg_get(ID *id)
void BKE_icon_changed(int id)
{
- Icon* icon = 0;
+ Icon* icon = NULL;
if (!id || G.background) return;
@@ -241,7 +242,7 @@ void BKE_icon_changed(int id)
int BKE_icon_getid(struct ID* id)
{
- Icon* new_icon = 0;
+ Icon* new_icon = NULL;
if (!id || G.background)
return 0;
@@ -262,8 +263,8 @@ int BKE_icon_getid(struct ID* id)
new_icon->type = GS(id->name);
/* next two lines make sure image gets created */
- new_icon->drawinfo = 0;
- new_icon->drawinfo_free = 0;
+ new_icon->drawinfo = NULL;
+ new_icon->drawinfo_free = NULL;
BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon);
@@ -272,13 +273,13 @@ int BKE_icon_getid(struct ID* id)
Icon* BKE_icon_get(int icon_id)
{
- Icon* icon = 0;
+ Icon* icon = NULL;
icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
if (!icon) {
printf("BKE_icon_get: Internal error, no icon for icon ID: %d\n", icon_id);
- return 0;
+ return NULL;
}
return icon;
@@ -286,7 +287,7 @@ Icon* BKE_icon_get(int icon_id)
void BKE_icon_set(int icon_id, struct Icon* icon)
{
- Icon* old_icon = 0;
+ Icon* old_icon = NULL;
old_icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
@@ -304,6 +305,6 @@ void BKE_icon_delete(struct ID* id)
if (!id->icon_id) return; /* no icon defined for library object */
- BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(id->icon_id), 0, icon_free);
+ BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(id->icon_id), NULL, icon_free);
id->icon_id = 0;
}
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index a6c7062e22b..6c8b5329711 100755
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -1,5 +1,5 @@
-/**
- * $Id: idcode.c 31437 2010-08-18 07:14:10Z campbellbarton $
+/*
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -33,9 +33,11 @@
#include "DNA_ID.h"
+#include "BKE_idcode.h"
+
typedef struct {
unsigned short code;
- char *name, *plural;
+ const char *name, *plural;
int flags;
#define IDTYPE_FLAGS_ISLINKABLE (1<<0)
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index a0df73d6c42..b3119f317a5 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -266,7 +266,7 @@ void IDP_FreeArray(IDProperty *prop)
return newp;
}
-IDProperty *IDP_CopyArray(IDProperty *prop)
+static IDProperty *IDP_CopyArray(IDProperty *prop)
{
IDProperty *newp = idp_generic_copy(prop);
@@ -328,7 +328,7 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
return prop;
}
-IDProperty *IDP_CopyString(IDProperty *prop)
+static IDProperty *IDP_CopyString(IDProperty *prop)
{
IDProperty *newp = idp_generic_copy(prop);
@@ -341,7 +341,7 @@ IDProperty *IDP_CopyString(IDProperty *prop)
}
-void IDP_AssignString(IDProperty *prop, char *st, int maxlen)
+void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
{
int stlen;
@@ -356,7 +356,7 @@ void IDP_AssignString(IDProperty *prop, char *st, int maxlen)
BLI_strncpy(prop->data.pointer, st, stlen);
}
-void IDP_ConcatStringC(IDProperty *prop, char *st)
+void IDP_ConcatStringC(IDProperty *prop, const char *st)
{
int newlen;
@@ -402,7 +402,7 @@ void IDP_UnlinkID(IDProperty *prop)
/*-------- Group Functions -------*/
/*checks if a property with the same name as prop exists, and if so replaces it.*/
-IDProperty *IDP_CopyGroup(IDProperty *prop)
+static IDProperty *IDP_CopyGroup(IDProperty *prop)
{
IDProperty *newp = idp_generic_copy(prop), *link;
newp->len = prop->len;
@@ -421,9 +421,7 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src)
IDProperty *loop, *prop;
for (prop=src->data.group.first; prop; prop=prop->next) {
for (loop=dest->data.group.first; loop; loop=loop->next) {
- if (BSTR_EQ(loop->name, prop->name)) {
- int copy_done= 0;
-
+ if (strcmp(loop->name, prop->name)==0) {
if(prop->type==loop->type) {
switch (prop->type) {
@@ -431,11 +429,9 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src)
case IDP_FLOAT:
case IDP_DOUBLE:
loop->data= prop->data;
- copy_done= 1;
break;
case IDP_GROUP:
IDP_SyncGroupValues(loop, prop);
- copy_done= 1;
break;
default:
{
@@ -444,7 +440,6 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src)
BLI_insertlinkafter(&dest->data.group, loop, copy);
BLI_remlink(&dest->data.group, tmp);
- loop = copy;
IDP_FreeProperty(tmp);
MEM_freeN(tmp);
@@ -540,6 +535,12 @@ IDProperty *IDP_GetPropertyFromGroup(IDProperty *prop, const char *name)
return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name));
}
+IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, const char type)
+{
+ IDProperty *idprop= IDP_GetPropertyFromGroup(prop, name);
+ return (idprop && idprop->type == type) ? idprop : NULL;
+}
+
typedef struct IDPIter {
void *next;
IDProperty *parent;
@@ -702,7 +703,6 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, const char *name)
case IDP_STRING:
{
char *st = val.str;
- int stlen;
prop = MEM_callocN(sizeof(IDProperty), "IDProperty string");
if (st == NULL) {
@@ -710,10 +710,10 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, const char *name)
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/
} else {
- stlen = strlen(st) + 1;
- prop->data.pointer = MEM_callocN(stlen, "id property string 2");
+ int stlen = strlen(st) + 1;
+ prop->data.pointer = MEM_mallocN(stlen, "id property string 2");
prop->len = prop->totallen = stlen;
- strcpy(prop->data.pointer, st);
+ memcpy(prop->data.pointer, st, stlen);
}
break;
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 0e282aa6449..8a15f63243c 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -54,12 +54,14 @@
#include "DNA_packedFile_types.h"
#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
#include "DNA_camera_types.h"
#include "DNA_sequence_types.h"
#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
#include "BLI_threads.h"
+#include "BLI_utildefines.h"
#include "BKE_bmfont.h"
#include "BKE_global.h"
@@ -69,8 +71,9 @@
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_scene.h"
-
-//XXX #include "BIF_editseq.h"
+#include "BKE_node.h"
+#include "BKE_sequencer.h" /* seq_foreground_frame_get() */
+#include "BKE_utildefines.h"
#include "BLF_api.h"
@@ -96,14 +99,14 @@ static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */
{
struct ImBuf * tbuf1, * tbuf2;
- if (ibuf == 0) return;
+ if (ibuf == NULL) return;
if (ibuf->flags & IB_fields) return;
ibuf->flags |= IB_fields;
if (ibuf->rect) {
/* make copies */
- tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0);
- tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0);
+ tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect);
+ tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect);
ibuf->x *= 2;
@@ -124,14 +127,14 @@ static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */
{
struct ImBuf * tbuf1, * tbuf2;
- if (ibuf == 0) return;
+ if (ibuf == NULL) return;
if (ibuf->flags & IB_fields) return;
ibuf->flags |= IB_fields;
if (ibuf->rect) {
/* make copies */
- tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0);
- tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0);
+ tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect);
+ tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect);
ibuf->x *= 2;
@@ -329,7 +332,7 @@ void BKE_image_merge(Image *dest, Image *source)
/* otherwise creates new. */
/* does not load ibuf itself */
/* pass on optional frame for #name images */
-Image *BKE_add_image_file(const char *name, int frame)
+Image *BKE_add_image_file(const char *name)
{
Image *ima;
int file, len;
@@ -337,7 +340,7 @@ Image *BKE_add_image_file(const char *name, int frame)
char str[FILE_MAX], strtest[FILE_MAX];
BLI_strncpy(str, name, sizeof(str));
- BLI_path_abs(str, G.sce);
+ BLI_path_abs(str, G.main->name);
/* exists? */
file= open(str, O_BINARY|O_RDONLY);
@@ -348,7 +351,7 @@ Image *BKE_add_image_file(const char *name, int frame)
for(ima= G.main->image.first; ima; ima= ima->id.next) {
if(ima->source!=IMA_SRC_VIEWER && ima->source!=IMA_SRC_GENERATED) {
BLI_strncpy(strtest, ima->name, sizeof(ima->name));
- BLI_path_abs(strtest, G.sce);
+ BLI_path_abs(strtest, G.main->name);
if( strcmp(strtest, str)==0 ) {
if(ima->anim==NULL || ima->id.us==0) {
@@ -381,22 +384,22 @@ Image *BKE_add_image_file(const char *name, int frame)
return ima;
}
-static ImBuf *add_ibuf_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4])
+static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short uvtestgrid, float color[4])
{
ImBuf *ibuf;
unsigned char *rect= NULL;
float *rect_float= NULL;
if (floatbuf) {
- ibuf= IMB_allocImBuf(width, height, depth, IB_rectfloat, 0);
+ ibuf= IMB_allocImBuf(width, height, depth, IB_rectfloat);
rect_float= (float*)ibuf->rect_float;
}
else {
- ibuf= IMB_allocImBuf(width, height, depth, IB_rect, 0);
+ ibuf= IMB_allocImBuf(width, height, depth, IB_rect);
rect= (unsigned char*)ibuf->rect;
}
- strcpy(ibuf->name, "//Untitled");
+ BLI_strncpy(ibuf->name, name, sizeof(ibuf->name));
ibuf->userflags |= IB_BITMAPDIRTY;
switch(uvtestgrid) {
@@ -414,7 +417,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int depth, int fl
}
/* adds new image block, creates ImBuf and initializes color */
-Image *BKE_add_image_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4])
+Image *BKE_add_image_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short uvtestgrid, float color[4])
{
/* on save, type is changed to FILE in editsima.c */
Image *ima= image_alloc(name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
@@ -510,7 +513,7 @@ static void tag_all_images_time()
}
#endif
-void free_old_images()
+void free_old_images(void)
{
Image *ima;
static int lasttime = 0;
@@ -523,6 +526,10 @@ void free_old_images()
if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime)
return;
+ /* of course not! */
+ if (G.rendering)
+ return;
+
lasttime = ctime;
ima= G.main->image.first;
@@ -595,7 +602,7 @@ void BKE_image_free_all_textures(void)
{
Tex *tex;
Image *ima;
- unsigned int totsize= 0;
+ /* unsigned int totsize= 0; */
for(ima= G.main->image.first; ima; ima= ima->id.next)
ima->id.flag &= ~LIB_DOIT;
@@ -607,13 +614,20 @@ void BKE_image_free_all_textures(void)
for(ima= G.main->image.first; ima; ima= ima->id.next) {
if(ima->ibufs.first && (ima->id.flag & LIB_DOIT)) {
ImBuf *ibuf;
+
for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) {
- if(ibuf->mipmap[0])
+ /* escape when image is painted on */
+ if(ibuf->userflags & IB_BITMAPDIRTY)
+ break;
+
+ /* if(ibuf->mipmap[0])
totsize+= 1.33*ibuf->x*ibuf->y*4;
else
- totsize+= ibuf->x*ibuf->y*4;
+ totsize+= ibuf->x*ibuf->y*4;*/
+
}
- image_free_buffers(ima);
+ if(ibuf==NULL)
+ image_free_buffers(ima);
}
}
/* printf("freed total %d MB\n", totsize/(1024*1024)); */
@@ -756,9 +770,9 @@ int BKE_imtype_is_movie(int imtype)
return 0;
}
-void BKE_add_image_extension(char *string, int imtype)
+int BKE_add_image_extension(char *string, int imtype)
{
- char *extension="";
+ const char *extension= NULL;
if(imtype== R_IRIS) {
if(!BLI_testextensie(string, ".rgb"))
@@ -829,7 +843,15 @@ void BKE_add_image_extension(char *string, int imtype)
extension= ".jpg";
}
- strcat(string, extension);
+ if(extension) {
+ /* prefer this in many cases to avoid .png.tga, but in certain cases it breaks */
+ /* return BLI_replace_extension(string, FILE_MAX, extension); */
+ strcat(string, extension);
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
}
/* could allow access externally - 512 is for long names, 64 is for id names */
@@ -841,6 +863,7 @@ typedef struct StampData {
char time[512];
char frame[512];
char camera[64];
+ char cameralens[64];
char scene[64];
char strip[64];
char rendertime[64];
@@ -853,32 +876,23 @@ static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix)
time_t t;
if (scene->r.stamp & R_STAMP_FILENAME) {
- if (G.relbase_valid) {
- if (do_prefix) sprintf(stamp_data->file, "File %s", G.sce);
- else sprintf(stamp_data->file, "%s", G.sce);
- } else {
- if (do_prefix) strcpy(stamp_data->file, "File <untitled>");
- else strcpy(stamp_data->file, "<untitled>");
- }
+ BLI_snprintf(stamp_data->file, sizeof(stamp_data->file), do_prefix ? "File %s":"%s", G.relbase_valid ? G.main->name:"<untitled>");
} else {
stamp_data->file[0] = '\0';
}
if (scene->r.stamp & R_STAMP_NOTE) {
/* Never do prefix for Note */
- sprintf(stamp_data->note, "%s", scene->r.stamp_udata);
+ BLI_snprintf(stamp_data->note, sizeof(stamp_data->note), "%s", scene->r.stamp_udata);
} else {
stamp_data->note[0] = '\0';
}
if (scene->r.stamp & R_STAMP_DATE) {
-
- t = time (NULL);
- tl = localtime (&t);
- sprintf (text, "%04d/%02d/%02d %02d:%02d:%02d", tl->tm_year+1900, tl->tm_mon+1, tl->tm_mday, tl->tm_hour, tl->tm_min, tl->tm_sec);
-
- if (do_prefix) sprintf(stamp_data->date, "Date %s", text);
- else sprintf(stamp_data->date, "%s", text);
+ t = time(NULL);
+ tl = localtime(&t);
+ BLI_snprintf(text, sizeof(text), "%04d/%02d/%02d %02d:%02d:%02d", tl->tm_year+1900, tl->tm_mon+1, tl->tm_mday, tl->tm_hour, tl->tm_min, tl->tm_sec);
+ BLI_snprintf(stamp_data->date, sizeof(stamp_data->date), do_prefix ? "Date %s":"%s", text);
} else {
stamp_data->date[0] = '\0';
}
@@ -888,18 +902,17 @@ static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix)
if (name) strcpy(text, name);
else strcpy(text, "<none>");
-
- if (do_prefix) sprintf(stamp_data->marker, "Marker %s", text);
- else sprintf(stamp_data->marker, "%s", text);
+
+ BLI_snprintf(stamp_data->marker, sizeof(stamp_data->marker), do_prefix ? "Marker %s":"%s", text);
} else {
stamp_data->marker[0] = '\0';
}
if (scene->r.stamp & R_STAMP_TIME) {
- int h, m, s, f;
- h= m= s= f= 0;
- f = (int)(scene->r.cfra % scene->r.frs_sec);
- s = (int)(scene->r.cfra / scene->r.frs_sec);
+ int f = (int)(scene->r.cfra % scene->r.frs_sec);
+ int s = (int)(scene->r.cfra / scene->r.frs_sec);
+ int h= 0;
+ int m= 0;
if (s) {
m = (int)(s / 60);
@@ -912,50 +925,58 @@ static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix)
}
if (scene->r.frs_sec < 100)
- sprintf (text, "%02d:%02d:%02d.%02d", h, m, s, f);
+ BLI_snprintf(text, sizeof(text), "%02d:%02d:%02d.%02d", h, m, s, f);
else
- sprintf (text, "%02d:%02d:%02d.%03d", h, m, s, f);
-
- if (do_prefix) sprintf(stamp_data->time, "Time %s", text);
- else sprintf(stamp_data->time, "%s", text);
+ BLI_snprintf(text, sizeof(text), "%02d:%02d:%02d.%03d", h, m, s, f);
+
+ BLI_snprintf(stamp_data->time, sizeof(stamp_data->time), do_prefix ? "Time %s":"%s", text);
} else {
stamp_data->time[0] = '\0';
}
if (scene->r.stamp & R_STAMP_FRAME) {
char format[32];
- if (do_prefix) sprintf(format, "Frame %%0%di", 1 + (int) log10(scene->r.efra));
- else sprintf(format, "%%0%di", 1 + (int) log10(scene->r.efra));
- sprintf (stamp_data->frame, format, scene->r.cfra);
+ int digits= 1;
+
+ if(scene->r.efra>9)
+ digits= 1 + (int) log10(scene->r.efra);
+
+ BLI_snprintf(format, sizeof(format), do_prefix ? "Frame %%0%di":"%%0%di", digits);
+ BLI_snprintf (stamp_data->frame, sizeof(stamp_data->frame), format, scene->r.cfra);
} else {
stamp_data->frame[0] = '\0';
}
if (scene->r.stamp & R_STAMP_CAMERA) {
- if (scene->camera) strcpy(text, ((Camera *) scene->camera)->id.name+2);
- else strcpy(text, "<none>");
-
- if (do_prefix) sprintf(stamp_data->camera, "Camera %s", text);
- else sprintf(stamp_data->camera, "%s", text);
+ BLI_snprintf(stamp_data->camera, sizeof(stamp_data->camera), do_prefix ? "Camera %s":"%s", scene->camera ? scene->camera->id.name+2 : "<none>");
} else {
stamp_data->camera[0] = '\0';
}
+ if (scene->r.stamp & R_STAMP_CAMERALENS) {
+ if (scene->camera && scene->camera->type == OB_CAMERA) {
+ BLI_snprintf(text, sizeof(text), "%.2f", ((Camera *)scene->camera->data)->lens);
+ }
+ else strcpy(text, "<none>");
+
+ BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), do_prefix ? "Lens %s":"%s", text);
+ } else {
+ stamp_data->cameralens[0] = '\0';
+ }
+
if (scene->r.stamp & R_STAMP_SCENE) {
- if (do_prefix) sprintf(stamp_data->scene, "Scene %s", scene->id.name+2);
- else sprintf(stamp_data->scene, "%s", scene->id.name+2);
+ BLI_snprintf(stamp_data->scene, sizeof(stamp_data->scene), do_prefix ? "Scene %s":"%s", scene->id.name+2);
} else {
stamp_data->scene[0] = '\0';
}
if (scene->r.stamp & R_STAMP_SEQSTRIP) {
- Sequence *seq= NULL; //XXX = get_foreground_frame_seq(scene->r.cfra);
+ Sequence *seq= seq_foreground_frame_get(scene, scene->r.cfra);
if (seq) strcpy(text, seq->name+2);
else strcpy(text, "<none>");
-
- if (do_prefix) sprintf(stamp_data->strip, "Strip %s", text);
- else sprintf(stamp_data->strip, "%s", text);
+
+ BLI_snprintf(stamp_data->strip, sizeof(stamp_data->strip), do_prefix ? "Strip %s":"%s", text);
} else {
stamp_data->strip[0] = '\0';
}
@@ -967,37 +988,20 @@ static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix)
if (stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
BLI_timestr(stats->lastframetime, text);
- if (do_prefix) sprintf(stamp_data->rendertime, "RenderTime %s", text);
- else sprintf(stamp_data->rendertime, "%s", text);
+ BLI_snprintf(stamp_data->rendertime, sizeof(stamp_data->rendertime), do_prefix ? "RenderTime %s":"%s", text);
} else {
stamp_data->rendertime[0] = '\0';
}
}
}
-// XXX - Bad level call.
-extern int datatoc_bmonofont_ttf_size;
-extern char datatoc_bmonofont_ttf[];
-
-// XXX - copied from text_font_begin ! Change all the BLF_* here
-static int mono= -1;
-
-int stamp_font_begin(int size)
-{
- if (mono == -1)
- mono= BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
-
- BLF_aspect(mono, 1.0);
- BLF_size(mono, size, 72);
- return(mono); // XXX This is for image_gen.c!!
-}
-
void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels)
{
struct StampData stamp_data;
float w, h, pad;
int x, y;
float h_fixed;
+ const int mono= blf_mono_font_render; // XXX
if (!rect && !rectf)
return;
@@ -1008,8 +1012,9 @@ void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, i
if(scene->r.stamp_font_id < 8)
scene->r.stamp_font_id= 12;
- stamp_font_begin(scene->r.stamp_font_id);
-
+ /* set before return */
+ BLF_size(mono, scene->r.stamp_font_id, 72);
+
BLF_buffer(mono, rectf, rect, width, height, channels);
BLF_buffer_col(mono, scene->r.fg_stamp[0], scene->r.fg_stamp[1], scene->r.fg_stamp[2], 1.0);
pad= BLF_width(mono, "--");
@@ -1137,6 +1142,18 @@ void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, i
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+2, y+h+2);
BLF_position(mono, x, y+3, 0.0);
BLF_draw_buffer(mono, stamp_data.camera);
+
+ /* space width. */
+ x += w + pad;
+ }
+
+ if (stamp_data.cameralens[0]) {
+ BLF_width_and_height(mono, stamp_data.cameralens, &w, &h); h= h_fixed;
+
+ /* extra space for background. */
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+2, y+h+2);
+ BLF_position(mono, x, y+3, 0.0);
+ BLF_draw_buffer(mono, stamp_data.cameralens);
}
if (stamp_data.scene[0]) {
@@ -1154,7 +1171,7 @@ void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, i
}
if (stamp_data.strip[0]) {
- BLF_width_and_height(mono, stamp_data.scene, &w, &h); h= h_fixed;
+ BLF_width_and_height(mono, stamp_data.strip, &w, &h); h= h_fixed;
/* Top right corner, with an extra space because blenfont is too strict! */
x= width - w - pad;
@@ -1187,15 +1204,40 @@ void BKE_stamp_info(Scene *scene, struct ImBuf *ibuf)
if (stamp_data.time[0]) IMB_metadata_change_field (ibuf, "Time", stamp_data.time);
if (stamp_data.frame[0]) IMB_metadata_change_field (ibuf, "Frame", stamp_data.frame);
if (stamp_data.camera[0]) IMB_metadata_change_field (ibuf, "Camera", stamp_data.camera);
+ if (stamp_data.cameralens[0]) IMB_metadata_change_field (ibuf, "Lens", stamp_data.cameralens);
if (stamp_data.scene[0]) IMB_metadata_change_field (ibuf, "Scene", stamp_data.scene);
if (stamp_data.strip[0]) IMB_metadata_change_field (ibuf, "Strip", stamp_data.strip);
if (stamp_data.rendertime[0]) IMB_metadata_change_field (ibuf, "RenderTime", stamp_data.rendertime);
}
-int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimtype, int quality)
+int BKE_alphatest_ibuf(ImBuf *ibuf)
+{
+ int tot;
+ if(ibuf->rect_float) {
+ float *buf= ibuf->rect_float;
+ for(tot= ibuf->x * ibuf->y; tot--; buf+=4) {
+ if(buf[3] < 1.0f) {
+ return TRUE;
+ }
+ }
+ }
+ else if (ibuf->rect) {
+ unsigned char *buf= (unsigned char *)ibuf->rect;
+ for(tot= ibuf->x * ibuf->y; tot--; buf+=4) {
+ if(buf[3] != 255) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, const char *name, int imtype, int subimtype, int quality)
{
int ok;
-
+ (void)subimtype; /* quies unused warnings */
+
if(imtype==0) {
/* pass */
}
@@ -1203,7 +1245,7 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt
ibuf->ftype= IMAGIC;
}
#ifdef WITH_HDR
- else if ((imtype==R_RADHDR)) {
+ else if (imtype==R_RADHDR) {
ibuf->ftype= RADHDR;
}
#endif
@@ -1215,11 +1257,11 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt
}
#ifdef WITH_DDS
- else if ((imtype==R_DDS)) {
+ else if (imtype==R_DDS) {
ibuf->ftype= DDS;
}
#endif
- else if ((imtype==R_BMP)) {
+ else if (imtype==R_BMP) {
ibuf->ftype= BMP;
}
#ifdef WITH_TIFF
@@ -1299,12 +1341,14 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt
}
-void BKE_makepicstring(char *string, char *base, int frame, int imtype, int use_ext)
+void BKE_makepicstring(char *string, const char *base, int frame, int imtype, const short use_ext, const short use_frames)
{
if (string==NULL) return;
BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */
- BLI_path_abs(string, G.sce);
- BLI_path_frame(string, frame, 4);
+ BLI_path_abs(string, G.main->name);
+
+ if(use_frames)
+ BLI_path_frame(string, frame, 4);
if(use_ext)
BKE_add_image_extension(string, imtype);
@@ -1318,7 +1362,7 @@ struct anim *openanim(char *name, int flags)
struct ImBuf *ibuf;
anim = IMB_open_anim(name, flags);
- if (anim == NULL) return(0);
+ if (anim == NULL) return NULL;
ibuf = IMB_anim_absolute(anim, 0);
if (ibuf == NULL) {
@@ -1327,7 +1371,7 @@ struct anim *openanim(char *name, int flags)
else
printf("anim file doesn't exist: %s\n", name);
IMB_free_anim(anim);
- return(0);
+ return NULL;
}
IMB_freeImBuf(ibuf);
@@ -1408,7 +1452,9 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
}
}
- image_free_buffers(ima);
+ /* force reload on first use, but not for multilayer, that makes nodes and buttons in ui drawing fail */
+ if(ima->type!=IMA_TYPE_MULTILAYER)
+ image_free_buffers(ima);
ima->ok= 1;
if(iuser)
@@ -1447,6 +1493,17 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
}
break;
}
+
+ /* dont use notifiers because they are not 100% sure to succseed
+ * this also makes sure all scenes are accounted for. */
+ {
+ Scene *scene;
+ for(scene= G.main->scene.first; scene; scene= scene->id.next) {
+ if(scene->nodetree) {
+ NodeTagIDChanged(scene->nodetree, &ima->id);
+ }
+ }
+ }
}
/* if layer or pass changes, we need an index for the imbufs list */
@@ -1549,15 +1606,10 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
/* common stuff to do with images after loading */
static void image_initialize_after_load(Image *ima, ImBuf *ibuf)
{
-
-
/* preview is NULL when it has never been used as an icon before */
if(G.background==0 && ima->preview==NULL)
BKE_icon_changed(BKE_icon_getid(&ima->id));
-
- /* stringcodes also in ibuf, ibuf->name is used to retrieve original (buttons) */
- BLI_strncpy(ibuf->name, ima->name, FILE_MAX);
-
+
/* fields */
if (ima->flag & IMA_FIELDS) {
if(ima->flag & IMA_STD_FIELD) de_interlace_st(ibuf);
@@ -1582,15 +1634,14 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
ima->tpageflag |= IMA_TPAGE_REFRESH;
ima->lastframe= frame;
-
- BLI_stringdec(ima->name, head, tail, &numlen);
- BLI_stringenc(ima->name, head, tail, numlen, frame);
BLI_strncpy(name, ima->name, sizeof(name));
-
+ BLI_stringdec(name, head, tail, &numlen);
+ BLI_stringenc(name, head, tail, numlen, frame);
+
if(ima->id.lib)
BLI_path_abs(name, ima->id.lib->filepath);
else
- BLI_path_abs(name, G.sce);
+ BLI_path_abs(name, G.main->name);
flag= IB_rect|IB_multilayer;
if(ima->flag & IMA_DO_PREMUL)
@@ -1662,11 +1713,12 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
if(rpass) {
// printf("load from pass %s\n", rpass->name);
/* since we free render results, we copy the rect */
- ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0);
+ ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
ibuf->rect_float= MEM_dupallocN(rpass->rect);
ibuf->flags |= IB_rectfloat;
ibuf->mall= IB_rectfloat;
ibuf->channels= rpass->channels;
+ ibuf->profile = IB_PROFILE_LINEAR_RGB;
image_initialize_after_load(ima, ibuf);
image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:0, frame);
@@ -1697,7 +1749,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
if(ima->id.lib)
BLI_path_abs(str, ima->id.lib->filepath);
else
- BLI_path_abs(str, G.sce);
+ BLI_path_abs(str, G.main->name);
ima->anim = openanim(str, IB_rect);
@@ -1730,8 +1782,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
return ibuf;
}
-/* cfra used for # code, Image can only have this # for all its users
- * warning, 'iuser' can be NULL */
+/* warning, 'iuser' can be NULL */
static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
{
struct ImBuf *ibuf;
@@ -1758,9 +1809,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
if(ima->id.lib)
BLI_path_abs(str, ima->id.lib->filepath);
else
- BLI_path_abs(str, G.sce);
-
- BLI_path_frame(str, cfra, 0);
+ BLI_path_abs(str, G.main->name);
/* read ibuf */
ibuf = IMB_loadiffname(str, flag);
@@ -1813,7 +1862,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
RenderPass *rpass= BKE_image_multilayer_index(ima->rr, iuser);
if(rpass) {
- ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0);
+ ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
image_initialize_after_load(ima, ibuf);
@@ -1920,7 +1969,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
/* make ibuf if needed, and initialize it */
if(ibuf==NULL) {
- ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, 0, 0);
+ ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, 0);
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
}
@@ -1952,6 +2001,9 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
ibuf->flags &= ~IB_zbuffloat;
}
+ /* since its possible to access the buffer from the image directly, set the profile [#25073] */
+ ibuf->profile= (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE;
+
ibuf->dither= dither;
ima->ok= IMA_OK_LOADED;
@@ -1981,11 +2033,6 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame
/* XXX temp stuff? */
if(ima->lastframe != frame) {
ima->tpageflag |= IMA_TPAGE_REFRESH;
- if(ibuf) {
- /* without this the image name only updates
- * on first load which is quite confusing */
- BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name));
- }
}
ima->lastframe = frame;
}
@@ -2005,14 +2052,9 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame
ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0);
}
else if(ima->source == IMA_SRC_VIEWER) {
- if(ima->type==IMA_TYPE_R_RESULT) {
- /* always verify entirely, not that this shouldn't happen
- * during render anyway */
- }
- else if(ima->type==IMA_TYPE_COMPOSITE) {
- frame= iuser?iuser->framenr:0;
- ibuf= image_get_ibuf(ima, 0, frame);
- }
+ /* always verify entirely, not that this shouldn't happen
+ * as part of texture sampling in rendering anyway, so not
+ * a big bottleneck */
}
*frame_r = frame;
@@ -2093,9 +2135,6 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
/* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
ibuf= image_load_sequence_multilayer(ima, iuser, frame);
}
-
- if(ibuf)
- BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name));
}
else if(ima->source==IMA_SRC_FILE) {
@@ -2129,10 +2168,16 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
BLI_lock_thread(LOCK_VIEWER);
*lock_r= ima;
- /* Composite Viewer, all handled in compositor */
- /* fake ibuf, will be filled in compositor */
- ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0);
- image_assign_ibuf(ima, ibuf, 0, frame);
+ /* XXX anim play for viewer nodes not yet supported */
+ frame= 0; // XXX iuser?iuser->framenr:0;
+ ibuf= image_get_ibuf(ima, 0, frame);
+
+ if(!ibuf) {
+ /* Composite Viewer, all handled in compositor */
+ /* fake ibuf, will be filled in compositor */
+ ibuf= IMB_allocImBuf(256, 256, 32, IB_rect);
+ image_assign_ibuf(ima, ibuf, 0, frame);
+ }
}
}
}
@@ -2141,10 +2186,7 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
BLI_unlock_thread(LOCK_IMAGE);
}
- /* we assuming that if it is not rendering, it's also not multithreaded
- * (a somewhat weak assumption) */
- if(G.rendering==0)
- tag_image_time(ima);
+ tag_image_time(ima);
return ibuf;
}
@@ -2161,6 +2203,7 @@ void BKE_image_release_ibuf(Image *ima, void *lock)
}
}
+/* warning, this can allocate generated images */
ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
{
return BKE_image_acquire_ibuf(ima, iuser, NULL);
@@ -2168,7 +2211,7 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr)
{
- int imanr, len;
+ int len;
/* here (+fie_ima/2-1) makes sure that division happens correctly */
len= (iuser->fie_ima*iuser->frames)/2;
@@ -2177,8 +2220,9 @@ void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr)
iuser->framenr= 0;
}
else {
+ int imanr;
cfra= cfra - iuser->sfra+1;
-
+
/* cyclic */
if(iuser->cycl) {
cfra= ( (cfra) % len );
@@ -2186,7 +2230,7 @@ void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr)
if(cfra==0) cfra= len;
}
- if(cfra<1) cfra= 1;
+ if(cfra<0) cfra= 0;
else if(cfra>len) cfra= len;
/* convert current frame to current field */
diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index 9248ce69280..c21e347d6d8 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -25,6 +25,8 @@
#include <math.h>
#include <stdlib.h>
+
+#include "BKE_image.h"
#include "BLI_math_color.h"
#include "BLF_api.h"
@@ -298,16 +300,16 @@ static void checker_board_grid_fill(unsigned char *rect, float *rect_float, int
}
/* defined in image.c */
-extern int stamp_font_begin(int size);
static void checker_board_text(unsigned char *rect, float *rect_float, int width, int height, int step, int outline)
{
- int x, y, mono;
+ int x, y;
int pen_x, pen_y;
char text[3]= {'A', '1', '\0'};
+ const int mono= blf_mono_font;
+
+ BLF_size(mono, 54, 72); /* hard coded size! */
- /* hard coded size! */
- mono= stamp_font_begin(54);
BLF_buffer(mono, rect_float, rect, width, height, 4);
for(y= 0; y < height; y+=step)
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 158f964a846..207c667f335 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1,31 +1,31 @@
-/* implicit.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*
-* The Original Code is Copyright (C) Blender Foundation
-* All rights reserved.
-*
-* The Original Code is: all of this file.
-*
-* Contributor(s): none yet.
-*
-* ***** END GPL LICENSE BLOCK *****
-*/
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
#include "MEM_guardedalloc.h"
@@ -37,12 +37,13 @@
#include "BLI_threads.h"
#include "BLI_math.h"
#include "BLI_linklist.h"
+#include "BLI_utildefines.h"
#include "BKE_cloth.h"
#include "BKE_collision.h"
#include "BKE_effect.h"
#include "BKE_global.h"
-#include "BKE_utildefines.h"
+
#define CLOTH_OPENMP_LIMIT 25
@@ -63,7 +64,7 @@ static void itend(void)
{
QueryPerformanceCounter(&_itend);
}
-double itval()
+double itval(void)
{
return ((double)_itend.QuadPart -
(double)_itstart.QuadPart)/((double)ifreq.QuadPart);
@@ -85,7 +86,7 @@ static void itend(void)
{
gettimeofday(&_itend,&itz);
}
-double itval()
+double itval(void)
{
double t1, t2;
t1 = (double)_itstart.tv_sec + (double)_itstart.tv_usec/(1000*1000);
@@ -726,7 +727,7 @@ typedef struct Implicit_Data
fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI, *M;
} Implicit_Data;
-int implicit_init (Object *ob, ClothModifierData *clmd)
+int implicit_init (Object *UNUSED(ob), ClothModifierData *clmd)
{
unsigned int i = 0;
unsigned int pinned = 0;
@@ -1218,7 +1219,7 @@ DO_INLINE void dfdx_damp(float to[3][3], float dir[3],float length,const float
}
-DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float time)
+DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *UNUSED(lF), lfVector *X, lfVector *V, fmatrix3x3 *UNUSED(dFdV), fmatrix3x3 *UNUSED(dFdX), float time)
{
Cloth *cloth = clmd->clothObject;
ClothVertex *verts = cloth->verts;
@@ -1228,7 +1229,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
float vel[3];
float k = 0.0f;
float L = s->restlen;
- float cb = clmd->sim_parms->structural;
+ float cb; /* = clmd->sim_parms->structural; */ /*UNUSED*/
float nullf[3] = {0,0,0};
float stretch_force[3] = {0,0,0};
@@ -1316,8 +1317,9 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
VECSUB(extent, X[s->ij], tvect);
- dot = INPR(extent, extent);
- length = sqrt(dot);
+ // SEE MSG BELOW (these are UNUSED)
+ // dot = INPR(extent, extent);
+ // length = sqrt(dot);
k = clmd->sim_parms->goalspring;
@@ -1353,7 +1355,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
}
}
-DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX)
+DO_INLINE void cloth_apply_spring_force(ClothModifierData *UNUSED(clmd), ClothSpring *s, lfVector *lF, lfVector *UNUSED(X), lfVector *UNUSED(V), fmatrix3x3 *dFdV, fmatrix3x3 *dFdX)
{
if(s->flags & CLOTH_SPRING_FLAG_NEEDED)
{
@@ -1425,7 +1427,7 @@ typedef struct HairGridVert {
by Lena Petrovic, Mark Henne and John Anderson
* Pixar Technical Memo #06-08, Pixar Animation Studios
*/
-static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, int numverts)
+static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
{
/* TODO: This is an initial implementation and should be made much better in due time.
* What should at least be implemented is a grid size parameter and a smoothing kernel
@@ -1441,10 +1443,10 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec
/* 2.0f is an experimental value that seems to give good results */
float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth;
float collfac = 2.0f * clmd->sim_parms->collider_friction;
- int v = 0;
- int i = 0;
- int j = 0;
- int k = 0;
+ unsigned int v = 0;
+ unsigned int i = 0;
+ int j = 0;
+ int k = 0;
INIT_MINMAX(gmin, gmax);
@@ -1555,20 +1557,22 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec
free_collider_cache(&colliders);
}
-static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M)
+static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M)
{
/* Collect forces and derivatives: F,dFdX,dFdV */
Cloth *cloth = clmd->clothObject;
- int i = 0;
+ unsigned int i = 0;
float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */
float gravity[3] = {0.0f, 0.0f, 0.0f};
- float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}};
+ float tm2[3][3] = {{0}};
MFace *mfaces = cloth->mfaces;
unsigned int numverts = cloth->numverts;
- LinkNode *search = cloth->springs;
+ LinkNode *search;
lfVector *winvec;
EffectedPoint epoint;
+ tm2[0][0]= tm2[1][1]= tm2[2][2]= -spring_air;
+
/* global acceleration (gravitation) */
if(clmd->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
VECCOPY(gravity, clmd->scene->physics_settings.gravity);
@@ -1708,7 +1712,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF,
// printf("\n");
}
-static void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *M, fmatrix3x3 *bigI)
+static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *UNUSED(P), fmatrix3x3 *UNUSED(Pinv), fmatrix3x3 *M, fmatrix3x3 *UNUSED(bigI))
{
unsigned int numverts = dFdV[0].vcount;
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index a24f37bf73a..329058b3115 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -59,9 +59,10 @@
#include "BLI_math.h" /* windows needs for M_PI */
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
-#include "BKE_utildefines.h"
+#include "BKE_ipo.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_fcurve.h"
@@ -102,7 +103,7 @@ void free_ipo (Ipo *ipo)
/* Mapping Table for bitflag <-> RNA path */
typedef struct AdrBit2Path {
int bit;
- char *path;
+ const char *path;
int array_index;
} AdrBit2Path;
@@ -111,27 +112,26 @@ typedef struct AdrBit2Path {
/* Object layers */
static AdrBit2Path ob_layer_bits[]= {
- {(1<<0), "layer", 0},
- {(1<<1), "layer", 1},
- {(1<<2), "layer", 2},
- {(1<<3), "layer", 3},
- {(1<<4), "layer", 4},
- {(1<<5), "layer", 5},
- {(1<<6), "layer", 6},
- {(1<<7), "layer", 7},
- {(1<<8), "layer", 8},
- {(1<<9), "layer", 9},
- {(1<<10), "layer", 10},
- {(1<<11), "layer", 11},
- {(1<<12), "layer", 12},
- {(1<<13), "layer", 13},
- {(1<<14), "layer", 14},
- {(1<<15), "layer", 15},
- {(1<<16), "layer", 16},
- {(1<<17), "layer", 17},
- {(1<<18), "layer", 18},
- {(1<<19), "layer", 19},
- {(1<<20), "layer", 20}
+ {(1<<0), "layers", 0},
+ {(1<<1), "layers", 1},
+ {(1<<2), "layers", 2},
+ {(1<<3), "layers", 3},
+ {(1<<4), "layers", 4},
+ {(1<<5), "layers", 5},
+ {(1<<6), "layers", 6},
+ {(1<<7), "layers", 7},
+ {(1<<8), "layers", 8},
+ {(1<<9), "layers", 9},
+ {(1<<10), "layers", 10},
+ {(1<<11), "layers", 11},
+ {(1<<12), "layers", 12},
+ {(1<<13), "layers", 13},
+ {(1<<14), "layers", 14},
+ {(1<<15), "layers", 15},
+ {(1<<16), "layers", 16},
+ {(1<<17), "layers", 17},
+ {(1<<18), "layers", 18},
+ {(1<<19), "layers", 19}
};
/* Material mode */
@@ -172,7 +172,7 @@ static AdrBit2Path *adrcode_bitmaps_to_paths (int blocktype, int adrcode, int *t
/* ADRCODE to RNA-Path Conversion Code - Standard */
/* Object types */
-static char *ob_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *ob_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -253,7 +253,7 @@ static char *ob_adrcodes_to_paths (int adrcode, int *array_index)
/* PoseChannel types
* NOTE: pchan name comes from 'actname' added earlier...
*/
-static char *pchan_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *pchan_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -297,7 +297,7 @@ static char *pchan_adrcodes_to_paths (int adrcode, int *array_index)
}
/* Constraint types */
-static char *constraint_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *constraint_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -315,9 +315,9 @@ static char *constraint_adrcodes_to_paths (int adrcode, int *array_index)
/* ShapeKey types
* NOTE: as we don't have access to the keyblock where the data comes from (for now),
- * we'll just use numerical indicies for now...
+ * we'll just use numerical indices for now...
*/
-static char *shapekey_adrcodes_to_paths (int adrcode, int *array_index)
+static char *shapekey_adrcodes_to_paths (int adrcode, int *UNUSED(array_index))
{
static char buf[128];
@@ -331,9 +331,9 @@ static char *shapekey_adrcodes_to_paths (int adrcode, int *array_index)
}
/* MTex (Texture Slot) types */
-static char *mtex_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *mtex_adrcodes_to_paths (int adrcode, int *UNUSED(array_index))
{
- char *base=NULL, *prop=NULL;
+ const char *base=NULL, *prop=NULL;
static char buf[128];
/* base part of path */
@@ -401,7 +401,7 @@ static char *mtex_adrcodes_to_paths (int adrcode, int *array_index)
}
/* Texture types */
-static char *texture_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *texture_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -481,7 +481,7 @@ static char *texture_adrcodes_to_paths (int adrcode, int *array_index)
}
/* Material Types */
-static char *material_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *material_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -565,7 +565,7 @@ static char *material_adrcodes_to_paths (int adrcode, int *array_index)
}
/* Camera Types */
-static char *camera_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *camera_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -605,7 +605,7 @@ static char *camera_adrcodes_to_paths (int adrcode, int *array_index)
}
/* Lamp Types */
-static char *lamp_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *lamp_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -647,7 +647,7 @@ static char *lamp_adrcodes_to_paths (int adrcode, int *array_index)
}
/* Sound Types */
-static char *sound_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *sound_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -670,7 +670,7 @@ static char *sound_adrcodes_to_paths (int adrcode, int *array_index)
}
/* World Types */
-static char *world_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *world_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -709,6 +709,11 @@ static char *world_adrcodes_to_paths (int adrcode, int *array_index)
*array_index= 1; return "stars.color";
case WO_STAR_B:
*array_index= 2; return "stars.color"; */
+ case WO_STAR_R:
+ case WO_STAR_G:
+ case WO_STAR_B:
+ printf("WARNING: WO_STAR_R/G/B deprecated\n");
+ return NULL;
case WO_STARDIST:
return "stars.min_distance";
@@ -723,7 +728,7 @@ static char *world_adrcodes_to_paths (int adrcode, int *array_index)
}
/* Particle Types */
-static char *particle_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *particle_adrcodes_to_paths (int adrcode, int *array_index)
{
/* set array index like this in-case nothing sets it correctly */
*array_index= 0;
@@ -798,10 +803,11 @@ static char *particle_adrcodes_to_paths (int adrcode, int *array_index)
* - array_index - index in property's array (if applicable) to use
* - return - the allocated path...
*/
-static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], Sequence * seq, int *array_index)
+static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], Sequence *seq, int *array_index)
{
DynStr *path= BLI_dynstr_new();
- char *propname=NULL, *rpath=NULL;
+ const char *propname=NULL;
+ char *rpath=NULL;
char buf[512];
int dummy_index= 0;
@@ -913,8 +919,17 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co
sprintf(buf, "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname);
}
else if (actname && actname[0]) {
- /* Pose-Channel */
- sprintf(buf, "pose.bones[\"%s\"]", actname);
+ if ((blocktype == ID_OB) && strcmp(actname, "Object")==0) {
+ /* Actionified "Object" IPO's... no extra path stuff needed */
+ }
+ else if ((blocktype == ID_KE) && strcmp(actname, "Shape")==0) {
+ /* Actionified "Shape" IPO's - these are forced onto object level via the action container there... */
+ strcpy(buf, "data.shape_keys");
+ }
+ else {
+ /* Pose-Channel */
+ sprintf(buf, "pose.bones[\"%s\"]", actname);
+ }
}
else if (constname && constname[0]) {
/* Constraint in Object */
@@ -922,8 +937,7 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co
}
else if (seq) {
/* Sequence names in Scene */
- sprintf(buf, "sequence_editor.sequences_all[\"%s\"]",
- seq->name+2);
+ sprintf(buf, "sequence_editor.sequences_all[\"%s\"]", seq->name+2);
}
else
strcpy(buf, ""); /* empty string */
@@ -1017,13 +1031,13 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
dtar= &dvar->targets[0];
dtar->id= (ID *)idriver->ob;
if (idriver->name[0])
- BLI_strncpy(dtar->pchan_name, idriver->name, 32);
+ BLI_strncpy(dtar->pchan_name, idriver->name, sizeof(dtar->pchan_name));
/* second bone target (name was stored in same var as the first one) */
dtar= &dvar->targets[1];
dtar->id= (ID *)idriver->ob;
if (idriver->name[0]) // xxx... for safety
- BLI_strncpy(dtar->pchan_name, idriver->name+DRIVER_NAME_OFFS, 32);
+ BLI_strncpy(dtar->pchan_name, idriver->name+DRIVER_NAME_OFFS, sizeof(dtar->pchan_name));
}
else {
/* only a single variable, of type 'transform channel' */
@@ -1034,7 +1048,7 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
dtar= &dvar->targets[0];
dtar->id= (ID *)idriver->ob;
if (idriver->name[0])
- BLI_strncpy(dtar->pchan_name, idriver->name, 32);
+ BLI_strncpy(dtar->pchan_name, idriver->name, sizeof(dtar->pchan_name));
dtar->transChan= adrcode_to_dtar_transchan(idriver->adrcode);
dtar->flag |= DTAR_FLAG_LOCALSPACE; /* old drivers took local space */
}
@@ -1123,7 +1137,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
{
AdrBit2Path *abp;
FCurve *fcu;
- int i=0, totbits;
+ int totbits;
/* allocate memory for a new F-Curve */
fcu= MEM_callocN(sizeof(FCurve), "FCurve");
@@ -1188,6 +1202,8 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
* 3) filter the keyframes for the flag of interest
*/
for (b=0; b < totbits; b++, abp++) {
+ unsigned int i=0;
+
/* make a copy of existing base-data if not the last curve */
if (b < (totbits-1))
fcurve= copy_fcurve(fcu);
@@ -1195,7 +1211,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
fcurve= fcu;
/* set path */
- fcurve->rna_path= BLI_strdupn(abp->path, strlen(abp->path));
+ fcurve->rna_path= BLI_strdup(abp->path);
fcurve->array_index= abp->array_index;
/* convert keyframes
@@ -1211,7 +1227,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
fcurve->bezt= MEM_callocN(sizeof(BezTriple)*fcurve->totvert, "BezTriples");
/* loop through copying all BezTriples individually, as we need to modify a few things */
- for (dst=fcurve->bezt, src=icu->bezt; i < fcurve->totvert; i++, dst++, src++) {
+ for (dst=fcurve->bezt, src=icu->bezt, i=0; i < fcurve->totvert; i++, dst++, src++) {
/* firstly, copy BezTriple data */
*dst= *src;
@@ -1239,6 +1255,8 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
}
}
else {
+ unsigned int i=0;
+
/* get rna-path
* - we will need to set the 'disabled' flag if no path is able to be made (for now)
*/
@@ -1259,7 +1277,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
fcu->bezt= MEM_callocN(sizeof(BezTriple)*fcu->totvert, "BezTriples");
/* loop through copying all BezTriples individually, as we need to modify a few things */
- for (dst=fcu->bezt, src=icu->bezt; i < fcu->totvert; i++, dst++, src++) {
+ for (dst=fcu->bezt, src=icu->bezt, i=0; i < fcu->totvert; i++, dst++, src++) {
/* firstly, copy BezTriple data */
*dst= *src;
@@ -1301,13 +1319,14 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
/* correct times for rotation drivers
* - need to go from degrees to radians...
* - there's only really 1 target to worry about
+ * - were also degrees/10
*/
if (fcu->driver && fcu->driver->variables.first) {
DriverVar *dvar= fcu->driver->variables.first;
DriverTarget *dtar= &dvar->targets[0];
if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
- const float fac= (float)M_PI / 180.0f;
+ const float fac= (float)M_PI / 18.0f;
dst->vec[0][0] *= fac;
dst->vec[1][0] *= fac;
@@ -1315,20 +1334,17 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
}
}
- /* correct values for sequencer curves,
- that were not locked to frame */
-
- if (seq &&
- (seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) {
+ /* correct values for sequencer curves, that were not locked to frame */
+ if (seq && (seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) {
double mul= (seq->enddisp-seq->startdisp)/100.0f;
double offset= seq->startdisp;
dst->vec[0][0] *= mul;
dst->vec[0][0] += offset;
-
+
dst->vec[1][0] *= mul;
dst->vec[1][0] += offset;
-
+
dst->vec[2][0] *= mul;
dst->vec[2][0] += offset;
}
@@ -1475,7 +1491,7 @@ static void action_to_animato (ID *id, bAction *act, ListBase *groups, ListBase
* This assumes that AnimData has been added already. Separation of drivers
* from animation data is accomplished here too...
*/
-static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[], Sequence * seq)
+static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[], Sequence *seq)
{
AnimData *adt= BKE_animdata_from_id(id);
ListBase anim = {NULL, NULL};
@@ -1506,19 +1522,23 @@ static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[],
if (G.f & G_DEBUG) printf("\thas anim \n");
/* try to get action */
if (adt->action == NULL) {
- adt->action= add_empty_action("ConvData_Action"); // XXX we need a better name for this
- if (G.f & G_DEBUG) printf("\t\tadded new action \n");
+ char nameBuf[MAX_ID_NAME];
+
+ BLI_snprintf(nameBuf, sizeof(nameBuf), "CDA:%s", ipo->id.name+2);
+
+ adt->action= add_empty_action(nameBuf);
+ if (G.f & G_DEBUG) printf("\t\tadded new action - '%s' \n", nameBuf);
}
/* add F-Curves to action */
- addlisttolist(&adt->action->curves, &anim);
+ BLI_movelisttolist(&adt->action->curves, &anim);
}
/* deal with drivers */
if (drivers.first) {
if (G.f & G_DEBUG) printf("\thas drivers \n");
/* add drivers to end of driver stack */
- addlisttolist(&adt->drivers, &drivers);
+ BLI_movelisttolist(&adt->drivers, &drivers);
}
}
@@ -1863,7 +1883,7 @@ void do_versions_ipos_to_animato(Main *main)
to different DNA variables later
(semi-hack (tm) )
*/
- switch(seq->type) {
+ switch (seq->type) {
case SEQ_IMAGE:
case SEQ_META:
case SEQ_SCENE:
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index f6f4226bf57..5c10c14c4e2 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -39,6 +39,7 @@
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_key_types.h"
@@ -58,14 +59,14 @@
#include "BKE_tessmesh.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_utildefines.h"
+
#include "RNA_access.h"
#include "BLI_cellalloc.h"
-
-#define KEY_BPOINT 1
-#define KEY_BEZTRIPLE 2
+#define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */
+#define KEY_MODE_BPOINT 1
+#define KEY_MODE_BEZTRIPLE 2
// old defines from DNA_ipo_types.h for data-type
#define IPO_FLOAT 4
@@ -167,14 +168,10 @@ Key *copy_key(Key *key)
Key *keyn;
KeyBlock *kbn, *kb;
- if(key==0) return 0;
+ if(key==NULL) return NULL;
keyn= copy_libblock(key);
-#if 0 // XXX old animation system
- keyn->ipo= copy_ipo(key->ipo);
-#endif // XXX old animation system
-
BLI_duplicatelist(&keyn->block, &key->block);
kb= key->block.first;
@@ -224,14 +221,10 @@ void make_local_key(Key *key)
* - only local users: set flag
* - mixed: make copy
*/
- if(key==0) return;
+ if(key==NULL) return;
- key->id.lib= 0;
- new_id(0, (ID *)key, 0);
-
-#if 0 // XXX old animation system
- make_local_ipo(key->ipo);
-#endif // XXX old animation system
+ key->id.lib= NULL;
+ new_id(NULL, (ID *)key, NULL);
}
/* Sort shape keys and Ipo curves after a change. This assumes that at most
@@ -416,14 +409,14 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
/* if(fac<0.0 || fac>1.0) return 1; */
- if(k1->next==0) return 1;
+ if(k1->next==NULL) return 1;
if(cycl) { /* pre-sort */
k[2]= k1->next;
k[3]= k[2]->next;
- if(k[3]==0) k[3]=k1;
+ if(k[3]==NULL) k[3]=k1;
while(k1) {
- if(k1->next==0) k[0]=k1;
+ if(k1->next==NULL) k[0]=k1;
k1=k1->next;
}
k1= k[1];
@@ -444,13 +437,13 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
k[2]= k1->next;
t[2]= k[2]->pos;
k[3]= k[2]->next;
- if(k[3]==0) k[3]= k[2];
+ if(k[3]==NULL) k[3]= k[2];
t[3]= k[3]->pos;
k1= k[3];
}
while( t[2]<fac ) { /* find correct location */
- if(k1->next==0) {
+ if(k1->next==NULL) {
if(cycl) {
k1= firstkey;
ofs+= dpos;
@@ -570,36 +563,53 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **
return kb->data;
}
-static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, int mode)
+
+/* currently only the first value of 'ofs' may be set. */
+static short key_pointer_size(const Key *key, const int mode, int *poinsize, int *ofs)
+{
+ if(key->from==NULL) {
+ return FALSE;
+ }
+
+ switch(GS(key->from->name)) {
+ case ID_ME:
+ *ofs= sizeof(float)*3;
+ *poinsize= *ofs;
+ break;
+ case ID_LT:
+ *ofs= sizeof(float)*3;
+ *poinsize= *ofs;
+ break;
+ case ID_CU:
+ if(mode == KEY_MODE_BPOINT) {
+ *ofs= sizeof(float)*4;
+ *poinsize= *ofs;
+ } else {
+ ofs[0]= sizeof(float)*12;
+ *poinsize= (*ofs) / 3;
+ }
+
+ break;
+ default:
+ BLI_assert(!"invalid 'key->from' ID type");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void cp_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, const int mode)
{
float ktot = 0.0, kd = 0.0;
int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0;
char *k1, *kref, *freek1, *freekref;
char *cp, elemstr[8];
- if(key->from==NULL) return;
-
- if( GS(key->from->name)==ID_ME ) {
- ofs[0]= sizeof(float)*3;
- ofs[1]= 0;
- poinsize= ofs[0];
- }
- else if( GS(key->from->name)==ID_LT ) {
- ofs[0]= sizeof(float)*3;
- ofs[1]= 0;
- poinsize= ofs[0];
- }
- else if( GS(key->from->name)==ID_CU ) {
- if(mode==KEY_BPOINT) {
- ofs[0]= sizeof(float)*4;
- poinsize= ofs[0];
- }else {
- ofs[0]= sizeof(float)*12;
- poinsize= ofs[0]/3;
- }
+ /* currently always 0, in future key_pointer_size may assign */
+ ofs[1]= 0;
- ofs[1]= 0;
- }
+ if(!key_pointer_size(key, mode, &poinsize, &ofs[0]))
+ return;
if(end>tot) end= tot;
@@ -631,7 +641,7 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
else k1+= start*key->elemsize;
}
- if(mode==KEY_BEZTRIPLE) {
+ if(mode == KEY_MODE_BEZTRIPLE) {
elemstr[0]= 1;
elemstr[1]= IPO_BEZTRIPLE;
elemstr[2]= 0;
@@ -639,11 +649,11 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
/* just do it here, not above! */
elemsize= key->elemsize;
- if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+ if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3;
for(a=start; a<end; a++) {
cp= key->elemstr;
- if(mode==KEY_BEZTRIPLE) cp= elemstr;
+ if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr;
ofsp= ofs;
@@ -666,8 +676,14 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
case IPO_BEZTRIPLE:
memcpy(poin, k1, sizeof(float)*12);
break;
+ default:
+ /* should never happen */
+ if(freek1) MEM_freeN(freek1);
+ if(freekref) MEM_freeN(freekref);
+ BLI_assert(!"invalid 'cp[1]'");
+ return;
}
-
+
poin+= ofsp[0];
cp+= 2; ofsp++;
}
@@ -686,14 +702,14 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
kref+= elemsize;
}
- if(mode==KEY_BEZTRIPLE) a+=2;
+ if(mode == KEY_MODE_BEZTRIPLE) a+=2;
}
if(freek1) MEM_freeN(freek1);
if(freekref) MEM_freeN(freekref);
}
-static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int start, int end, char *out, int tot)
+static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const int start, int end, char *out, const int tot)
{
Nurb *nu;
int a, step, a1, a2;
@@ -705,7 +721,7 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int st
a1= MAX2(a, start);
a2= MIN2(a+step, end);
- if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_BPOINT);
+ if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BPOINT);
}
else if(nu->bezt) {
step= 3*nu->pntsu;
@@ -714,45 +730,26 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int st
a1= MAX2(a, start);
a2= MIN2(a+step, end);
- if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_BEZTRIPLE);
+ if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BEZTRIPLE);
}
else
step= 0;
}
}
-
-void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock *actkb, int mode)
+void do_rel_key(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode)
{
KeyBlock *kb;
int *ofsp, ofs[3], elemsize, b;
char *cp, *poin, *reffrom, *from, elemstr[8];
char *freefrom, *freereffrom;
- int poinsize= 0;
-
- if(key->from==NULL) return;
+ int poinsize;
- if( GS(key->from->name)==ID_ME ) {
- ofs[0]= sizeof(float)*3;
- ofs[1]= 0;
- poinsize= ofs[0];
- }
- else if( GS(key->from->name)==ID_LT ) {
- ofs[0]= sizeof(float)*3;
- ofs[1]= 0;
- poinsize= ofs[0];
- }
- else if( GS(key->from->name)==ID_CU ) {
- if(mode==KEY_BPOINT) {
- ofs[0]= sizeof(float)*4;
- poinsize= ofs[0];
- } else {
- ofs[0]= sizeof(float)*12;
- poinsize= ofs[0] / 3;
- }
+ /* currently always 0, in future key_pointer_size may assign */
+ ofs[1]= 0;
- ofs[1]= 0;
- }
+ if(!key_pointer_size(key, mode, &poinsize, &ofs[0]))
+ return;
if(end>tot) end= tot;
@@ -763,7 +760,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
/* just here, not above! */
elemsize= key->elemsize;
- if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+ if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3;
/* step 1 init */
cp_key(start, end, tot, basispoin, key, actkb, key->refkey, NULL, mode);
@@ -799,7 +796,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
weight= icuval;
cp= key->elemstr;
- if(mode==KEY_BEZTRIPLE) cp= elemstr;
+ if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr;
ofsp= ofs;
@@ -815,8 +812,14 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
case IPO_BEZTRIPLE:
rel_flerp(12, (float *)poin, (float *)reffrom, (float *)from, weight);
break;
+ default:
+ /* should never happen */
+ if(freefrom) MEM_freeN(freefrom);
+ if(freereffrom) MEM_freeN(freereffrom);
+ BLI_assert(!"invalid 'cp[1]'");
+ return;
}
-
+
poin+= ofsp[0];
cp+= 2;
@@ -826,7 +829,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
reffrom+= elemsize;
from+= elemsize;
- if(mode==KEY_BEZTRIPLE) b+= 2;
+ if(mode == KEY_MODE_BEZTRIPLE) b+= 2;
if(weights) weights++;
}
@@ -838,7 +841,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
}
-static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, int mode)
+static void do_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, const int mode)
{
float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0;
float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0;
@@ -847,29 +850,11 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
char *k1, *k2, *k3, *k4, *freek1, *freek2, *freek3, *freek4;
char *cp, elemstr[8];;
- if(key->from==0) return;
+ /* currently always 0, in future key_pointer_size may assign */
+ ofs[1]= 0;
- if( GS(key->from->name)==ID_ME ) {
- ofs[0]= sizeof(float)*3;
- ofs[1]= 0;
- poinsize= ofs[0];
- }
- else if( GS(key->from->name)==ID_LT ) {
- ofs[0]= sizeof(float)*3;
- ofs[1]= 0;
- poinsize= ofs[0];
- }
- else if( GS(key->from->name)==ID_CU ) {
- if(mode==KEY_BPOINT) {
- ofs[0]= sizeof(float)*4;
- poinsize= ofs[0];
- } else {
- ofs[0]= sizeof(float)*12;
- poinsize= ofs[0] / 3;
- }
-
- ofs[1]= 0;
- }
+ if(!key_pointer_size(key, mode, &poinsize, &ofs[0]))
+ return;
if(end>tot) end= tot;
@@ -971,12 +956,12 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
/* only here, not above! */
elemsize= key->elemsize;
- if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+ if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3;
for(a=start; a<end; a++) {
cp= key->elemstr;
- if(mode==KEY_BEZTRIPLE) cp= elemstr;
+ if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr;
ofsp= ofs;
@@ -992,6 +977,14 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
case IPO_BEZTRIPLE:
flerp(12, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
break;
+ default:
+ /* should never happen */
+ if(freek1) MEM_freeN(freek1);
+ if(freek2) MEM_freeN(freek2);
+ if(freek3) MEM_freeN(freek3);
+ if(freek4) MEM_freeN(freek4);
+ BLI_assert(!"invalid 'cp[1]'");
+ return;
}
poin+= ofsp[0];
@@ -1040,7 +1033,7 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
else k4+= elemsize;
}
- if(mode==KEY_BEZTRIPLE) a+= 2;
+ if(mode == KEY_MODE_BEZTRIPLE) a+= 2;
}
if(freek1) MEM_freeN(freek1);
@@ -1116,7 +1109,7 @@ static float *get_weights_array(Object *ob, char *vgroup)
return NULL;
}
-static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
+static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
{
KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
float cfra, ctime, t[4], delta;
@@ -1137,7 +1130,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
for(a=0; a<tot; a+=step, cfra+= delta) {
- ctime= bsystem_time(scene, 0, cfra, 0.0); // xxx ugly cruft!
+ ctime= bsystem_time(scene, NULL, cfra, 0.0); // xxx ugly cruft!
#if 0 // XXX old animation system
if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
@@ -1151,9 +1144,9 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0)
- do_key(a, a+step, tot, (char *)out, key, actkb, k, t, 0);
+ do_key(a, a+step, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
else
- cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, 0);
+ cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
}
}
else {
@@ -1163,7 +1156,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
for(kb= key->block.first; kb; kb= kb->next)
kb->weights= get_weights_array(ob, kb->vgroup);
- do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
+ do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY);
for(kb= key->block.first; kb; kb= kb->next) {
if(kb->weights) MEM_freeN(kb->weights);
@@ -1186,14 +1179,14 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0)
- do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
+ do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
else
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
}
}
}
-static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, int tot)
+static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, const int tot)
{
Nurb *nu;
int a, step;
@@ -1201,18 +1194,18 @@ static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float
for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
if(nu->bp) {
step= nu->pntsu*nu->pntsv;
- do_key(a, a+step, tot, out, key, actkb, k, t, KEY_BPOINT);
+ do_key(a, a+step, tot, out, key, actkb, k, t, KEY_MODE_BPOINT);
}
else if(nu->bezt) {
step= 3*nu->pntsu;
- do_key(a, a+step, tot, out, key, actkb, k, t, KEY_BEZTRIPLE);
+ do_key(a, a+step, tot, out, key, actkb, k, t, KEY_MODE_BEZTRIPLE);
}
else
step= 0;
}
}
-static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, char *out, int tot)
+static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float UNUSED(ctime), char *out, const int tot)
{
Nurb *nu;
int a, step;
@@ -1220,18 +1213,18 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, cha
for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
if(nu->bp) {
step= nu->pntsu*nu->pntsv;
- do_rel_key(a, a+step, tot, out, key, actkb, KEY_BPOINT);
+ do_rel_key(a, a+step, tot, out, key, actkb, KEY_MODE_BPOINT);
}
else if(nu->bezt) {
step= 3*nu->pntsu;
- do_rel_key(a, a+step, tot, out, key, actkb, KEY_BEZTRIPLE);
+ do_rel_key(a, a+step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE);
}
else
step= 0;
}
}
-static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
+static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
{
Curve *cu= ob->data;
KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
@@ -1240,7 +1233,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
if(key->slurph && key->type!=KEY_RELATIVE) {
Nurb *nu;
- int mode, i= 0, remain= 0, estep, count;
+ int mode=0, i= 0, remain= 0, estep=0, count=0;
delta= (float)key->slurph / tot;
@@ -1255,11 +1248,11 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
for(nu=cu->nurb.first; nu; nu=nu->next) {
if(nu->bp) {
- mode= KEY_BPOINT;
+ mode= KEY_MODE_BPOINT;
estep= nu->pntsu*nu->pntsv;
}
else if(nu->bezt) {
- mode= KEY_BEZTRIPLE;
+ mode= KEY_MODE_BEZTRIPLE;
estep= 3*nu->pntsu;
}
else
@@ -1269,7 +1262,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
while (a < estep) {
if (remain <= 0) {
cfra+= delta;
- ctime= bsystem_time(scene, 0, cfra, 0.0f); // XXX old cruft
+ ctime= bsystem_time(scene, NULL, cfra, 0.0f); // XXX old cruft
ctime /= 100.0f;
CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
@@ -1279,7 +1272,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
}
count= MIN2(remain, estep);
- if (mode == KEY_BEZTRIPLE) {
+ if (mode == KEY_MODE_BEZTRIPLE) {
count += 3 - count % 3;
}
@@ -1317,7 +1310,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
}
}
-static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
+static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
{
Lattice *lt= ob->data;
KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
@@ -1332,7 +1325,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
for(a=0; a<tot; a++, cfra+= delta) {
- ctime= bsystem_time(scene, 0, cfra, 0.0); // XXX old cruft
+ ctime= bsystem_time(scene, NULL, cfra, 0.0); // XXX old cruft
#if 0 // XXX old animation system
if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
@@ -1343,9 +1336,9 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0)
- do_key(a, a+1, tot, (char *)out, key, actkb, k, t, 0);
+ do_key(a, a+1, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
else
- cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, 0);
+ cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
}
}
else {
@@ -1355,7 +1348,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
for(kb= key->block.first; kb; kb= kb->next)
kb->weights= get_weights_array(ob, kb->vgroup);
- do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
+ do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY);
for(kb= key->block.first; kb; kb= kb->next) {
if(kb->weights) MEM_freeN(kb->weights);
@@ -1375,9 +1368,9 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0)
- do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
+ do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
else
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
}
}
@@ -1490,7 +1483,7 @@ Key *ob_get_key(Object *ob)
return NULL;
}
-KeyBlock *add_keyblock(Key *key, char *name)
+KeyBlock *add_keyblock(Key *key, const char *name)
{
KeyBlock *kb;
float curpos= -0.1;
@@ -1707,7 +1700,7 @@ void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
}
}
-void key_to_curve(KeyBlock *kb, Curve *cu, ListBase *nurb)
+void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
{
Nurb *nu;
BezTriple *bezt;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 725f9a34b25..70eba3903d0 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -1,4 +1,4 @@
-/**
+/*
* lattice.c
*
*
@@ -41,6 +41,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_cellalloc.h"
+#include "BLI_utildefines.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -50,6 +51,7 @@
#include "DNA_curve_types.h"
#include "DNA_key_types.h"
+#include "BKE_animsys.h"
#include "BKE_anim.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_displist.h"
@@ -60,7 +62,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
-#include "BKE_utildefines.h"
+
#include "BKE_deform.h"
//XXX #include "BIF_editdeform.h"
@@ -182,7 +184,7 @@ void resizelattice(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
MEM_freeN(vertexCos);
}
-Lattice *add_lattice(char *name)
+Lattice *add_lattice(const char *name)
{
Lattice *lt;
@@ -204,10 +206,6 @@ Lattice *copy_lattice(Lattice *lt)
ltn= copy_libblock(lt);
ltn->def= MEM_dupallocN(lt->def);
-
-#if 0 // XXX old animation system
- id_us_plus((ID *)ltn->ipo);
-#endif // XXX old animation system
ltn->key= copy_key(ltn->key);
if(ltn->key) ltn->key->from= (ID *)ltn;
@@ -234,6 +232,12 @@ void free_lattice(Lattice *lt)
MEM_freeN(editlt);
MEM_freeN(lt->editlatt);
}
+
+ /* free animation data */
+ if (lt->adt) {
+ BKE_free_animdata(&lt->id);
+ lt->adt= NULL;
+ }
}
@@ -248,11 +252,11 @@ void make_local_lattice(Lattice *lt)
* - mixed: make copy
*/
- if(lt->id.lib==0) return;
+ if(lt->id.lib==NULL) return;
if(lt->id.us==1) {
- lt->id.lib= 0;
+ lt->id.lib= NULL;
lt->id.flag= LIB_LOCAL;
- new_id(0, (ID *)lt, 0);
+ new_id(NULL, (ID *)lt, NULL);
return;
}
@@ -266,9 +270,9 @@ void make_local_lattice(Lattice *lt)
}
if(local && lib==0) {
- lt->id.lib= 0;
+ lt->id.lib= NULL;
lt->id.flag= LIB_LOCAL;
- new_id(0, (ID *)lt, 0);
+ new_id(NULL, (ID *)lt, NULL);
}
else if(local && lib) {
ltn= copy_lattice(lt);
@@ -278,7 +282,7 @@ void make_local_lattice(Lattice *lt)
while(ob) {
if(ob->data==lt) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
ob->data= ltn;
ltn->id.us++;
lt->id.us--;
@@ -600,16 +604,6 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C
}
#endif
-
- static float q_x90d[4] = {0.70710676908493, 0.70710676908493, 0.0, 0.0}; // float rot_axis[3]= {1,0,0}; axis_angle_to_quat(q, rot_axis, 90 * (M_PI / 180));
- static float q_y90d[4] = {0.70710676908493, 0.0, 0.70710676908493, 0.0}; // float rot_axis[3]= {0,1,0}; axis_angle_to_quat(q, rot_axis, 90 * (M_PI / 180));
- static float q_z90d[4] = {0.70710676908493, 0.0, 0.0, 0.70710676908493}; // float rot_axis[3]= {0,0,2}; axis_angle_to_quat(q, rot_axis, 90 * (M_PI / 180));
-
- static float q_nx90d[4] = {0.70710676908493, -0.70710676908493, 0.0, 0.0}; // float rot_axis[3]= {1,0,0}; axis_angle_to_quat(q, rot_axis, -90 * (M_PI / 180));
- static float q_ny90d[4] = {0.70710676908493, 0.0, -0.70710676908493, 0.0}; // float rot_axis[3]= {0,1,0}; axis_angle_to_quat(q, rot_axis, -90 * (M_PI / 180));
- static float q_nz90d[4] = {0.70710676908493, 0.0, 0.0, -0.70710676908493}; // float rot_axis[3]= {0,0,2}; axis_angle_to_quat(q, rot_axis, -90 * (M_PI / 180));
-
-
if(cd->no_rot_axis) { /* set by caller */
/* this is not exactly the same as 2.4x, since the axis is having rotation removed rather then
@@ -636,53 +630,18 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C
* Notice X,Y,Z Up all have light colors and each ordered CCW.
*
* Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
+ *
+ * note: moved functions into quat_apply_track/vec_apply_track
* */
+ copy_qt_qt(quat, new_quat);
+ copy_v3_v3(cent, co);
+
+ /* zero the axis which is not used,
+ * the big block of text above now applies to these 3 lines */
+ quat_apply_track(quat, axis-1, (axis==1 || axis==3) ? 1:0); /* up flag is a dummy, set so no rotation is done */
+ vec_apply_track(cent, axis-1);
+ cent[axis < 4 ? axis-1 : axis-4]= 0.0f;
- switch(axis) {
- case MOD_CURVE_POSX:
- mul_qt_qtqt(quat, new_quat, q_y90d);
-
- cent[0]= 0.0;
- cent[1]= co[2];
- cent[2]= co[1];
- break;
- case MOD_CURVE_NEGX:
- mul_qt_qtqt(quat, new_quat, q_ny90d);
-
- cent[0]= 0.0;
- cent[1]= -co[1];
- cent[2]= co[2];
-
- break;
- case MOD_CURVE_POSY:
- mul_qt_qtqt(quat, new_quat, q_x90d);
-
- cent[0]= co[2];
- cent[1]= 0.0;
- cent[2]= -co[0];
- break;
- case MOD_CURVE_NEGY:
- mul_qt_qtqt(quat, new_quat, q_nx90d);
-
- cent[0]= -co[0];
- cent[1]= 0.0;
- cent[2]= -co[2];
- break;
- case MOD_CURVE_POSZ:
- mul_qt_qtqt(quat, new_quat, q_z90d);
-
- cent[0]= co[1];
- cent[1]= -co[0];
- cent[2]= 0.0;
- break;
- case MOD_CURVE_NEGZ:
- mul_qt_qtqt(quat, new_quat, q_nz90d);
-
- cent[0]= co[0];
- cent[1]= -co[1];
- cent[2]= 0.0;
- break;
- }
/* scale if enabled */
if(cu->flag & CU_PATH_RADIUS)
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 687b212ec2e..cb96f549829 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -39,6 +39,7 @@
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
+#include <assert.h>
#include "MEM_guardedalloc.h"
@@ -66,9 +67,10 @@
#include "DNA_world_types.h"
#include "DNA_gpencil_types.h"
-
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
+
#include "BKE_animsys.h"
#include "BKE_context.h"
@@ -136,8 +138,14 @@ void id_us_plus(ID *id)
void id_us_min(ID *id)
{
- if(id)
- id->us--;
+ if(id) {
+ if(id->us<2 && (id->flag & LIB_FAKEUSER))
+ id->us= 1;
+ else if(id->us<=0)
+ printf("ID user decrement error: %s \n", id->name);
+ else
+ id->us--;
+ }
}
int id_make_local(ID *id, int test)
@@ -302,7 +310,7 @@ int id_copy(ID *id, ID **newid, int test)
if(!test) *newid= (ID*)copy_action((bAction*)id);
return 1;
case ID_NT:
- if(!test) *newid= (ID*)ntreeCopyTree((bNodeTree*)id, 0);
+ if(!test) *newid= (ID*)ntreeCopyTree((bNodeTree*)id);
return 1;
case ID_BR:
if(!test) *newid= (ID*)copy_brush((Brush*)id);
@@ -335,7 +343,7 @@ int id_unlink(ID *id, int test)
break;
case ID_OB:
if(test) return 1;
- unlink_object(NULL, (Object*)id);
+ unlink_object((Object*)id);
break;
}
@@ -411,7 +419,7 @@ ListBase *which_libbase(Main *mainlib, short type)
case ID_GD:
return &(mainlib->gpencil);
}
- return 0;
+ return NULL;
}
/* Flag all ids in listbase */
@@ -442,7 +450,7 @@ void recalc_all_library_objects(Main *main)
/* flag for full recalc */
for(ob=main->object.first; ob; ob=ob->id.next)
if(ob->id.lib)
- ob->recalc |= OB_RECALC_ALL;
+ ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
}
/* note: MAX_LIBARRAY define should match this code */
@@ -450,11 +458,13 @@ int set_listbasepointers(Main *main, ListBase **lb)
{
int a = 0;
- /* BACKWARDS! also watch order of free-ing! (mesh<->mat) */
-
+ /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last.
+ * This is important because freeing data decreases usercounts of other datablocks,
+ * if this data is its self freed it can crash. */
lb[a++]= &(main->ipo);
lb[a++]= &(main->action); // xxx moved here to avoid problems when freeing with animato (aligorith)
lb[a++]= &(main->key);
+ lb[a++]= &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */
lb[a++]= &(main->nodetree);
lb[a++]= &(main->image);
lb[a++]= &(main->tex);
@@ -481,14 +491,13 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[a++]= &(main->brush);
lb[a++]= &(main->script);
lb[a++]= &(main->particle);
-
+
lb[a++]= &(main->world);
lb[a++]= &(main->screen);
lb[a++]= &(main->object);
lb[a++]= &(main->scene);
lb[a++]= &(main->library);
lb[a++]= &(main->wm);
- lb[a++]= &(main->gpencil);
lb[a]= NULL;
@@ -617,24 +626,24 @@ void *alloc_libblock(ListBase *lb, short type, const char *name)
/* by spec, animdata is first item after ID */
/* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */
-static void id_copy_animdata(ID *id)
+static void id_copy_animdata(ID *id, const short do_action)
{
AnimData *adt= BKE_animdata_from_id(id);
if (adt) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
- iat->adt= BKE_copy_animdata(iat->adt);
+ iat->adt= BKE_copy_animdata(iat->adt, do_action); /* could be set to FALSE, need to investigate */
}
}
/* material nodes use this since they are not treated as libdata */
-void copy_libblock_data(ID *id, const ID *id_from)
+void copy_libblock_data(ID *id, const ID *id_from, const short do_action)
{
if (id_from->properties)
id->properties = IDP_CopyProperty(id_from->properties);
/* the duplicate should get a copy of the animdata */
- id_copy_animdata(id);
+ id_copy_animdata(id, do_action);
}
/* used everywhere in blenkernel */
@@ -649,11 +658,9 @@ void *copy_libblock(void *rt)
lb= which_libbase(G.main, GS(id->name));
idn= alloc_libblock(lb, GS(id->name), id->name+2);
-
- if(idn==NULL) {
- printf("ERROR: Illegal ID name for %s (Crashing now)\n", id->name);
- }
-
+
+ assert(idn != NULL);
+
idn_len= MEM_allocN_len(idn);
if(idn_len - sizeof(ID) > 0) {
cp= (char *)id;
@@ -664,12 +671,12 @@ void *copy_libblock(void *rt)
id->newid= idn;
idn->flag |= LIB_NEW;
- copy_libblock_data(idn, id);
+ copy_libblock_data(idn, id, FALSE);
return idn;
}
-static void free_library(Library *lib)
+static void free_library(Library *UNUSED(lib))
{
/* no freeing needed for libraries yet */
}
@@ -681,7 +688,7 @@ void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) )
free_windowmanager_cb= func;
}
-void animdata_dtar_clear_cb(ID *id, AnimData *adt, void *userdata)
+static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
{
ChannelDriver *driver;
FCurve *fcu;
@@ -822,7 +829,7 @@ void free_libblock_us(ListBase *lb, void *idv) /* test users */
else printf("ERROR block %s users %d\n", id->name, id->us);
}
if(id->us==0) {
- if( GS(id->name)==ID_OB ) unlink_object(NULL, (Object *)id);
+ if( GS(id->name)==ID_OB ) unlink_object((Object *)id);
free_libblock(lb, id);
}
@@ -851,7 +858,7 @@ void free_main(Main *mainvar)
/* ***************** ID ************************ */
-ID *find_id(char *type, char *name) /* type: "OB" or "MA" etc */
+ID *find_id(const char *type, const char *name) /* type: "OB" or "MA" etc */
{
ListBase *lb= which_libbase(G.main, GS(type));
return BLI_findstring(lb, name, offsetof(ID, name) + 2);
@@ -913,7 +920,7 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor
BLI_dynstr_append(pupds, buf);
BLI_dynstr_append(pupds, id->name+2);
- sprintf(buf, "%%x%d", i+1);
+ BLI_snprintf(buf, sizeof(buf), "%%x%d", i+1);
BLI_dynstr_append(pupds, buf);
/* icon */
@@ -924,7 +931,7 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor
case ID_IM: /* fall through */
case ID_WO: /* fall through */
case ID_LA: /* fall through */
- sprintf(buf, "%%i%d", BKE_icon_getid(id) );
+ BLI_snprintf(buf, sizeof(buf), "%%i%d", BKE_icon_getid(id) );
BLI_dynstr_append(pupds, buf);
break;
default:
@@ -940,7 +947,7 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor
/* used by headerbuttons.c buttons.c editobject.c editseq.c */
/* if nr==NULL no MAX_IDPUP, this for non-header browsing */
-void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr)
+void IDnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
{
DynStr *pupds= BLI_dynstr_new();
@@ -962,7 +969,7 @@ void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb,
}
/* skips viewer images */
-void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr)
+void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
{
DynStr *pupds= BLI_dynstr_new();
@@ -983,35 +990,6 @@ void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb
BLI_dynstr_free(pupds);
}
-
-/* used by buttons.c library.c mball.c */
-int splitIDname(char *name, char *left, int *nr)
-{
- int a;
-
- *nr= 0;
- strncpy(left, name, 21);
-
- a= strlen(name);
- if(a>1 && name[a-1]=='.') return a;
-
- while(a--) {
- if( name[a]=='.' ) {
- left[a]= 0;
- *nr= atol(name+a+1);
- return a;
- }
- if( isdigit(name[a])==0 ) break;
-
- left[a]= 0;
- }
-
- for(a= 0; name[a]; a++)
- left[a]= name[a];
-
- return a;
-}
-
static void sort_alpha_id(ListBase *lb, ID *id)
{
ID *idtest;
@@ -1029,7 +1007,7 @@ static void sort_alpha_id(ListBase *lb, ID *id)
idtest= idtest->next;
}
/* as last */
- if(idtest==0) {
+ if(idtest==NULL) {
BLI_addtail(lb, id);
}
}
@@ -1040,7 +1018,7 @@ static void sort_alpha_id(ListBase *lb, ID *id)
* Check to see if there is an ID with the same name as 'name'.
* Returns the ID if so, if not, returns NULL
*/
-static ID *is_dupid(ListBase *lb, ID *id, char *name)
+static ID *is_dupid(ListBase *lb, ID *id, const char *name)
{
ID *idtest=NULL;
@@ -1091,7 +1069,7 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
memset(in_use, 0, sizeof(in_use));
/* get name portion, number portion ("name.number") */
- left_len= splitIDname(name, left, &nr);
+ left_len= BLI_split_name_num(left, &nr, name, '.');
/* if new name will be too long, truncate it */
if(nr > 999 && left_len > 16) {
@@ -1108,7 +1086,7 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
(idtest->lib == NULL) &&
(*name == *(idtest->name+2)) &&
(strncmp(name, idtest->name+2, left_len)==0) &&
- (splitIDname(idtest->name+2, leftest, &nrtest) == left_len)
+ (BLI_split_name_num(leftest, &nrtest, idtest->name+2, '.') == left_len)
) {
if(nrtest < sizeof(in_use))
in_use[nrtest]= 1; /* mark as used */
@@ -1146,11 +1124,11 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
/* this would overflow name buffer */
left[16] = 0;
/* left_len = 16; */ /* for now this isnt used again */
- memcpy(name, left, sizeof(char) * 16);
+ memcpy(name, left, sizeof(char) * 17);
continue;
}
/* this format specifier is from hell... */
- sprintf(name, "%s.%.3d", left, nr);
+ BLI_snprintf(name, sizeof(id->name) - 2,"%s.%.3d", left, nr);
return 1;
}
@@ -1211,7 +1189,7 @@ int new_id(ListBase *lb, ID *id, const char *tname)
}
/* next to indirect usage in read/writefile also in editobject.c scene.c */
-void clear_id_newpoins()
+void clear_id_newpoins(void)
{
ListBase *lbarray[MAX_LIBARRAY];
ID *id;
@@ -1221,7 +1199,7 @@ void clear_id_newpoins()
while(a--) {
id= lbarray[a]->first;
while(id) {
- id->newid= 0;
+ id->newid= NULL;
id->flag &= ~LIB_NEW;
id= id->next;
}
@@ -1234,7 +1212,7 @@ static void image_fix_relative_path(Image *ima)
if(ima->id.lib==NULL) return;
if(strncmp(ima->name, "//", 2)==0) {
BLI_path_abs(ima->name, ima->id.lib->filepath);
- BLI_path_rel(ima->name, G.sce);
+ BLI_path_rel(ima->name, G.main->name);
}
}
@@ -1279,25 +1257,43 @@ static void lib_indirect_test_id(ID *id, Library *lib)
}
}
-void tag_main(struct Main *mainvar, int tag)
+void tag_main_lb(ListBase *lb, const short tag)
{
- ListBase *lbarray[MAX_LIBARRAY];
ID *id;
+ if(tag) {
+ for(id= lb->first; id; id= id->next) {
+ id->flag |= LIB_DOIT;
+ }
+ }
+ else {
+ for(id= lb->first; id; id= id->next) {
+ id->flag &= ~LIB_DOIT;
+ }
+ }
+}
+
+void tag_main_idcode(struct Main *mainvar, const short type, const short tag)
+{
+ ListBase *lb= which_libbase(mainvar, type);
+
+ tag_main_lb(lb, tag);
+}
+
+void tag_main(struct Main *mainvar, const short tag)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
int a;
a= set_listbasepointers(mainvar, lbarray);
while(a--) {
- for(id= lbarray[a]->first; id; id= id->next) {
- if(tag) id->flag |= LIB_DOIT;
- else id->flag &= ~LIB_DOIT;
- }
+ tag_main_lb(lbarray[a], tag);
}
}
/* if lib!=NULL, only all from lib local */
void all_local(Library *lib, int untagged_only)
{
- ListBase *lbarray[MAX_LIBARRAY], tempbase={0, 0};
+ ListBase *lbarray[MAX_LIBARRAY], tempbase={NULL, NULL};
ID *id, *idn;
int a;
@@ -1326,7 +1322,7 @@ void all_local(Library *lib, int untagged_only)
image_fix_relative_path((Image *)id);
id->lib= NULL;
- new_id(lbarray[a], id, 0); /* new_id only does it with double names */
+ new_id(lbarray[a], id, NULL); /* new_id only does it with double names */
sort_alpha_id(lbarray[a], id);
}
}
@@ -1338,7 +1334,7 @@ void all_local(Library *lib, int untagged_only)
while( (id=tempbase.first) ) {
BLI_remlink(&tempbase, id);
BLI_addtail(lbarray[a], id);
- new_id(lbarray[a], id, 0);
+ new_id(lbarray[a], id, NULL);
}
}
@@ -1359,7 +1355,7 @@ void test_idbutton(char *name)
lb= which_libbase(G.main, GS(name-2) );
- if(lb==0) return;
+ if(lb==NULL) return;
/* search for id */
idtest= BLI_findstring(lb, name, offsetof(ID, name) + 2);
@@ -1386,14 +1382,14 @@ void text_idbutton(struct ID *id, char *text)
}
else {
text[0]= '\0';
-}
+ }
}
-void rename_id(ID *id, char *name)
+void rename_id(ID *id, const char *name)
{
ListBase *lb;
- strncpy(id->name+2, name, 21);
+ BLI_strncpy(id->name+2, name, sizeof(id->name)-2);
lb= which_libbase(G.main, GS(id->name) );
new_id(lb, id, name);
@@ -1402,7 +1398,7 @@ void rename_id(ID *id, char *name)
void name_uiprefix_id(char *name, ID *id)
{
name[0] = id->lib ? 'L':' ';
- name[1] = id->flag & LIB_FAKEUSER ? 'F':' ';
+ name[1] = id->flag & LIB_FAKEUSER ? 'F': (id->us==0)?'0':' ';
name[2] = ' ';
strcpy(name+3, id->name+2);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 7e52f746ebc..0b1cbd60432 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -44,6 +44,8 @@
#include "DNA_scene_types.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BKE_animsys.h"
#include "BKE_displist.h"
@@ -54,7 +56,7 @@
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
-#include "BKE_utildefines.h"
+
#include "GPU_material.h"
@@ -84,7 +86,8 @@ void free_material(Material *ma)
BKE_free_animdata((ID *)ma);
- BKE_previewimg_free(&ma->preview);
+ if(ma->preview)
+ BKE_previewimg_free(&ma->preview);
BKE_icon_delete((struct ID*)ma);
ma->id.icon_id = 0;
@@ -185,7 +188,7 @@ void init_material(Material *ma)
ma->preview = NULL;
}
-Material *add_material(char *name)
+Material *add_material(const char *name)
{
Material *ma;
@@ -196,6 +199,7 @@ Material *add_material(char *name)
return ma;
}
+/* XXX keep synced with next function */
Material *copy_material(Material *ma)
{
Material *man;
@@ -203,9 +207,6 @@ Material *copy_material(Material *ma)
man= copy_libblock(ma);
-#if 0 // XXX old animation system
- id_us_plus((ID *)man->ipo);
-#endif // XXX old animation system
id_lib_extern((ID *)man->group);
for(a=0; a<MAX_MTEX; a++) {
@@ -222,7 +223,7 @@ Material *copy_material(Material *ma)
if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview);
if(ma->nodetree) {
- man->nodetree= ntreeCopyTree(ma->nodetree, 0); /* 0 == full new tree */
+ man->nodetree= ntreeCopyTree(ma->nodetree); /* 0 == full new tree */
}
man->gpumaterial.first= man->gpumaterial.last= NULL;
@@ -230,6 +231,38 @@ Material *copy_material(Material *ma)
return man;
}
+/* XXX (see above) material copy without adding to main dbase */
+Material *localize_material(Material *ma)
+{
+ Material *man;
+ int a;
+
+ man= copy_libblock(ma);
+ BLI_remlink(&G.main->mat, man);
+
+ for(a=0; a<MAX_MTEX; a++) {
+ if(ma->mtex[a]) {
+ man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
+ memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
+ /* free_material decrements! */
+ id_us_plus((ID *)man->mtex[a]->tex);
+ }
+ }
+
+ if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col);
+ if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec);
+
+ man->preview = NULL;
+
+ if(ma->nodetree) {
+ man->nodetree= ntreeLocalize(ma->nodetree);
+ }
+
+ man->gpumaterial.first= man->gpumaterial.last= NULL;
+
+ return man;
+}
+
void make_local_material(Material *ma)
{
Main *bmain= G.main;
@@ -245,11 +278,11 @@ void make_local_material(Material *ma)
* - mixed: make copy
*/
- if(ma->id.lib==0) return;
+ if(ma->id.lib==NULL) return;
if(ma->id.us==1) {
- ma->id.lib= 0;
+ ma->id.lib= NULL;
ma->id.flag= LIB_LOCAL;
- new_id(0, (ID *)ma, 0);
+ new_id(NULL, (ID *)ma, NULL);
for(a=0; a<MAX_MTEX; a++) {
if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex);
}
@@ -311,14 +344,14 @@ void make_local_material(Material *ma)
}
if(local && lib==0) {
- ma->id.lib= 0;
+ ma->id.lib= NULL;
ma->id.flag= LIB_LOCAL;
for(a=0; a<MAX_MTEX; a++) {
if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex);
}
- new_id(0, (ID *)ma, 0);
+ new_id(NULL, (ID *)ma, NULL);
}
else if(local && lib) {
@@ -331,7 +364,7 @@ void make_local_material(Material *ma)
if(ob->mat) {
for(a=0; a<ob->totcol; a++) {
if(ob->mat[a]==ma) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
ob->mat[a]= man;
man->id.us++;
ma->id.us--;
@@ -347,7 +380,7 @@ void make_local_material(Material *ma)
if(me->mat) {
for(a=0; a<me->totcol; a++) {
if(me->mat[a]==ma) {
- if(me->id.lib==0) {
+ if(me->id.lib==NULL) {
me->mat[a]= man;
man->id.us++;
ma->id.us--;
@@ -363,7 +396,7 @@ void make_local_material(Material *ma)
if(cu->mat) {
for(a=0; a<cu->totcol; a++) {
if(cu->mat[a]==ma) {
- if(cu->id.lib==0) {
+ if(cu->id.lib==NULL) {
cu->mat[a]= man;
man->id.us++;
ma->id.us--;
@@ -379,7 +412,7 @@ void make_local_material(Material *ma)
if(mb->mat) {
for(a=0; a<mb->totcol; a++) {
if(mb->mat[a]==ma) {
- if(mb->id.lib==0) {
+ if(mb->id.lib==NULL) {
mb->mat[a]= man;
man->id.us++;
ma->id.us--;
@@ -445,7 +478,7 @@ Material ***give_matarar_id(ID *id)
return &(((Curve *)id)->mat);
break;
case ID_MB:
- return &(((Curve *)id)->mat);
+ return &(((MetaBall *)id)->mat);
break;
}
return NULL;
@@ -461,7 +494,7 @@ short *give_totcolp_id(ID *id)
return &(((Curve *)id)->totcol);
break;
case ID_MB:
- return &(((Curve *)id)->totcol);
+ return &(((MetaBall *)id)->totcol);
break;
}
return NULL;
@@ -492,6 +525,7 @@ Material *material_pop_id(ID *id, int index)
short *totcol= give_totcolp_id(id);
if(index >= 0 && index < (*totcol)) {
ret= (*matar)[index];
+ id_us_min((ID *)ret);
if(*totcol <= 1) {
*totcol= 0;
MEM_freeN(*matar);
@@ -529,6 +563,10 @@ Material *give_current_material(Object *ob, int act)
totcolp= give_totcolp(ob);
if(totcolp==NULL || ob->totcol==0) return NULL;
+ if(act<0) {
+ printf("no!\n");
+ }
+
if(act>ob->totcol) act= ob->totcol;
else if(act<=0) act= 1;
@@ -545,7 +583,7 @@ Material *give_current_material(Object *ob, int act)
matarar= give_matarar(ob);
if(matarar && *matarar) ma= (*matarar)[act-1];
- else ma= 0;
+ else ma= NULL;
}
@@ -555,7 +593,7 @@ Material *give_current_material(Object *ob, int act)
ID *material_from(Object *ob, int act)
{
- if(ob==0) return 0;
+ if(ob==NULL) return NULL;
if(ob->totcol==0) return ob->data;
if(act==0) act= 1;
@@ -589,67 +627,53 @@ Material *give_node_material(Material *ma)
/* from misc_util: flip the bytes from x */
/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
-void test_object_materials(ID *id)
+void resize_object_material(Object *ob, const short totcol)
{
- /* make the ob mat-array same size as 'ob->data' mat-array */
- Object *ob;
- Mesh *me;
- Curve *cu;
- MetaBall *mb;
Material **newmatar;
char *newmatbits;
- int totcol=0;
-
- if(id==0) return;
- if( GS(id->name)==ID_ME ) {
- me= (Mesh *)id;
- totcol= me->totcol;
+ if(totcol==0) {
+ if(ob->totcol) {
+ MEM_freeN(ob->mat);
+ MEM_freeN(ob->matbits);
+ ob->mat= NULL;
+ ob->matbits= NULL;
+ }
}
- else if( GS(id->name)==ID_CU ) {
- cu= (Curve *)id;
- totcol= cu->totcol;
+ else if(ob->totcol<totcol) {
+ newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar");
+ newmatbits= MEM_callocN(sizeof(char)*totcol, "newmatbits");
+ if(ob->totcol) {
+ memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol);
+ memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol);
+ MEM_freeN(ob->mat);
+ MEM_freeN(ob->matbits);
+ }
+ ob->mat= newmatar;
+ ob->matbits= newmatbits;
}
- else if( GS(id->name)==ID_MB ) {
- mb= (MetaBall *)id;
- totcol= mb->totcol;
+ ob->totcol= totcol;
+ if(ob->totcol && ob->actcol==0) ob->actcol= 1;
+ if(ob->actcol>ob->totcol) ob->actcol= ob->totcol;
+}
+
+void test_object_materials(ID *id)
+{
+ /* make the ob mat-array same size as 'ob->data' mat-array */
+ Object *ob;
+ short *totcol;
+
+ if(id==NULL || (totcol=give_totcolp_id(id))==NULL) {
+ return;
}
- else return;
- ob= G.main->object.first;
- while(ob) {
-
+ for(ob= G.main->object.first; ob; ob= ob->id.next) {
if(ob->data==id) {
-
- if(totcol==0) {
- if(ob->totcol) {
- MEM_freeN(ob->mat);
- MEM_freeN(ob->matbits);
- ob->mat= NULL;
- ob->matbits= NULL;
- }
- }
- else if(ob->totcol<totcol) {
- newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar");
- newmatbits= MEM_callocN(sizeof(char)*totcol, "newmatbits");
- if(ob->totcol) {
- memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol);
- memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol);
- MEM_freeN(ob->mat);
- MEM_freeN(ob->matbits);
- }
- ob->mat= newmatar;
- ob->matbits= newmatbits;
- }
- ob->totcol= totcol;
- if(ob->totcol && ob->actcol==0) ob->actcol= 1;
- if(ob->actcol>ob->totcol) ob->actcol= ob->totcol;
+ resize_object_material(ob, *totcol);
}
- ob= ob->id.next;
}
}
-
void assign_material(Object *ob, Material *ma, int act)
{
Material *mao, **matar, ***matarar;
@@ -664,7 +688,7 @@ void assign_material(Object *ob, Material *ma, int act)
totcolp= give_totcolp(ob);
matarar= give_matarar(ob);
- if(totcolp==0 || matarar==0) return;
+ if(totcolp==NULL || matarar==NULL) return;
if(act > *totcolp) {
matar= MEM_callocN(sizeof(void *)*act, "matarray1");
@@ -758,11 +782,18 @@ int object_add_material_slot(Object *ob)
{
Material *ma;
- if(ob==0) return FALSE;
+ if(ob==NULL) return FALSE;
if(ob->totcol>=MAXMAT) return FALSE;
ma= give_current_material(ob, ob->actcol);
+ if(ma == NULL)
+ ma= add_material("Material");
+ else
+ ma= copy_material(ma);
+
+ id_us_min(&ma->id);
+
assign_material(ob, ma, ob->totcol+1);
ob->actcol= ob->totcol;
return TRUE;
@@ -786,10 +817,10 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
ma->texco |= mtex->texco;
ma->mapto |= mtex->mapto;
- if(r_mode & R_OSA) {
- if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA;
- else if(mtex->texflag & MTEX_NEW_BUMP) ma->texco |= TEXCO_OSA; // NEWBUMP: need texture derivatives for procedurals as well
- }
+
+ /* always get derivatives for these textures */
+ if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA;
+ else if(mtex->texflag & (MTEX_COMPAT_BUMP|MTEX_3TAP_BUMP|MTEX_5TAP_BUMP)) ma->texco |= TEXCO_OSA;
if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1;
else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT|TEXCO_SPEED)) needuv= 1;
@@ -841,7 +872,7 @@ static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode
if(ma!=basemat) {
do_init_render_material(ma, r_mode, amb);
basemat->texco |= ma->texco;
- basemat->mode_l |= ma->mode_l;
+ basemat->mode_l |= ma->mode_l & ~(MA_TRANSP|MA_ZTRANSP|MA_RAYTRANSP);
}
}
else if(node->type==NODE_GROUP)
@@ -933,7 +964,7 @@ int material_in_material(Material *parmat, Material *mat)
/* ****************** */
-char colname_array[125][20]= {
+static char colname_array[125][20]= {
"Black","DarkRed","HalfRed","Red","Red",
"DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed",
"HalfGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange",
@@ -966,7 +997,7 @@ void automatname(Material *ma)
int nr, r, g, b;
float ref;
- if(ma==0) return;
+ if(ma==NULL) return;
if(ma->mode & MA_SHLESS) ref= 1.0;
else ref= ma->ref;
@@ -1014,7 +1045,7 @@ int object_remove_material_slot(Object *ob)
if(*totcolp==0) {
MEM_freeN(*matarar);
- *matarar= 0;
+ *matarar= NULL;
}
actcol= ob->actcol;
@@ -1037,7 +1068,7 @@ int object_remove_material_slot(Object *ob)
if(obt->totcol==0) {
MEM_freeN(obt->mat);
MEM_freeN(obt->matbits);
- obt->mat= 0;
+ obt->mat= NULL;
obt->matbits= NULL;
}
}
@@ -1318,8 +1349,7 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
/* copy/paste buffer, if we had a propper py api that would be better */
Material matcopybuf;
-// MTex mtexcopybuf;
-static short matcopied=0;
+static short matcopied= 0;
void clear_matcopybuf(void)
{
@@ -1329,7 +1359,6 @@ void clear_matcopybuf(void)
void free_matcopybuf(void)
{
-// extern MTex mtexcopybuf; /* buttons.c */
int a;
for(a=0; a<MAX_MTEX; a++) {
@@ -1350,7 +1379,6 @@ void free_matcopybuf(void)
MEM_freeN(matcopybuf.nodetree);
matcopybuf.nodetree= NULL;
}
-// default_mtex(&mtexcopybuf);
matcopied= 0;
}
@@ -1373,7 +1401,7 @@ void copy_matcopybuf(Material *ma)
matcopybuf.mtex[a]= MEM_dupallocN(mtex);
}
}
- matcopybuf.nodetree= ntreeCopyTree(ma->nodetree, 0);
+ matcopybuf.nodetree= ntreeCopyTree(ma->nodetree);
matcopybuf.preview= NULL;
matcopybuf.gpumaterial.first= matcopybuf.gpumaterial.last= NULL;
matcopied= 1;
@@ -1401,7 +1429,7 @@ void paste_matcopybuf(Material *ma)
MEM_freeN(ma->nodetree);
}
- GPU_materials_free(ma);
+ GPU_material_free(ma);
id= (ma->id);
memcpy(ma, &matcopybuf, sizeof(Material));
@@ -1418,11 +1446,5 @@ void paste_matcopybuf(Material *ma)
}
}
- ma->nodetree= ntreeCopyTree(matcopybuf.nodetree, 0);
-
- /*
- BIF_preview_changed(ID_MA);
- BIF_undo_push("Paste material settings");
- scrarea_queue_winredraw(curarea);
- */
+ ma->nodetree= ntreeCopyTree(matcopybuf.nodetree);
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index e6f38e04d76..4f44875b7ea 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -1,4 +1,4 @@
-/** mball.c
+/* mball.c
*
* MetaBalls are created from a single Object (with a name without number in it),
* here the DispList and BoundBox also is located.
@@ -48,8 +48,9 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
-#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -76,7 +77,7 @@ void unlink_mball(MetaBall *mb)
for(a=0; a<mb->totcol; a++) {
if(mb->mat[a]) mb->mat[a]->id.us--;
- mb->mat[a]= 0;
+ mb->mat[a]= NULL;
}
}
@@ -86,14 +87,17 @@ void free_mball(MetaBall *mb)
{
unlink_mball(mb);
- if(mb->adt) BKE_free_animdata((ID *)mb);
+ if(mb->adt) {
+ BKE_free_animdata((ID *)mb);
+ mb->adt = NULL;
+ }
if(mb->mat) MEM_freeN(mb->mat);
if(mb->bb) MEM_freeN(mb->bb);
BLI_freelistN(&mb->elems);
if(mb->disp.first) freedisplist(&mb->disp);
}
-MetaBall *add_mball(char *name)
+MetaBall *add_mball(const char *name)
{
MetaBall *mb;
@@ -138,9 +142,9 @@ void make_local_mball(MetaBall *mb)
* - mixed: make copy
*/
- if(mb->id.lib==0) return;
+ if(mb->id.lib==NULL) return;
if(mb->id.us==1) {
- mb->id.lib= 0;
+ mb->id.lib= NULL;
mb->id.flag= LIB_LOCAL;
return;
}
@@ -155,7 +159,7 @@ void make_local_mball(MetaBall *mb)
}
if(local && lib==0) {
- mb->id.lib= 0;
+ mb->id.lib= NULL;
mb->id.flag= LIB_LOCAL;
}
else if(local && lib) {
@@ -166,7 +170,7 @@ void make_local_mball(MetaBall *mb)
while(ob) {
if(ob->data==mb) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
ob->data= mbn;
mbn->id.us++;
mb->id.us--;
@@ -238,7 +242,7 @@ void tex_space_mball(Object *ob)
float *data, min[3], max[3], loc[3], size[3];
int tot, doit=0;
- if(ob->bb==0) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox");
+ if(ob->bb==NULL) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox");
bb= ob->bb;
/* Weird one, this. */
@@ -309,6 +313,19 @@ float *make_orco_mball(Object *ob, ListBase *dispbase)
return orcodata;
}
+
+/* Note on mball basis stuff 2.5x (this is a can of worms)
+ * This really needs a rewrite/refactorm its totally broken in anything other then basic cases
+ * Multiple Scenes + Set Scenes & mixing mball basis SHOULD work but fails to update the depsgraph on rename
+ * and linking into scenes or removal of basis mball. so take care when changing this code.
+ *
+ * Main idiot thing here is that the system returns find_basis_mball() objects which fail a is_basis_mball() test.
+ *
+ * Not only that but the depsgraph and ther areas depend on this behavior!, so making small fixes here isnt worth it.
+ * - campbell
+ */
+
+
/** \brief Test, if Object *ob is basic MetaBall.
*
* It test last character of Object ID name. If last character
@@ -330,8 +347,8 @@ int is_mball_basis_for(Object *ob1, Object *ob2)
int basis1nr, basis2nr;
char basis1name[32], basis2name[32];
- splitIDname(ob1->id.name+2, basis1name, &basis1nr);
- splitIDname(ob2->id.name+2, basis2name, &basis2nr);
+ BLI_split_name_num(basis1name, &basis1nr, ob1->id.name+2, '.');
+ BLI_split_name_num(basis2name, &basis2nr, ob2->id.name+2, '.');
if(!strcmp(basis1name, basis2name)) return is_basis_mball(ob1);
else return 0;
@@ -352,16 +369,16 @@ void copy_mball_properties(Scene *scene, Object *active_object)
int basisnr, obnr;
char basisname[32], obname[32];
- splitIDname(active_object->id.name+2, basisname, &basisnr);
+ BLI_split_name_num(basisname, &basisnr, active_object->id.name+2, '.');
/* XXX recursion check, see scene.c, just too simple code this next_object() */
- if(F_ERROR==next_object(&sce_iter, 0, 0, 0))
+ if(F_ERROR==next_object(&sce_iter, 0, NULL, NULL))
return;
while(next_object(&sce_iter, 1, &base, &ob)) {
if (ob->type==OB_MBALL) {
if(ob!=active_object){
- splitIDname(ob->id.name+2, obname, &obnr);
+ BLI_split_name_num(obname, &obnr, ob->id.name+2, '.');
/* Object ob has to be in same "group" ... it means, that it has to have
* same base of its name */
@@ -385,6 +402,8 @@ void copy_mball_properties(Scene *scene, Object *active_object)
* its name. All MetaBalls with same base of name can be
* blended. MetaBalls with different basic name can't be
* blended.
+ *
+ * warning!, is_basis_mball() can fail on returned object, see long note above.
*/
Object *find_basis_mball(Scene *scene, Object *basis)
{
@@ -394,12 +413,12 @@ Object *find_basis_mball(Scene *scene, Object *basis)
MetaElem *ml=NULL;
int basisnr, obnr;
char basisname[32], obname[32];
-
- splitIDname(basis->id.name+2, basisname, &basisnr);
+
+ BLI_split_name_num(basisname, &basisnr, basis->id.name+2, '.');
totelem= 0;
/* XXX recursion check, see scene.c, just too simple code this next_object() */
- if(F_ERROR==next_object(&sce_iter, 0, 0, 0))
+ if(F_ERROR==next_object(&sce_iter, 0, NULL, NULL))
return NULL;
while(next_object(&sce_iter, 1, &base, &ob)) {
@@ -415,7 +434,7 @@ Object *find_basis_mball(Scene *scene, Object *basis)
else ml= mb->elems.first;
}
else{
- splitIDname(ob->id.name+2, obname, &obnr);
+ BLI_split_name_num(obname, &obnr, ob->id.name+2, '.');
/* object ob has to be in same "group" ... it means, that it has to have
* same base of its name */
@@ -679,8 +698,8 @@ float metaball(float x, float y, float z)
/* ******************************************** */
-int *indices=NULL;
-int totindex, curindex;
+static int *indices=NULL;
+static int totindex, curindex;
void accum_mballfaces(int i1, int i2, int i3, int i4)
@@ -719,12 +738,12 @@ void accum_mballfaces(int i1, int i2, int i3, int i4)
void *new_pgn_element(int size)
{
/* during polygonize 1000s of elements are allocated
- * and never freed inbetween. Freeing only done at the end.
+ * and never freed in between. Freeing only done at the end.
*/
int blocksize= 16384;
static int offs= 0; /* the current free address */
- static struct pgn_elements *cur= 0;
- static ListBase lb= {0, 0};
+ static struct pgn_elements *cur= NULL;
+ static ListBase lb= {NULL, NULL};
void *adr;
if(size>10000 || size==0) {
@@ -906,14 +925,14 @@ void testface(int i, int j, int k, CUBE* old, int bit, int c1, int c2, int c3, i
newc.corners[FLIP(c3, bit)] = corn3;
newc.corners[FLIP(c4, bit)] = corn4;
- if(newc.corners[0]==0) newc.corners[0] = setcorner(p, i, j, k);
- if(newc.corners[1]==0) newc.corners[1] = setcorner(p, i, j, k+1);
- if(newc.corners[2]==0) newc.corners[2] = setcorner(p, i, j+1, k);
- if(newc.corners[3]==0) newc.corners[3] = setcorner(p, i, j+1, k+1);
- if(newc.corners[4]==0) newc.corners[4] = setcorner(p, i+1, j, k);
- if(newc.corners[5]==0) newc.corners[5] = setcorner(p, i+1, j, k+1);
- if(newc.corners[6]==0) newc.corners[6] = setcorner(p, i+1, j+1, k);
- if(newc.corners[7]==0) newc.corners[7] = setcorner(p, i+1, j+1, k+1);
+ if(newc.corners[0]==NULL) newc.corners[0] = setcorner(p, i, j, k);
+ if(newc.corners[1]==NULL) newc.corners[1] = setcorner(p, i, j, k+1);
+ if(newc.corners[2]==NULL) newc.corners[2] = setcorner(p, i, j+1, k);
+ if(newc.corners[3]==NULL) newc.corners[3] = setcorner(p, i, j+1, k+1);
+ if(newc.corners[4]==NULL) newc.corners[4] = setcorner(p, i+1, j, k);
+ if(newc.corners[5]==NULL) newc.corners[5] = setcorner(p, i+1, j, k+1);
+ if(newc.corners[6]==NULL) newc.corners[6] = setcorner(p, i+1, j+1, k);
+ if(newc.corners[7]==NULL) newc.corners[7] = setcorner(p, i+1, j+1, k+1);
p->cubes->cube= newc;
}
@@ -1012,7 +1031,7 @@ void makecubetable (void)
for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c);
for (e = 0; e < 12; e++)
if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
- INTLIST *ints = 0;
+ INTLIST *ints = NULL;
INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist");
int start = e, edge = e;
@@ -1061,7 +1080,7 @@ void BKE_freecubetable(void)
MEM_freeN(lists);
lists= nlists;
}
- cubetable[i]= 0;
+ cubetable[i]= NULL;
}
}
@@ -1403,7 +1422,7 @@ void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
int i, j, k, c_i, c_j, c_k;
int index[3]={1,0,-1};
float f =0.0f;
- float in_v, out_v;
+ float in_v /*, out_v*/;
MB_POINT workp;
float tmp_v, workp_v, max_len, len, dx, dy, dz, nx, ny, nz, MAXN;
@@ -1464,7 +1483,7 @@ void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
calc_mballco(ml, (float *)&out);
- out_v = mbproc->function(out.x, out.y, out.z);
+ /*out_v = mbproc->function(out.x, out.y, out.z);*/ /*UNUSED*/
/* find "first points" on Implicit Surface of MetaElemnt ml */
workp.x = in.x;
@@ -1563,8 +1582,8 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */
Object *bob;
MetaBall *mb;
MetaElem *ml;
- float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], obmat[4][4], vec[3];
- float temp1[4][4], temp2[4][4], temp3[4][4]; //max=0.0;
+ float size, totsize, obinv[4][4], obmat[4][4], vec[3];
+ //float max=0.0;
int a, obnr, zero_size=0;
char obname[32];
@@ -1572,10 +1591,10 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */
invert_m4_m4(obinv, ob->obmat);
a= 0;
- splitIDname(ob->id.name+2, obname, &obnr);
+ BLI_split_name_num(obname, &obnr, ob->id.name+2, '.');
/* make main array */
- next_object(&sce_iter, 0, 0, 0);
+ next_object(&sce_iter, 0, NULL, NULL);
while(next_object(&sce_iter, 1, &base, &bob)) {
if(bob->type==OB_MBALL) {
@@ -1583,7 +1602,6 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */
ml= NULL;
if(bob==ob && (base->flag & OB_FROMDUPLI)==0) {
- mat= imat= 0;
mb= ob->data;
if(mb->editelems) ml= mb->editelems->first;
@@ -1593,7 +1611,7 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */
char name[32];
int nr;
- splitIDname(bob->id.name+2, name, &nr);
+ BLI_split_name_num(name, &nr, bob->id.name+2, '.');
if( strcmp(obname, name)==0 ) {
mb= bob->data;
@@ -1630,6 +1648,8 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */
while(ml) {
if(!(ml->flag & MB_HIDE)) {
int i;
+ float temp1[4][4], temp2[4][4], temp3[4][4];
+ float (*mat)[4] = NULL, (*imat)[4] = NULL;
float max_x, max_y, max_z, min_x, min_y, min_z;
max_x = max_y = max_z = -3.4e38;
@@ -2154,7 +2174,7 @@ void metaball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
if(G.moving && mb->flag==MB_UPDATE_FAST) return;
curindex= totindex= 0;
- indices= 0;
+ indices= NULL;
thresh= mb->thresh;
/* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */
@@ -2209,7 +2229,7 @@ void metaball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
mbproc.function = metaball;
mbproc.size = width;
mbproc.bounds = nr_cubes;
- mbproc.cubes= 0;
+ mbproc.cubes= NULL;
mbproc.delta = width/(float)(RES*RES);
polygonize(&mbproc, mb);
@@ -2231,7 +2251,7 @@ void metaball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
dl->parts= curindex;
dl->index= indices;
- indices= 0;
+ indices= NULL;
a= mbproc.vertices.count;
dl->verts= ve= MEM_mallocN(sizeof(float)*3*a, "mballverts");
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index f205d8f9e9a..f6679315606 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -44,6 +44,13 @@
#include "DNA_ipo_types.h"
#include "DNA_customdata_types.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_math.h"
+#include "BLI_edgehash.h"
+#include "BLI_utildefines.h"
+#include "BLI_scanfill.h"
+
#include "BKE_animsys.h"
#include "BKE_main.h"
#include "BKE_customdata.h"
@@ -53,12 +60,13 @@
#include "BKE_displist.h"
#include "BKE_library.h"
#include "BKE_material.h"
+#include "BKE_modifier.h"
+#include "BKE_multires.h"
#include "BKE_key.h"
/* these 2 are only used by conversion functions */
#include "BKE_curve.h"
/* -- */
#include "BKE_object.h"
-#include "BKE_utildefines.h"
#include "BKE_tessmesh.h"
#include "BLI_edgehash.h"
@@ -396,11 +404,11 @@ void unlink_mesh(Mesh *me)
{
int a;
- if(me==0) return;
+ if(me==NULL) return;
for(a=0; a<me->totcol; a++) {
if(me->mat[a]) me->mat[a]->id.us--;
- me->mat[a]= 0;
+ me->mat[a]= NULL;
}
if(me->key) {
@@ -408,9 +416,9 @@ void unlink_mesh(Mesh *me)
if (me->key->id.us == 0 && me->key->ipo )
me->key->ipo->id.us--;
}
- me->key= 0;
+ me->key= NULL;
- if(me->texcomesh) me->texcomesh= 0;
+ if(me->texcomesh) me->texcomesh= NULL;
}
@@ -485,7 +493,7 @@ void free_dverts(MDeformVert *dvert, int totvert)
MEM_freeN (dvert);
}
-Mesh *add_mesh(char *name)
+Mesh *add_mesh(const char *name)
{
Mesh *me;
@@ -600,9 +608,9 @@ void make_local_tface(Mesh *me)
if(tface->tpage) {
ima= tface->tpage;
if(ima->id.lib) {
- ima->id.lib= 0;
+ ima->id.lib= NULL;
ima->id.flag= LIB_LOCAL;
- new_id(0, (ID *)ima, 0);
+ new_id(NULL, (ID *)ima, NULL);
}
}
}
@@ -623,11 +631,11 @@ void make_local_mesh(Mesh *me)
* - mixed: make copy
*/
- if(me->id.lib==0) return;
+ if(me->id.lib==NULL) return;
if(me->id.us==1) {
- me->id.lib= 0;
+ me->id.lib= NULL;
me->id.flag= LIB_LOCAL;
- new_id(0, (ID *)me, 0);
+ new_id(NULL, (ID *)me, NULL);
if(me->mtface) make_local_tface(me);
@@ -644,9 +652,9 @@ void make_local_mesh(Mesh *me)
}
if(local && lib==0) {
- me->id.lib= 0;
+ me->id.lib= NULL;
me->id.flag= LIB_LOCAL;
- new_id(0, (ID *)me, 0);
+ new_id(NULL, (ID *)me, NULL);
if(me->mtface) make_local_tface(me);
@@ -658,7 +666,7 @@ void make_local_mesh(Mesh *me)
ob= bmain->object.first;
while(ob) {
if( me==get_mesh(ob) ) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
set_mesh(ob, men);
}
}
@@ -673,7 +681,7 @@ void boundbox_mesh(Mesh *me, float *loc, float *size)
float min[3], max[3];
float mloc[3], msize[3];
- if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ if(me->bb==NULL) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
bb= me->bb;
if (!loc) loc= mloc;
@@ -786,11 +794,11 @@ void transform_mesh_orco_verts(Mesh *me, float (*orco)[3], int totvert, int inve
int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr)
{
/* first test if the face is legal */
- if(mface->v3 && mface->v3==mface->v4) {
+ if((mface->v3 || nr==4) && mface->v3==mface->v4) {
mface->v4= 0;
nr--;
}
- if(mface->v2 && mface->v2==mface->v3) {
+ if((mface->v2 || mface->v4) && mface->v2==mface->v3) {
mface->v3= mface->v4;
mface->v4= 0;
nr--;
@@ -802,6 +810,32 @@ int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr)
nr--;
}
+ /* check corrupt cases, bowtie geometry, cant handle these because edge data wont exist so just return 0 */
+ if(nr==3) {
+ if(
+ /* real edges */
+ mface->v1==mface->v2 ||
+ mface->v2==mface->v3 ||
+ mface->v3==mface->v1
+ ) {
+ return 0;
+ }
+ }
+ else if(nr==4) {
+ if(
+ /* real edges */
+ mface->v1==mface->v2 ||
+ mface->v2==mface->v3 ||
+ mface->v3==mface->v4 ||
+ mface->v4==mface->v1 ||
+ /* across the face */
+ mface->v1==mface->v3 ||
+ mface->v2==mface->v4
+ ) {
+ return 0;
+ }
+ }
+
/* prevent a zero at wrong index location */
if(nr==3) {
if(mface->v3==0) {
@@ -832,16 +866,18 @@ int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr)
Mesh *get_mesh(Object *ob)
{
- if(ob==0) return 0;
+ if(ob==NULL) return NULL;
if(ob->type==OB_MESH) return ob->data;
- else return 0;
+ else return NULL;
}
void set_mesh(Object *ob, Mesh *me)
{
- Mesh *old=0;
+ Mesh *old=NULL;
+
+ multires_force_update(ob);
- if(ob==0) return;
+ if(ob==NULL) return;
if(ob->type==OB_MESH) {
old= ob->data;
@@ -852,6 +888,8 @@ void set_mesh(Object *ob, Mesh *me)
}
test_object_materials((ID *)me);
+
+ test_object_modifiers(ob);
}
/* ************** make edges in a Mesh, for outside of editmode */
@@ -903,7 +941,7 @@ static void mfaces_strip_loose(MFace *mface, int *totface)
}
/* Create edges based on known verts and faces */
-static void make_edges_mdata(MVert *allvert, MFace *allface, int totvert, int totface,
+static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED(totvert), int totface,
int old, MEdge **alledge, int *_totedge)
{
MFace *mface;
@@ -1020,6 +1058,23 @@ void mesh_strip_loose_faces(Mesh *me)
me->totface = b;
}
+void mesh_strip_loose_edges(Mesh *me)
+{
+ int a,b;
+
+ for (a=b=0; a<me->totedge; a++) {
+ if (me->medge[a].v1!=me->medge[a].v2) {
+ if (a!=b) {
+ memcpy(&me->medge[b],&me->medge[a],sizeof(me->medge[b]));
+ CustomData_copy_data(&me->edata, &me->edata, a, b, 1);
+ CustomData_free_elem(&me->edata, a, 1);
+ }
+ b++;
+ }
+ }
+ me->totedge = b;
+}
+
void mball_to_mesh(ListBase *lb, Mesh *me)
{
DispList *dl;
@@ -1029,7 +1084,7 @@ void mball_to_mesh(ListBase *lb, Mesh *me)
int a, *index;
dl= lb->first;
- if(dl==0) return;
+ if(dl==NULL) return;
if(dl->type==DL_INDEX4) {
me->totvert= dl->nr;
@@ -1077,7 +1132,7 @@ void mball_to_mesh(ListBase *lb, Mesh *me)
int nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
MEdge **alledge, int *totedge, MFace **allface, int *totface)
{
- return nurbs_to_mdata_customdb(ob, &((Curve *)ob->data)->disp,
+ return nurbs_to_mdata_customdb(ob, &ob->disp,
allvert, totvert, alledge, totedge, allface, totface);
}
@@ -1093,9 +1148,13 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
float *data;
int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0;
int p1, p2, p3, p4, *index;
+ int conv_polys= 0;
cu= ob->data;
+ conv_polys|= cu->flag & CU_3D; /* 2d polys are filled with DL_INDEX3 displists */
+ conv_polys|= ob->type == OB_SURF; /* surf polys are never filled */
+
/* count */
dl= dispbase->first;
while(dl) {
@@ -1104,8 +1163,10 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
totvlak+= dl->parts*(dl->nr-1);
}
else if(dl->type==DL_POLY) {
- totvert+= dl->parts*dl->nr;
- totvlak+= dl->parts*dl->nr;
+ if(conv_polys) {
+ totvert+= dl->parts*dl->nr;
+ totvlak+= dl->parts*dl->nr;
+ }
}
else if(dl->type==DL_SURF) {
totvert+= dl->parts*dl->nr;
@@ -1125,7 +1186,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
}
*allvert= mvert= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mvert");
- *allface= mface= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mface");
+ *allface= mface= MEM_callocN(sizeof (MVert) * totvlak, "nurbs_init mface");
/* verts and faces */
vertcount= 0;
@@ -1157,24 +1218,26 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
}
else if(dl->type==DL_POLY) {
- startvert= vertcount;
- a= dl->parts*dl->nr;
- data= dl->verts;
- while(a--) {
- VECCOPY(mvert->co, data);
- data+=3;
- vertcount++;
- mvert++;
- }
+ if(conv_polys) {
+ startvert= vertcount;
+ a= dl->parts*dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
- for(a=0; a<dl->parts; a++) {
- ofs= a*dl->nr;
- for(b=0; b<dl->nr; b++) {
- mface->v1= startvert+ofs+b;
- if(b==dl->nr-1) mface->v2= startvert+ofs;
- else mface->v2= startvert+ofs+b+1;
- if(smooth) mface->flag |= ME_SMOOTH;
- mface++;
+ for(a=0; a<dl->parts; a++) {
+ ofs= a*dl->nr;
+ for(b=0; b<dl->nr; b++) {
+ mface->v1= startvert+ofs+b;
+ if(b==dl->nr-1) mface->v2= startvert+ofs;
+ else mface->v2= startvert+ofs+b+1;
+ if(smooth) mface->flag |= ME_SMOOTH;
+ mface++;
+ }
}
}
}
@@ -1196,6 +1259,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
mface->v2= startvert+index[2];
mface->v3= startvert+index[1];
mface->v4= 0;
+ mface->mat_nr= (unsigned char)dl->col;
test_index_face(mface, NULL, 0, 3);
if(smooth) mface->flag |= ME_SMOOTH;
@@ -1313,7 +1377,7 @@ void nurbs_to_mesh(Object *ob)
tex_space_mesh(me);
- cu->mat= 0;
+ cu->mat= NULL;
cu->totcol= 0;
if(ob->data) {
@@ -1555,14 +1619,12 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth)
mf->flag &= ~ME_SMOOTH;
}
}
-
-// XXX do this in caller DAG_id_flush_update(&me->id, OB_RECALC_DATA);
}
void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float **faceNors_r)
{
float (*tnorms)[3]= MEM_callocN(numVerts*sizeof(*tnorms), "tnorms");
- float *fnors= MEM_mallocN(sizeof(*fnors)*3*numFaces, "meshnormals");
+ float *fnors= MEM_callocN(sizeof(*fnors)*3*numFaces, "meshnormals");
int i;
for (i=0; i<numFaces; i++) {
@@ -1782,7 +1844,7 @@ void mesh_pmv_free(PartialVisibility *pv)
MEM_freeN(pv);
}
-void mesh_pmv_revert(Object *ob, Mesh *me)
+void mesh_pmv_revert(Mesh *me)
{
if(me->pv) {
unsigned i;
@@ -1816,15 +1878,13 @@ void mesh_pmv_revert(Object *ob, Mesh *me)
me->pv->edge_map= NULL;
MEM_freeN(me->pv->vert_map);
me->pv->vert_map= NULL;
-
-// XXX do this in caller DAG_id_flush_update(&me->id, OB_RECALC_DATA);
}
}
-void mesh_pmv_off(Object *ob, Mesh *me)
+void mesh_pmv_off(Mesh *me)
{
- if(ob && me->pv) {
- mesh_pmv_revert(ob, me);
+ if(me->pv) {
+ mesh_pmv_revert(me);
MEM_freeN(me->pv);
me->pv= NULL;
}
@@ -1946,7 +2006,7 @@ int mesh_recalcTesselation(CustomData *fdata,
}
BLI_addfilledge(lastv, firstv);
- BLI_edgefill(0, 0);
+ BLI_edgefill(0);
for (f=fillfacebase.first; f; f=f->next) {
BLI_array_growone(mf);
BLI_array_growone(origIndex);
@@ -2129,7 +2189,10 @@ int mesh_center_median(Mesh *me, float cent[3])
for(mvert= me->mvert; i--; mvert++) {
add_v3_v3(cent, mvert->co);
}
- mul_v3_fl(cent, 1.0f/(float)me->totvert);
+ /* otherwise we get NAN for 0 verts */
+ if(me->totvert) {
+ mul_v3_fl(cent, 1.0f/(float)me->totvert);
+ }
return (me->totvert != 0);
}
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
new file mode 100644
index 00000000000..0821b4188fe
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -0,0 +1,379 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLO_sys_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_edgehash.h"
+
+#include "BKE_DerivedMesh.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_mesh.h"
+
+#define SELECT 1
+
+typedef union {
+ uint32_t verts[2];
+ int64_t edval;
+} EdgeUUID;
+
+typedef struct SortFace {
+// unsigned int v[4];
+ EdgeUUID es[4];
+ unsigned int index;
+} SortFace;
+
+static void edge_store_assign(uint32_t verts[2], const uint32_t v1, const uint32_t v2)
+{
+ if(v1 < v2) {
+ verts[0]= v1;
+ verts[1]= v2;
+ }
+ else {
+ verts[0]= v2;
+ verts[1]= v1;
+ }
+}
+
+static void edge_store_from_mface_quad(EdgeUUID es[4], MFace *mf)
+{
+ edge_store_assign(es[0].verts, mf->v1, mf->v2);
+ edge_store_assign(es[1].verts, mf->v2, mf->v3);
+ edge_store_assign(es[2].verts, mf->v3, mf->v4);
+ edge_store_assign(es[3].verts, mf->v4, mf->v1);
+}
+
+static void edge_store_from_mface_tri(EdgeUUID es[3], MFace *mf)
+{
+ edge_store_assign(es[0].verts, mf->v1, mf->v2);
+ edge_store_assign(es[1].verts, mf->v2, mf->v3);
+ edge_store_assign(es[2].verts, mf->v3, mf->v1);
+ es[3].verts[0] = es[3].verts[1] = UINT_MAX;
+}
+
+static int int64_cmp(const void *v1, const void *v2)
+{
+ const int64_t x1= *(const int64_t *)v1;
+ const int64_t x2= *(const int64_t *)v2;
+
+ if( x1 > x2 ) return 1;
+ else if( x1 < x2 ) return -1;
+ return 0;
+}
+
+static int search_face_cmp(const void *v1, const void *v2)
+{
+ const SortFace *sfa= v1, *sfb= v2;
+
+ if (sfa->es[0].edval > sfb->es[0].edval) return 1;
+ else if (sfa->es[0].edval < sfb->es[0].edval) return -1;
+
+ else if (sfa->es[1].edval > sfb->es[1].edval) return 1;
+ else if (sfa->es[1].edval < sfb->es[1].edval) return -1;
+
+ else if (sfa->es[2].edval > sfb->es[2].edval) return 1;
+ else if (sfa->es[2].edval < sfb->es[2].edval) return -1;
+
+ else if (sfa->es[3].edval > sfb->es[3].edval) return 1;
+ else if (sfa->es[3].edval < sfb->es[3].edval) return -1;
+ else return 0;
+
+}
+
+int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge *medges, int totedge, MFace *mfaces, int totface, const short do_verbose, const short do_fixes)
+{
+# define PRINT if(do_verbose) printf
+# define REMOVE_EDGE_TAG(_med) { _med->v2= _med->v1; do_edge_free= 1; }
+# define REMOVE_FACE_TAG(_mf) { _mf->v3=0; do_face_free= 1; }
+
+// MVert *mv;
+ MEdge *med;
+ MFace *mf;
+ MFace *mf_prev;
+ int i;
+
+ int do_face_free= FALSE;
+ int do_edge_free= FALSE;
+
+ int do_edge_recalc= FALSE;
+
+ EdgeHash *edge_hash = BLI_edgehash_new();
+
+ SortFace *sort_faces= MEM_callocN(sizeof(SortFace) * totface, "search faces");
+ SortFace *sf;
+ SortFace *sf_prev;
+ int totsortface= 0;
+
+ BLI_assert(!(do_fixes && me == NULL));
+
+ PRINT("ED_mesh_validate: verts(%d), edges(%d), faces(%d)\n", totvert, totedge, totface);
+
+ if(totedge == 0 && totface != 0) {
+ PRINT(" locical error, %d faces and 0 edges\n", totface);
+ do_edge_recalc= TRUE;
+ }
+
+ for(i=0, med= medges; i<totedge; i++, med++) {
+ int remove= FALSE;
+ if(med->v1 == med->v2) {
+ PRINT(" edge %d: has matching verts, both %d\n", i, med->v1);
+ remove= do_fixes;
+ }
+ if(med->v1 >= totvert) {
+ PRINT(" edge %d: v1 index out of range, %d\n", i, med->v1);
+ remove= do_fixes;
+ }
+ if(med->v2 >= totvert) {
+ PRINT(" edge %d: v2 index out of range, %d\n", i, med->v2);
+ remove= do_fixes;
+ }
+
+ if(BLI_edgehash_haskey(edge_hash, med->v1, med->v2)) {
+ PRINT(" edge %d: is a duplicate of, %d\n", i, GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, med->v1, med->v2)));
+ remove= do_fixes;
+ }
+
+ if(remove == FALSE){
+ BLI_edgehash_insert(edge_hash, med->v1, med->v2, SET_INT_IN_POINTER(i));
+ }
+ else {
+ REMOVE_EDGE_TAG(med);
+ }
+ }
+
+ for(i=0, mf=mfaces, sf=sort_faces; i<totface; i++, mf++) {
+ int remove= FALSE;
+ int fidx;
+ unsigned int fv[4];
+
+ fidx = mf->v4 ? 3:2;
+ do {
+ fv[fidx]= *(&(mf->v1) + fidx);
+ if(fv[fidx] >= totvert) {
+ PRINT(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, fv[fidx]);
+ remove= do_fixes;
+ }
+ } while (fidx--);
+
+ if(remove == FALSE) {
+ if(mf->v4) {
+ if(mf->v1 == mf->v2) { PRINT(" face %d: verts invalid, v1/v2 both %d\n", i, mf->v1); remove= do_fixes; }
+ if(mf->v1 == mf->v3) { PRINT(" face %d: verts invalid, v1/v3 both %d\n", i, mf->v1); remove= do_fixes; }
+ if(mf->v1 == mf->v4) { PRINT(" face %d: verts invalid, v1/v4 both %d\n", i, mf->v1); remove= do_fixes; }
+
+ if(mf->v2 == mf->v3) { PRINT(" face %d: verts invalid, v2/v3 both %d\n", i, mf->v2); remove= do_fixes; }
+ if(mf->v2 == mf->v4) { PRINT(" face %d: verts invalid, v2/v4 both %d\n", i, mf->v2); remove= do_fixes; }
+
+ if(mf->v3 == mf->v4) { PRINT(" face %d: verts invalid, v3/v4 both %d\n", i, mf->v3); remove= do_fixes; }
+ }
+ else {
+ if(mf->v1 == mf->v2) { PRINT(" faceT %d: verts invalid, v1/v2 both %d\n", i, mf->v1); remove= do_fixes; }
+ if(mf->v1 == mf->v3) { PRINT(" faceT %d: verts invalid, v1/v3 both %d\n", i, mf->v1); remove= do_fixes; }
+
+ if(mf->v2 == mf->v3) { PRINT(" faceT %d: verts invalid, v2/v3 both %d\n", i, mf->v2); remove= do_fixes; }
+ }
+
+ if(remove == FALSE) {
+ if(totedge) {
+ if(mf->v4) {
+ if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) { PRINT(" face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); do_edge_recalc= TRUE; }
+ if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) { PRINT(" face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); do_edge_recalc= TRUE; }
+ if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v4)) { PRINT(" face %d: edge v3/v4 (%d,%d) is missing egde data\n", i, mf->v3, mf->v4); do_edge_recalc= TRUE; }
+ if(!BLI_edgehash_haskey(edge_hash, mf->v4, mf->v1)) { PRINT(" face %d: edge v4/v1 (%d,%d) is missing egde data\n", i, mf->v4, mf->v1); do_edge_recalc= TRUE; }
+ }
+ else {
+ if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) { PRINT(" face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); do_edge_recalc= TRUE; }
+ if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) { PRINT(" face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); do_edge_recalc= TRUE; }
+ if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v1)) { PRINT(" face %d: edge v3/v1 (%d,%d) is missing egde data\n", i, mf->v3, mf->v1); do_edge_recalc= TRUE; }
+ }
+ }
+
+ sf->index = i;
+
+ if(mf->v4) {
+ edge_store_from_mface_quad(sf->es, mf);
+
+ qsort(sf->es, 4, sizeof(int64_t), int64_cmp);
+ }
+ else {
+ edge_store_from_mface_tri(sf->es, mf);
+ qsort(sf->es, 3, sizeof(int64_t), int64_cmp);
+ }
+
+ totsortface++;
+ sf++;
+ }
+ }
+ if(remove) {
+ REMOVE_FACE_TAG(mf);
+ }
+ }
+
+ qsort(sort_faces, totsortface, sizeof(SortFace), search_face_cmp);
+
+ sf= sort_faces;
+ sf_prev= sf;
+ sf++;
+
+ for(i=1; i<totsortface; i++, sf++) {
+ int remove= FALSE;
+ /* on a valid mesh, code below will never run */
+ if(memcmp(sf->es, sf_prev->es, sizeof(sf_prev->es)) == 0) {
+ mf= mfaces + sf->index;
+
+ if(do_verbose) {
+ mf_prev= mfaces + sf_prev->index;
+ if(mf->v4) {
+ PRINT(" face %d & %d: are duplicates (%d,%d,%d,%d) (%d,%d,%d,%d)\n", sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4, mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4);
+ }
+ else {
+ PRINT(" face %d & %d: are duplicates (%d,%d,%d) (%d,%d,%d)\n", sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf_prev->v1, mf_prev->v2, mf_prev->v3);
+ }
+ }
+
+ remove= do_fixes;
+ }
+ else {
+ sf_prev= sf;
+ }
+
+ if(remove) {
+ REMOVE_FACE_TAG(mf);
+ }
+ }
+
+ BLI_edgehash_free(edge_hash, NULL);
+ MEM_freeN(sort_faces);
+
+ PRINT("BKE_mesh_validate: finished\n\n");
+
+# undef PRINT
+# undef REMOVE_EDGE_TAG
+# undef REMOVE_FACE_TAG
+
+ if(me) {
+ if(do_face_free) {
+ mesh_strip_loose_faces(me);
+ }
+
+ if (do_edge_free) {
+ mesh_strip_loose_edges(me);
+ }
+
+ if(do_fixes && do_edge_recalc) {
+ BKE_mesh_calc_edges(me, TRUE);
+ }
+ }
+
+ return (do_face_free || do_edge_free || do_edge_recalc);
+}
+
+int BKE_mesh_validate(Mesh *me, int do_verbose)
+{
+ printf("MESH: %s\n", me->id.name+2);
+ return BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, do_verbose, TRUE);
+}
+
+int BKE_mesh_validate_dm(DerivedMesh *dm)
+{
+ return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), TRUE, FALSE);
+}
+
+void BKE_mesh_calc_edges(Mesh *mesh, int update)
+{
+ CustomData edata;
+ EdgeHashIterator *ehi;
+ MFace *mf = mesh->mface;
+ MEdge *med, *med_orig;
+ EdgeHash *eh = BLI_edgehash_new();
+ int i, totedge, totface = mesh->totface;
+
+ if(mesh->totedge==0)
+ update= 0;
+
+ if(update) {
+ /* assume existing edges are valid
+ * useful when adding more faces and generating edges from them */
+ med= mesh->medge;
+ for(i= 0; i<mesh->totedge; i++, med++)
+ BLI_edgehash_insert(eh, med->v1, med->v2, med);
+ }
+
+ for (i = 0; i < totface; i++, mf++) {
+ if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
+ BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
+ if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
+ BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
+
+ if (mf->v4) {
+ if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
+ BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
+ if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
+ BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
+ } else {
+ if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
+ BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
+ }
+ }
+
+ totedge = BLI_edgehash_size(eh);
+
+ /* write new edges into a temporary CustomData */
+ memset(&edata, 0, sizeof(edata));
+ CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+
+ ehi = BLI_edgehashIterator_new(eh);
+ med = CustomData_get_layer(&edata, CD_MEDGE);
+ for(i = 0; !BLI_edgehashIterator_isDone(ehi);
+ BLI_edgehashIterator_step(ehi), ++i, ++med) {
+
+ if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) {
+ *med= *med_orig; /* copy from the original */
+ } else {
+ BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
+ med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */
+ }
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /* free old CustomData and assign new one */
+ CustomData_free(&mesh->edata, mesh->totedge);
+ mesh->edata = edata;
+ mesh->totedge = totedge;
+
+ mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);
+
+ BLI_edgehash_free(eh, NULL);
+}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 63f0f1fa091..7439a47a746 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -40,30 +40,33 @@
#include <math.h>
#include <float.h>
+#include "MEM_guardedalloc.h"
+
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
-#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BKE_bmesh.h"
#include "BKE_cloth.h"
#include "BKE_key.h"
+#include "BKE_multires.h"
#include "MOD_modifiertypes.h"
ModifierTypeInfo *modifierType_getInfo(ModifierType type)
{
- static ModifierTypeInfo *types[NUM_MODIFIER_TYPES];
+ static ModifierTypeInfo *types[NUM_MODIFIER_TYPES]= {NULL};
static int types_init = 1;
if (types_init) {
- modifier_type_init(types, type); /* MOD_utils.c */
+ modifier_type_init(types); /* MOD_utils.c */
types_init= 0;
}
- if(type >= 0 && type < NUM_MODIFIER_TYPES &&
- types[type]->name[0] != '\0') {
+ /* type unsigned, no need to chech < 0 */
+ if(type < NUM_MODIFIER_TYPES && types[type]->name[0] != '\0') {
return types[type];
}
else {
@@ -146,14 +149,14 @@ ModifierData *modifiers_findByName(Object *ob, const char *name)
void modifiers_clearErrors(Object *ob)
{
ModifierData *md = ob->modifiers.first;
- int qRedraw = 0;
+ /* int qRedraw = 0; */
for (; md; md=md->next) {
if (md->error) {
MEM_freeN(md->error);
md->error = NULL;
- qRedraw = 1;
+ /* qRedraw = 1; */
}
}
}
@@ -215,14 +218,15 @@ int modifier_sameTopology(ModifierData *md)
return ( mti->type == eModifierTypeType_OnlyDeform || mti->type == eModifierTypeType_Nonconstructive);
}
-void modifier_setError(ModifierData *md, char *format, ...)
+void modifier_setError(ModifierData *md, const char *format, ...)
{
- char buffer[2048];
+ char buffer[512];
va_list ap;
va_start(ap, format);
- vsprintf(buffer, format, ap);
+ vsnprintf(buffer, sizeof(buffer), format, ap);
va_end(ap);
+ buffer[sizeof(buffer) - 1]= '\0';
if (md->error)
MEM_freeN(md->error);
@@ -235,13 +239,19 @@ void modifier_setError(ModifierData *md, char *format, ...)
* there
*
* also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
- * then is NULL)
+ * then is NULL)
+ * also used for some mesh tools to give warnings
*/
int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *lastPossibleCageIndex_r, int virtual_)
{
ModifierData *md = (virtual_)? modifiers_getVirtualModifierList(ob): ob->modifiers.first;
int i, cageIndex = -1;
+ if(lastPossibleCageIndex_r) {
+ /* ensure the value is initialized */
+ *lastPossibleCageIndex_r= -1;
+ }
+
/* Find the last modifier acting on the cage. */
for (i=0; md; i++,md=md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -491,7 +501,7 @@ int modifier_isCorrectableDeformed(ModifierData *md)
return 0;
}
-int modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob)
+int modifiers_isCorrectableDeformed(Object *ob)
{
ModifierData *md = modifiers_getVirtualModifierList(ob);
@@ -526,5 +536,21 @@ void modifier_freeTemporaryData(ModifierData *md)
}
}
+/* ensure modifier correctness when changing ob->data */
+void test_object_modifiers(Object *ob)
+{
+ ModifierData *md;
+
+ /* just multires checked for now, since only multires
+ modifies mesh data */
+
+ if(ob->type != OB_MESH) return;
+ for(md = ob->modifiers.first; md; md = md->next) {
+ if(md->type == eModifierType_Multires) {
+ MultiresModifierData *mmd = (MultiresModifierData*)md;
+ multiresModifier_set_levels_from_disps(mmd, ob);
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 4b54114505e..f2c5a9cbf37 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -37,6 +37,8 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_pbvh.h"
+#include "BLI_editVert.h"
+#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
@@ -45,7 +47,9 @@
#include "BKE_paint.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
-#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
+
+#include "BKE_object.h"
#include "CCGSubSurf.h"
@@ -89,6 +93,36 @@ MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData *
return NULL;
}
+/* used for applying scale on mdisps layer and syncing subdivide levels when joining objects
+ use_first - return first multires modifier if all multires'es are disabled
+*/
+MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, int use_first)
+{
+ ModifierData *md;
+ MultiresModifierData *mmd= NULL, *firstmmd= NULL;
+
+ /* find first active multires modifier */
+ for(md = ob->modifiers.first; md; md = md->next) {
+ if(md->type == eModifierType_Multires) {
+ if(!firstmmd)
+ firstmmd= (MultiresModifierData*)md;
+
+ if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
+ mmd= (MultiresModifierData*)md;
+ break;
+ }
+ }
+ }
+
+ if(!mmd && use_first) {
+ /* active multires have not been found
+ try to use first one */
+ return firstmmd;
+ }
+
+ return mmd;
+}
+
static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render)
{
if(render)
@@ -151,68 +185,6 @@ void multires_force_render_update(Object *ob)
multires_force_update(ob);
}
-/* XXX */
-#if 0
-void multiresModifier_join(Object *ob)
-{
- Base *base = NULL;
- int highest_lvl = 0;
-
- /* First find the highest level of subdivision */
- base = FIRSTBASE;
- while(base) {
- if(TESTBASELIB_BGMODE(v3d, scene, base) && base->object->type==OB_MESH) {
- ModifierData *md;
- for(md = base->object->modifiers.first; md; md = md->next) {
- if(md->type == eModifierType_Multires) {
- int totlvl = ((MultiresModifierData*)md)->totlvl;
- if(totlvl > highest_lvl)
- highest_lvl = totlvl;
-
- /* Ensure that all updates are processed */
- multires_force_update(base->object);
- }
- }
- }
- base = base->next;
- }
-
- /* No multires meshes selected */
- if(highest_lvl == 0)
- return;
-
- /* Subdivide all the displacements to the highest level */
- base = FIRSTBASE;
- while(base) {
- if(TESTBASELIB_BGMODE(v3d, scene, base) && base->object->type==OB_MESH) {
- ModifierData *md = NULL;
- MultiresModifierData *mmd = NULL;
-
- for(md = base->object->modifiers.first; md; md = md->next) {
- if(md->type == eModifierType_Multires)
- mmd = (MultiresModifierData*)md;
- }
-
- /* If the object didn't have multires enabled, give it a new modifier */
- if(!mmd) {
- md = base->object->modifiers.first;
-
- while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
- md = md->next;
-
- mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires);
- BLI_insertlinkbefore(&base->object->modifiers, md, mmd);
- modifier_unique_name(&base->object->modifiers, mmd);
- }
-
- if(mmd)
- multiresModifier_subdivide(mmd, base->object, highest_lvl - mmd->totlvl, 0, 0);
- }
- base = base->next;
- }
-}
-#endif
-
int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd,
Object *ob, DerivedMesh *srcdm)
{
@@ -229,7 +201,7 @@ int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd,
return 1;
}
- mrdm->release(mrdm);
+ if(mrdm) mrdm->release(mrdm);
return 0;
}
@@ -275,6 +247,60 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm
return result;
}
+/* reset the multires levels to match the number of mdisps */
+static int get_levels_from_disps(Object *ob)
+{
+ Mesh *me = ob->data;
+ MDisps *mdisp, *md;
+ int i, j, totlvl= 0;
+
+ mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS);
+
+ for(i = 0; i < me->totpoly; ++i) {
+ int S = me->mpoly[i].totloop;
+
+ md = mdisp + me->mpoly[i].loopstart;
+ for (j=0; j<me->mpoly[i].totloop; j++, md++) {
+ if(md->totdisp == 0) continue;
+
+ while(1) {
+ int side = (1 << (totlvl-1)) + 1;
+ int lvl_totdisp = side*side*S;
+ if(md->totdisp == lvl_totdisp)
+ break;
+ else if(md->totdisp < lvl_totdisp)
+ --totlvl;
+ else
+ ++totlvl;
+
+ }
+
+ break;
+ }
+ }
+
+ return totlvl;
+}
+
+/* reset the multires levels to match the number of mdisps */
+void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
+{
+ Mesh *me = ob->data;
+ MDisps *mdisp;
+
+ if(me->edit_btmesh)
+ mdisp = CustomData_get_layer(&me->edit_btmesh->bm->ldata, CD_MDISPS);
+ else
+ mdisp = CustomData_get_layer(&me->ldata, CD_MDISPS);
+
+ if(mdisp) {
+ mmd->totlvl = get_levels_from_disps(ob);
+ mmd->lvl = MIN2(mmd->sculptlvl, mmd->totlvl);
+ mmd->sculptlvl = MIN2(mmd->sculptlvl, mmd->totlvl);
+ mmd->renderlvl = MIN2(mmd->renderlvl, mmd->totlvl);
+ }
+}
+
static void multires_set_tot_mdisps(Mesh *me, int lvl)
{
MDisps *mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS);
@@ -351,11 +377,9 @@ static void multires_copy_dm_grid(DMGridData *gridA, DMGridData *gridB, int size
}
}
-/* direction=1 for delete higher, direction=0 for lower (not implemented yet) */
-void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction)
+static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
{
- Mesh *me = get_mesh(ob);
- int lvl = multires_get_level(ob, mmd, 0);
+ Mesh *me = (Mesh*)ob->data;
int levels = mmd->totlvl - lvl;
MDisps *mdisps;
@@ -365,7 +389,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire
multires_force_update(ob);
- if(mdisps && levels > 0 && direction == 1) {
+ if(mdisps && levels > 0) {
if(lvl > 0) {
MLoop *ml = me->mloop;
int nsize = multires_side_tot[lvl];
@@ -403,11 +427,31 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire
multires_set_tot_level(ob, mmd, lvl);
}
+/* direction=1 for delete higher, direction=0 for lower (not implemented yet) */
+void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction)
+{
+ Mesh *me = get_mesh(ob);
+ int lvl = multires_get_level(ob, mmd, 0);
+ int levels = mmd->totlvl - lvl;
+ MDisps *mdisps;
+
+ multires_set_tot_mdisps(me, mmd->totlvl);
+ CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
+ mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
+
+ multires_force_update(ob);
+
+ if(mdisps && levels > 0 && direction == 1) {
+ multires_del_higher(mmd, ob, lvl);
+ }
+
+ multires_set_tot_level(ob, mmd, lvl);
+}
+
static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple)
{
- MultiresModifierData mmd;
+ MultiresModifierData mmd= {{NULL}};
- memset(&mmd, 0, sizeof(MultiresModifierData));
mmd.lvl = lvl;
mmd.sculptlvl = lvl;
mmd.renderlvl = lvl;
@@ -417,11 +461,10 @@ static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lv
return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0);
}
-static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal)
+static DerivedMesh *subsurf_dm_create_local(Object *UNUSED(ob), DerivedMesh *dm, int lvl, int simple, int optimal)
{
- SubsurfModifierData smd;
+ SubsurfModifierData smd= {{NULL}};
- memset(&smd, 0, sizeof(SubsurfModifierData));
smd.levels = smd.renderLevels = lvl;
smd.flags |= eSubsurfModifierFlag_SubsurfUv;
if(simple)
@@ -432,12 +475,133 @@ static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl
return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0);
}
-void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple)
+
+
+/* assumes no is normalized; return value's sign is negative if v is on
+ the other side of the plane */
+static float v3_dist_from_plane(float v[3], float center[3], float no[3])
+{
+ float s[3];
+ sub_v3_v3v3(s, v, center);
+ return dot_v3v3(s, no);
+}
+
+void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob)
+{
+ DerivedMesh *cddm, *dispdm, *origdm;
+ Mesh *me;
+ ListBase *fmap;
+ float (*origco)[3];
+ int i, j, offset, totlvl;
+
+ multires_force_update(ob);
+
+ me = get_mesh(ob);
+ totlvl = mmd->totlvl;
+
+ /* nothing to do */
+ if(!totlvl)
+ return;
+
+ /* XXX - probably not necessary to regenerate the cddm so much? */
+
+ /* generate highest level with displacements */
+ cddm = CDDM_from_mesh(me, NULL);
+ DM_set_only_copy(cddm, CD_MASK_BAREMESH);
+ dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0);
+ cddm->release(cddm);
+
+ /* copy the new locations of the base verts into the mesh */
+ offset = dispdm->getNumVerts(dispdm) - me->totvert;
+ for(i = 0; i < me->totvert; ++i) {
+ dispdm->getVertCo(dispdm, offset + i, me->mvert[i].co);
+ }
+
+ /* heuristic to produce a better-fitting base mesh */
+
+ cddm = CDDM_from_mesh(me, NULL);
+ fmap = cddm->getFaceMap(ob, cddm);
+ origco = MEM_callocN(sizeof(float)*3*me->totvert, "multires apply base origco");
+ for(i = 0; i < me->totvert ;++i)
+ copy_v3_v3(origco[i], me->mvert[i].co);
+
+ for(i = 0; i < me->totvert; ++i) {
+ IndexNode *n;
+ float avg_no[3] = {0,0,0}, center[3] = {0,0,0}, push[3];
+ float dist;
+ int tot;
+
+ /* don't adjust verts not used by at least one face */
+ if(!fmap[i].first)
+ continue;
+
+ /* find center */
+ for(n = fmap[i].first, tot = 0; n; n = n->next) {
+ MFace *f = &me->mface[n->index];
+ int S = f->v4 ? 4 : 3;
+
+ /* this double counts, not sure if that's bad or good */
+ for(j = 0; j < S; ++j) {
+ int vndx = (&f->v1)[j];
+ if(vndx != i) {
+ add_v3_v3(center, origco[vndx]);
+ ++tot;
+ }
+ }
+ }
+ mul_v3_fl(center, 1.0f / tot);
+
+ /* find normal */
+ for(n = fmap[i].first; n; n = n->next) {
+ MFace *f = &me->mface[n->index];
+ int S = f->v4 ? 4 : 3;
+ float v[4][3], no[3];
+
+ for(j = 0; j < S; ++j) {
+ int vndx = (&f->v1)[j];
+ if(vndx == i)
+ copy_v3_v3(v[j], center);
+ else
+ copy_v3_v3(v[j], origco[vndx]);
+ }
+
+ if(S == 4)
+ normal_quad_v3(no, v[0], v[1], v[2], v[3]);
+ else
+ normal_tri_v3(no, v[0], v[1], v[2]);
+ add_v3_v3(avg_no, no);
+ }
+ normalize_v3(avg_no);
+
+ /* push vertex away from the plane */
+ dist = v3_dist_from_plane(me->mvert[i].co, center, avg_no);
+ copy_v3_v3(push, avg_no);
+ mul_v3_fl(push, dist);
+ add_v3_v3(me->mvert[i].co, push);
+
+ }
+
+ MEM_freeN(origco);
+ cddm->release(cddm);
+
+ /* subdivide the mesh to highest level without displacements */
+ cddm = CDDM_from_mesh(me, NULL);
+ DM_set_only_copy(cddm, CD_MASK_BAREMESH);
+ origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0);
+ cddm->release(cddm);
+
+ /* calc disps */
+ multiresModifier_disp_run(dispdm, me, 1, 0, origdm->getGridData(origdm), totlvl);
+
+ origdm->release(origdm);
+ dispdm->release(dispdm);
+}
+
+static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl, int updateblock, int simple)
{
Mesh *me = ob->data;
MDisps *mdisps;
int lvl= mmd->totlvl;
- int totlvl= mmd->totlvl+1;
if(totlvl > multires_max_levels)
return;
@@ -510,6 +674,11 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat
multires_set_tot_level(ob, mmd, totlvl);
}
+void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple)
+{
+ multires_subdivide(mmd, ob, mmd->totlvl+1, updateblock, simple);
+}
+
static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3])
{
if(axis == 0) {
@@ -541,7 +710,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int
MPoly *mpoly = me->mpoly;
MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
int *gridOffset;
- int i, k, numGrids, gridSize, dGridSize, dSkip;
+ int i, k, /*numGrids,*/ gridSize, dGridSize, dSkip;
if(!mdisps) {
if(invert)
@@ -550,7 +719,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int
return;
}
- numGrids = dm->getNumGrids(dm);
+ /*numGrids = dm->getNumGrids(dm);*/ /*UNUSED*/
gridSize = dm->getGridSize(dm);
gridData = dm->getGridData(dm);
gridOffset = dm->getGridOffset(dm);
@@ -747,7 +916,7 @@ void multires_stitch_grids(Object *ob)
}
DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob,
- int useRenderParams, int isFinalCalc)
+ int useRenderParams, int UNUSED(isFinalCalc))
{
Mesh *me= ob->data;
DerivedMesh *result;
@@ -802,7 +971,7 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca
***************************/
/* Adapted from sculptmode.c */
-static void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v)
+void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v)
{
int x, y, x2, y2;
const int st_max = st - 1;
@@ -843,7 +1012,7 @@ static void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u
add_v3_v3v3(out, d2[0], d2[1]);
}
-static void old_mdisps_rotate(int S, int newside, int oldside, int x, int y, float *u, float *v)
+static void old_mdisps_rotate(int S, int UNUSED(newside), int oldside, int x, int y, float *u, float *v)
{
float offset = oldside*0.5f - 0.5f;
@@ -998,7 +1167,12 @@ static void create_old_vert_edge_map(ListBase **map, IndexNode **mem, const Mult
static MultiresFace *find_old_face(ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4)
{
IndexNode *n1;
- int v[4] = {v1, v2, v3, v4}, i, j;
+ int v[4], i, j;
+
+ v[0]= v1;
+ v[1]= v2;
+ v[2]= v3;
+ v[3]= v4;
for(n1 = map[v1].first; n1; n1 = n1->next) {
int fnd[4] = {0, 0, 0, 0};
@@ -1145,18 +1319,18 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
MultiresLevel *lvl, *lvl1;
Multires *mr= me->mr;
MVert *vsrc, *vdst;
- int src, dst;
+ unsigned int src, dst;
int st = multires_side_tot[totlvl - 1] - 1;
int extedgelen = multires_side_tot[totlvl] - 2;
int *vvmap; // inorder for dst, map to src
int crossedgelen;
- int i, j, s, x, totvert, tottri, totquad;
+ int s, x, tottri, totquad;
+ unsigned int i, j, totvert;
src = 0;
- dst = 0;
vsrc = mr->verts;
vdst = dm->getVertArray(dm);
- totvert = dm->getNumVerts(dm);
+ totvert = (unsigned int)dm->getNumVerts(dm);
vvmap = MEM_callocN(sizeof(int) * totvert, "multires vvmap");
lvl1 = mr->levels.first;
@@ -1247,7 +1421,7 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
fmem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires fmem");
emem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires emem");
lvl = lvl1;
- for(i = 0; i < mr->level_count - 1; ++i) {
+ for(i = 0; i < (unsigned int)mr->level_count - 1; ++i) {
create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface);
create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge);
lvl = lvl->next;
@@ -1282,9 +1456,9 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
dst = ldst;
}
- lvl = lvl->next;
+ /*lvl = lvl->next;*/ /*UNUSED*/
- for(i = 0; i < mr->level_count - 1; ++i) {
+ for(i = 0; i < (unsigned int)(mr->level_count - 1); ++i) {
MEM_freeN(fmap[i]);
MEM_freeN(fmem[i]);
MEM_freeN(emap[i]);
@@ -1306,6 +1480,52 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
multires_mvert_to_ss(dm, vdst);
}
+/* Copy the first-level vcol data to the mesh, if it exists */
+/* Warning: higher-level vcol data will be lost */
+static void multires_load_old_vcols(Mesh *me)
+{
+ MultiresLevel *lvl;
+ MultiresColFace *colface;
+ MCol *mcol;
+ int i, j;
+
+ if(!(lvl = me->mr->levels.first))
+ return;
+
+ if(!(colface = lvl->colfaces))
+ return;
+
+ /* older multires format never supported multiple vcol layers,
+ so we can assume the active vcol layer is the correct one */
+ if(!(mcol = CustomData_get_layer(&me->fdata, CD_MCOL)))
+ return;
+
+ for(i = 0; i < me->totface; ++i) {
+ for(j = 0; j < 4; ++j) {
+ mcol[i*4 + j].a = colface[i].col[j].a;
+ mcol[i*4 + j].r = colface[i].col[j].r;
+ mcol[i*4 + j].g = colface[i].col[j].g;
+ mcol[i*4 + j].b = colface[i].col[j].b;
+ }
+ }
+}
+
+/* Copy the first-level face-flag data to the mesh */
+static void multires_load_old_face_flags(Mesh *me)
+{
+ MultiresLevel *lvl;
+ MultiresFace *faces;
+ int i;
+
+ if(!(lvl = me->mr->levels.first))
+ return;
+
+ if(!(faces = lvl->faces))
+ return;
+
+ for(i = 0; i < me->totface; ++i)
+ me->mface[i].flag = faces[i].flag;
+}
void multires_load_old(Object *ob, Mesh *me)
{
@@ -1367,8 +1587,593 @@ void multires_load_old(Object *ob, Mesh *me)
memset(&me->mr->vdata, 0, sizeof(CustomData));
memset(&me->mr->fdata, 0, sizeof(CustomData));
+ multires_load_old_vcols(me);
+ multires_load_old_face_flags(me);
+
/* Remove the old multires */
multires_free(me->mr);
me->mr= NULL;
}
+static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob)
+{
+ MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1);
+ MultiresModifierData *to_mmd= get_multires_modifier(scene, to_ob, 1);
+
+ if(!mmd) {
+ /* object could have MDISP even when there is no multires modifier
+ this could lead to troubles due to i've got no idea how mdisp could be
+ upsampled correct without modifier data.
+ just remove mdisps if no multires present (nazgul) */
+
+ Mesh *me= (Mesh*)ob->data;
+
+ CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
+ CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
+ }
+
+ if(!mmd || !to_mmd) return;
+
+ if(mmd->totlvl>to_mmd->totlvl) multires_del_higher(mmd, ob, to_mmd->totlvl);
+ else multires_subdivide(mmd, ob, to_mmd->totlvl, 0, mmd->simple);
+}
+
+static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
+{
+ DerivedMesh *dm= NULL, *cddm= NULL, *subdm= NULL;
+ DMGridData **gridData, **subGridData;
+ Mesh *me= (Mesh*)ob->data;
+ MFace *mface= me->mface;
+ MDisps *mdisps;
+ int *gridOffset;
+ int i, /*numGrids,*/ gridSize, dGridSize, dSkip, totvert;
+ float (*vertCos)[3] = NULL;
+ MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1);
+ MultiresModifierData high_mmd;
+
+ CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
+ mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
+
+ if(!mdisps || !mmd) return;
+
+ /* we need derived mesh created from highest resolution */
+ high_mmd= *mmd;
+ high_mmd.lvl= high_mmd.totlvl;
+
+ /* unscaled multires with applied displacement */
+ subdm= get_multires_dm(scene, &high_mmd, ob);
+
+ /* prepare scaled CDDM to create ccgDN */
+ cddm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+
+ totvert= cddm->getNumVerts(cddm);
+ vertCos= MEM_mallocN(sizeof(*vertCos) * totvert, "multiresScale vertCos");
+ cddm->getVertCos(cddm, vertCos);
+ for(i=0; i<totvert; i++)
+ mul_m3_v3(smat, vertCos[i]);
+ CDDM_apply_vert_coords(cddm, vertCos);
+ MEM_freeN(vertCos);
+
+ /* scaled ccgDM for tangent space of object with applied scale */
+ dm= subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0);
+ cddm->release(cddm);
+
+ /*numGrids= dm->getNumGrids(dm);*/ /*UNUSED*/
+ gridSize= dm->getGridSize(dm);
+ gridData= dm->getGridData(dm);
+ gridOffset= dm->getGridOffset(dm);
+ subGridData= subdm->getGridData(subdm);
+
+ dGridSize= multires_side_tot[high_mmd.totlvl];
+ dSkip= (dGridSize-1)/(gridSize-1);
+
+ #pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT)
+ for(i = 0; i < me->totface; ++i) {
+ const int numVerts= mface[i].v4 ? 4 : 3;
+ MDisps *mdisp= &mdisps[i];
+ int S, x, y, gIndex = gridOffset[i];
+
+ for(S = 0; S < numVerts; ++S, ++gIndex) {
+ DMGridData *grid= gridData[gIndex];
+ DMGridData *subgrid= subGridData[gIndex];
+ float (*dispgrid)[3]= &mdisp->disps[S*dGridSize*dGridSize];
+
+ for(y = 0; y < gridSize; y++) {
+ for(x = 0; x < gridSize; x++) {
+ float *co= grid[x + y*gridSize].co;
+ float *sco= subgrid[x + y*gridSize].co;
+ float *no= grid[x + y*gridSize].no;
+ float *data= dispgrid[dGridSize*y*dSkip + x*dSkip];
+ float mat[3][3], tx[3], ty[3], disp[3];
+
+ /* construct tangent space matrix */
+ grid_tangent(gridSize, gIndex, x, y, 0, gridData, tx);
+ normalize_v3(tx);
+
+ grid_tangent(gridSize, gIndex, x, y, 1, gridData, ty);
+ normalize_v3(ty);
+
+ column_vectors_to_mat3(mat, tx, ty, no);
+
+ /* scale subgrid coord and calculate displacement */
+ mul_m3_v3(smat, sco);
+ sub_v3_v3v3(disp, sco, co);
+
+ /* convert difference to tangent space */
+ invert_m3(mat);
+ mul_v3_m3v3(data, mat, disp);
+ }
+ }
+ }
+ }
+
+ dm->release(dm);
+ subdm->release(subdm);
+}
+
+int multires_mdisp_corners(MDisps *s)
+{
+ int lvl= 13;
+
+ while(lvl > 0) {
+ int side = (1 << (lvl-1)) + 1;
+ if ((s->totdisp % (side*side)) == 0) return s->totdisp / (side*side);
+ lvl--;
+ }
+
+ return 0;
+}
+
+void multiresModifier_scale_disp(Scene *scene, Object *ob)
+{
+ float smat[3][3];
+
+ /* object's scale matrix */
+ object_scale_to_mat3(ob, smat);
+
+ multires_apply_smat(scene, ob, smat);
+}
+
+void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
+{
+ float smat[3][3], tmat[3][3], mat[3][3];
+ multires_sync_levels(scene, ob, to_ob);
+
+ /* construct scale matrix for displacement */
+ object_scale_to_mat3(to_ob, tmat);
+ invert_m3(tmat);
+ object_scale_to_mat3(ob, smat);
+ mul_m3_m3m3(mat, smat, tmat);
+
+ multires_apply_smat(scene, ob, mat);
+}
+
+/* update multires data after topology changing */
+void multires_topology_changed(Scene *scene, Object *ob)
+{
+ Mesh *me= (Mesh*)ob->data;
+ MDisps *mdisp= NULL, *cur= NULL;
+ int i, grid= 0, corners;
+ MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1);
+
+ if(mmd)
+ multires_set_tot_mdisps(me, mmd->totlvl);
+
+ CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
+ mdisp= CustomData_get_layer(&me->fdata, CD_MDISPS);
+
+ if(!mdisp) return;
+
+ cur= mdisp;
+ for(i = 0; i < me->totface; i++, cur++) {
+ if(mdisp->totdisp) {
+ corners= multires_mdisp_corners(mdisp);
+ grid= mdisp->totdisp / corners;
+
+ break;
+ }
+ }
+
+ for(i = 0; i < me->totface; i++, mdisp++) {
+ int nvert= me->mface[i].v4 ? 4 : 3;
+
+ /* allocate memory for mdisp, the whole disp layer would be erased otherwise */
+ if(!mdisp->totdisp) {
+ if(grid) {
+ mdisp->totdisp= nvert*grid;
+ mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology");
+ }
+
+ continue;
+ }
+
+ corners= multires_mdisp_corners(mdisp);
+
+ if(corners!=nvert) {
+ mdisp->totdisp= (mdisp->totdisp/corners)*nvert;
+
+ if(mdisp->disps)
+ MEM_freeN(mdisp->disps);
+
+ mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology");
+ }
+ }
+}
+
+/* makes displacement along grid boundary symmetrical */
+void multires_mdisp_smooth_bounds(MDisps *disps)
+{
+ int x, y, side, S, corners;
+ float (*out)[3];
+
+ corners = multires_mdisp_corners(disps);
+ side = sqrt(disps->totdisp / corners);
+
+ out = disps->disps;
+ for(S = 0; S < corners; S++) {
+ for(y = 0; y < side; ++y) {
+ for(x = 0; x < side; ++x, ++out) {
+ float (*dispgrid)[3];
+ float *data;
+
+ if(x != 0 && y != 0) continue;
+
+ if(corners == 4) {
+ if(S == 0) {
+ if(y == 0) {
+ dispgrid = &disps->disps[1*side*side];
+ data = dispgrid[side * x + 0];
+
+ (*out)[0] = (*out)[0] + data[1];
+ (*out)[1] = (*out)[1] - data[0];
+ (*out)[2] = (*out)[2] + data[2];
+
+ mul_v3_fl(*out, 0.5);
+
+ data[0] = -(*out)[1];
+ data[1] = (*out)[0];
+ data[2] = (*out)[2];
+ } else if (x == 0) {
+ dispgrid = &disps->disps[3 * side * side];
+ data = dispgrid[side * 0 + y];
+
+ (*out)[0] = (*out)[0] - data[1];
+ (*out)[1] = (*out)[1] + data[0];
+ (*out)[2] = (*out)[2] + data[2];
+
+ mul_v3_fl(*out, 0.5);
+
+ data[0] = (*out)[1];
+ data[1] = -(*out)[0];
+ data[2] = (*out)[2];
+ }
+ } else if (S == 2) {
+ if(y == 0) {
+ dispgrid = &disps->disps[3 * side * side];
+ data = dispgrid[side * x + 0];
+
+ (*out)[0] = (*out)[0] + data[1];
+ (*out)[1] = (*out)[1] - data[0];
+ (*out)[2] = (*out)[2] + data[2];
+
+ mul_v3_fl(*out, 0.5);
+
+ data[0] = -(*out)[1];
+ data[1] = (*out)[0];
+ data[2] = (*out)[2];
+ } else if(x == 0) {
+ dispgrid = &disps->disps[1 * side * side];
+ data = dispgrid[side * 0 + y];
+
+ (*out)[0] = (*out)[0] - data[1];
+ (*out)[1] = (*out)[1] + data[0];
+ (*out)[2] = (*out)[2] + data[2];
+
+ mul_v3_fl(*out, 0.5);
+
+ data[0] = (*out)[1];
+ data[1] = -(*out)[0];
+ data[2] = (*out)[2];
+ }
+ }
+ } else if (corners == 3) {
+ if(S == 0) {
+ if(y == 0) {
+ dispgrid = &disps->disps[1*side*side];
+ data = dispgrid[side * x + 0];
+
+ (*out)[0] = (*out)[0] + data[1];
+ (*out)[1] = (*out)[1] - data[0];
+ (*out)[2] = (*out)[2] + data[2];
+
+ mul_v3_fl(*out, 0.5);
+
+ data[0] = -(*out)[1];
+ data[1] = (*out)[0];
+ data[2] = (*out)[2];
+ } else if (x == 0) {
+ dispgrid = &disps->disps[2 * side * side];
+ data = dispgrid[side * 0 + y];
+
+ (*out)[0] = (*out)[0] - data[1];
+ (*out)[1] = (*out)[1] + data[0];
+ (*out)[2] = (*out)[2] + data[2];
+
+ mul_v3_fl(*out, 0.5);
+
+ data[0] = (*out)[1];
+ data[1] = -(*out)[0];
+ data[2] = (*out)[2];
+ }
+ } else if (S == 2) {
+ if(x == 0) {
+ dispgrid = &disps->disps[1 * side * side];
+ data = dispgrid[side * 0 + y];
+
+ (*out)[0] = (*out)[0] - data[1];
+ (*out)[1] = (*out)[1] + data[0];
+ (*out)[2] = (*out)[2] + data[2];
+
+ mul_v3_fl(*out, 0.5);
+
+ data[0] = (*out)[1];
+ data[1] = -(*out)[0];
+ data[2] = (*out)[2];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/***************** Multires interpolation stuff *****************/
+
+static void mdisp_get_crn_rect(int face_side, float crn[3][4][2])
+{
+ float offset = face_side*0.5f - 0.5f;
+ float mid[2];
+
+ mid[0] = offset * 4 / 3;
+ mid[1] = offset * 2 / 3;
+
+ crn[0][0][0] = mid[0]; crn[0][0][1] = mid[1];
+ crn[0][1][0] = offset; crn[0][1][1] = 0;
+ crn[0][2][0] = 0; crn[0][2][1] = 0;
+ crn[0][3][0] = offset; crn[0][3][1] = offset;
+
+ crn[1][0][0] = mid[0]; crn[1][0][1] = mid[1];
+ crn[1][1][0] = offset * 2; crn[1][1][1] = offset;
+ crn[1][2][0] = offset * 2; crn[1][2][1] = 0;
+ crn[1][3][0] = offset; crn[1][3][1] = 0;
+
+ crn[2][0][0] = mid[0]; crn[2][0][1] = mid[1];
+ crn[2][1][0] = offset; crn[2][1][1] = offset;
+ crn[2][2][0] = offset * 2; crn[2][2][1] = offset * 2;
+ crn[2][3][0] = offset * 2; crn[2][3][1] = offset;
+}
+
+static int mdisp_pt_in_crn(float p[2], float crn[4][2])
+{
+ float v[2][2];
+ float a[2][2];
+
+ sub_v2_v2v2(v[0], crn[1], crn[0]);
+ sub_v2_v2v2(v[1], crn[3], crn[0]);
+
+ sub_v2_v2v2(a[0], p, crn[0]);
+ sub_v2_v2v2(a[1], crn[2], crn[0]);
+
+ if(cross_v2v2(a[0], v[0]) * cross_v2v2(a[1], v[0]) < 0)
+ return 0;
+
+ if(cross_v2v2(a[0], v[1]) * cross_v2v2(a[1], v[1]) < 0)
+ return 0;
+
+ return 1;
+}
+
+static void face_to_crn_interp(float u, float v, float v1[2], float v2[2], float v3[2], float v4[2], float *x)
+{
+ float a = (v4[1]-v3[1])*v2[0]+(-v4[1]+v3[1])*v1[0]+(-v2[1]+v1[1])*v4[0]+(v2[1]-v1[1])*v3[0];
+ float b = (v3[1]-v)*v2[0]+(v4[1]-2*v3[1]+v)*v1[0]+(-v4[1]+v3[1]+v2[1]-v1[1])*u+(v4[0]-v3[0])*v-v1[1]*v4[0]+(-v2[1]+2*v1[1])*v3[0];
+ float c = (v3[1]-v)*v1[0]+(-v3[1]+v1[1])*u+v3[0]*v-v1[1]*v3[0];
+ float d = b * b - 4 * a * c;
+ float x1, x2;
+
+ if(a == 0) {
+ *x = -c / b;
+ return;
+ }
+
+ x1 = (-b - sqrtf(d)) / (2 * a);
+ x2 = (-b + sqrtf(d)) / (2 * a);
+
+ *x = maxf(x1, x2);
+}
+
+void mdisp_rot_crn_to_face(const int S, const int corners, const int face_side, const float x, const float y, float *u, float *v)
+{
+ float offset = face_side*0.5f - 0.5f;
+
+ if(corners == 4) {
+ if(S == 1) { *u= offset + x; *v = offset - y; }
+ if(S == 2) { *u= offset + y; *v = offset + x; }
+ if(S == 3) { *u= offset - x; *v = offset + y; }
+ if(S == 0) { *u= offset - y; *v = offset - x; }
+ } else {
+ float crn[3][4][2], vec[4][2];
+ float p[2];
+
+ mdisp_get_crn_rect(face_side, crn);
+
+ interp_v2_v2v2(vec[0], crn[S][0], crn[S][1], x / offset);
+ interp_v2_v2v2(vec[1], crn[S][3], crn[S][2], x / offset);
+ interp_v2_v2v2(vec[2], crn[S][0], crn[S][3], y / offset);
+ interp_v2_v2v2(vec[3], crn[S][1], crn[S][2], y / offset);
+
+ isect_seg_seg_v2_point(vec[0], vec[1], vec[2], vec[3], p);
+
+ (*u) = p[0];
+ (*v) = p[1];
+ }
+}
+
+int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y)
+{
+ const float offset = face_side*0.5f - 0.5f;
+ int S = 0;
+
+ if (corners == 4) {
+ if(u <= offset && v <= offset) S = 0;
+ else if(u > offset && v <= offset) S = 1;
+ else if(u > offset && v > offset) S = 2;
+ else if(u <= offset && v >= offset) S = 3;
+
+ if(S == 0) {
+ *y = offset - u;
+ *x = offset - v;
+ } else if(S == 1) {
+ *x = u - offset;
+ *y = offset - v;
+ } else if(S == 2) {
+ *y = u - offset;
+ *x = v - offset;
+ } else if(S == 3) {
+ *x= offset - u;
+ *y = v - offset;
+ }
+ } else {
+ float crn[3][4][2];
+ float p[2] = {u, v};
+
+ mdisp_get_crn_rect(face_side, crn);
+
+ for (S = 0; S < 3; ++S) {
+ if (mdisp_pt_in_crn(p, crn[S]))
+ break;
+ }
+
+ face_to_crn_interp(u, v, crn[S][0], crn[S][1], crn[S][3], crn[S][2], &p[0]);
+ face_to_crn_interp(u, v, crn[S][0], crn[S][3], crn[S][1], crn[S][2], &p[1]);
+
+ *x = p[0] * offset;
+ *y = p[1] * offset;
+ }
+
+ return S;
+}
+
+void mdisp_apply_weight(const int S, const int corners, int x, int y, const int face_side,
+ float crn_weight[4][2], float *u_r, float *v_r)
+{
+ float u, v, xl, yl;
+ float mid1[2], mid2[2], mid3[2];
+
+ mdisp_rot_crn_to_face(S, corners, face_side, x, y, &u, &v);
+
+ if(corners == 4) {
+ xl = u / (face_side - 1);
+ yl = v / (face_side - 1);
+
+ mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl;
+ mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl;
+ mid2[0] = crn_weight[3][0] * (1 - xl) + crn_weight[2][0] * xl;
+ mid2[1] = crn_weight[3][1] * (1 - xl) + crn_weight[2][1] * xl;
+ mid3[0] = mid1[0] * (1 - yl) + mid2[0] * yl;
+ mid3[1] = mid1[1] * (1 - yl) + mid2[1] * yl;
+ } else {
+ yl = v / (face_side - 1);
+
+ if(v == face_side - 1) xl = 1;
+ else xl = 1 - (face_side - 1 - u) / (face_side - 1 - v);
+
+ mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl;
+ mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl;
+ mid3[0] = mid1[0] * (1 - yl) + crn_weight[2][0] * yl;
+ mid3[1] = mid1[1] * (1 - yl) + crn_weight[2][1] * yl;
+ }
+
+ *u_r = mid3[0];
+ *v_r = mid3[1];
+}
+
+void mdisp_flip_disp(const int S, const int corners, const float axis_x[2], const float axis_y[2], float disp[3])
+{
+ float crn_x[2], crn_y[2];
+ float vx[2], vy[2], coord[2];
+
+ if (corners == 4) {
+ float x[4][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
+ float y[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
+
+ copy_v2_v2(crn_x, x[S]);
+ copy_v2_v2(crn_y, y[S]);
+
+ mul_v2_v2fl(vx, crn_x, disp[0]);
+ mul_v2_v2fl(vy, crn_y, disp[1]);
+ add_v2_v2v2(coord, vx, vy);
+
+ project_v2_v2v2(vx, coord, axis_x);
+ project_v2_v2v2(vy, coord, axis_y);
+
+ disp[0] = len_v2(vx);
+ disp[1] = len_v2(vy);
+
+ if(dot_v2v2(vx, axis_x) < 0)
+ disp[0] = -disp[0];
+
+ if(dot_v2v2(vy, axis_y) < 0)
+ disp[1] = -disp[1];
+ } else {
+ /* XXX: it was very overhead code to support displacement flipping
+ for case of tris without visible profit.
+ Maybe its not really big limitation? for now? (nazgul) */
+ disp[0] = 0;
+ disp[1] = 0;
+ }
+}
+
+/* Join two triangular displacements into one quad
+ Corners mapping:
+ 2 -------- 3
+ | \ tri2 |
+ | \ |
+ | tri1 \ |
+ 0 -------- 1 */
+void mdisp_join_tris(MDisps *dst, MDisps *tri1, MDisps *tri2)
+{
+ int side, st;
+ int S, x, y, crn;
+ float face_u, face_v, crn_u, crn_v;
+ float (*out)[3];
+ MDisps *src;
+
+ if(dst->disps)
+ MEM_freeN(dst->disps);
+
+ side = sqrt(tri1->totdisp / 3);
+ st = (side<<1)-1;
+
+ dst->totdisp = 4 * side * side;
+ out = dst->disps = MEM_callocN(3*dst->totdisp*sizeof(float), "join disps");
+
+ for(S = 0; S < 4; S++)
+ for(y = 0; y < side; ++y)
+ for(x = 0; x < side; ++x, ++out) {
+ mdisp_rot_crn_to_face(S, 4, st, x, y, &face_u, &face_v);
+ face_u = st - 1 - face_u;
+
+ if(face_v > face_u) {
+ src = tri2;
+ face_u = st - 1 - face_u;
+ face_v = st - 1 - face_v;
+ } else src = tri1;
+
+ crn = mdisp_rot_face_to_crn(3, st, face_u, face_v, &crn_u, &crn_v);
+
+ old_mdisps_bilinear((*out), &src->disps[crn*side*side], side, crn_u, crn_v);
+ (*out)[0] = 0;
+ (*out)[1] = 0;
+ }
+}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index b053d615756..df012c47f66 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -36,6 +36,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "DNA_anim_types.h"
@@ -46,7 +47,7 @@
#include "BKE_nla.h"
#include "BKE_global.h"
#include "BKE_library.h"
-#include "BKE_utildefines.h"
+
#include "RNA_access.h"
#include "nla_private.h"
@@ -77,7 +78,7 @@ void free_nlastrip (ListBase *strips, NlaStrip *strip)
/* remove reference to action */
if (strip->act)
- strip->act->id.us--;
+ id_us_min(&strip->act->id);
/* free remapping info */
//if (strip->remap)
@@ -159,7 +160,7 @@ NlaStrip *copy_nlastrip (NlaStrip *strip)
/* increase user-count of action */
if (strip_d->act)
- strip_d->act->id.us++;
+ id_us_plus(&strip_d->act->id);
/* copy F-Curves and modifiers */
copy_fcurves(&strip_d->fcurves, &strip->fcurves);
@@ -362,7 +363,7 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short
return strip->end - scale*(cframe - strip->actstart);
}
else if (mode == NLATIME_CONVERT_UNMAP) {
- return strip->actend - (strip->end - cframe) / scale;
+ return (strip->end + (strip->actstart * scale - cframe)) / scale;
}
else /* if (mode == NLATIME_CONVERT_EVAL) */{
if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) {
@@ -513,7 +514,7 @@ short BKE_nlastrips_has_space (ListBase *strips, float start, float end)
/* if start frame of strip is past the target end-frame, that means that
* we've gone past the window we need to check for, so things are fine
*/
- if (strip->start > end)
+ if (strip->start >= end)
return 1;
/* if the end of the strip is greater than either of the boundaries, the range
@@ -590,7 +591,7 @@ short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip)
/* find the right place to add the strip to the nominated track */
for (ns= strips->first; ns; ns= ns->next) {
/* if current strip occurs after the new strip, add it before */
- if (ns->start > strip->end) {
+ if (ns->start >= strip->end) {
BLI_insertlinkbefore(strips, ns, strip);
not_added= 0;
break;
@@ -682,7 +683,7 @@ void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip)
}
/* free the meta-strip now */
- BLI_freelinkN(strips, strip);
+ free_nlastrip(strips, strip);
}
/* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
@@ -916,9 +917,14 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
/* Check if there is any space in the given track to add a strip of the given length */
short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
{
- /* sanity checks */
- if ((nlt == NULL) || IS_EQ(start, end))
+ /* sanity checks
+ * - track must exist
+ * - track must be editable
+ * - bounds cannot be equal (0-length is nasty)
+ */
+ if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQ(start, end))
return 0;
+
if (start > end) {
puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
SWAP(float, start, end);
@@ -1206,6 +1212,11 @@ void BKE_nlastrip_validate_fcurves (NlaStrip *strip)
/* Sanity Validation ------------------------------------ */
+static int nla_editbone_name_check(void *arg, const char *name)
+{
+ return BLI_ghash_haskey((GHash *)arg, (void *)name);
+}
+
/* Find (and set) a unique name for a strip from the whole AnimData block
* Uses a similar method to the BLI method, but is implemented differently
* as we need to ensure that the name is unique over several lists of tracks,
@@ -1259,28 +1270,8 @@ void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip)
/* if the hash-table has a match for this name, try other names...
* - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :)
*/
- if (BLI_ghash_haskey(gh, strip->name)) {
- char tempname[128];
- int number = 1;
- char *dot;
-
- /* Strip off the suffix */
- dot = strrchr(strip->name, '.');
- if (dot) *dot=0;
-
- /* Try different possibilities */
- for (number = 1; number <= 999; number++) {
- /* assemble alternative name */
- BLI_snprintf(tempname, 128, "%s.%03d", strip->name, number);
-
- /* if hash doesn't have this, set it */
- if (BLI_ghash_haskey(gh, tempname) == 0) {
- BLI_strncpy(strip->name, tempname, sizeof(strip->name));
- break;
- }
- }
- }
-
+ BLI_uniquename_cb(nla_editbone_name_check, (void *)gh, "NlaStrip", '.', strip->name, sizeof(strip->name));
+
/* free the hash... */
BLI_ghash_free(gh, NULL, NULL);
}
@@ -1329,7 +1320,7 @@ static void nlastrip_get_endpoint_overlaps (NlaStrip *strip, NlaTrack *track, fl
}
/* Determine auto-blending for the given strip */
-void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls)
+static void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls)
{
float *ps=NULL, *pe=NULL;
float *ns=NULL, *ne=NULL;
@@ -1447,7 +1438,7 @@ void BKE_nla_action_pushdown (AnimData *adt)
/* do other necessary work on strip */
if (strip) {
/* clear reference to action now that we've pushed it onto the stack */
- adt->action->id.us--;
+ id_us_min(&adt->action->id);
adt->action= NULL;
/* if the strip is the first one in the track it lives in, check if there
@@ -1585,7 +1576,7 @@ void BKE_nla_tweakmode_exit (AnimData *adt)
/* Baking Tools ------------------------------------------- */
-void BKE_nla_bake (Scene *scene, ID *id, AnimData *adt, int flag)
+static void BKE_nla_bake (Scene *scene, ID *UNUSED(id), AnimData *adt, int UNUSED(flag))
{
/* verify that data is valid
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index eb09ecf2e6e..53bac9171ae 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -27,25 +27,34 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
#include <Python.h>
#endif
+#include "MEM_guardedalloc.h"
+
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
+#include <limits.h>
#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_node_types.h"
+
+#include "BLI_listbase.h"
#include "RNA_access.h"
+#include "BKE_animsys.h"
+#include "BKE_action.h"
#include "BKE_fcurve.h"
-#include "BKE_animsys.h" /* BKE_free_animdata only */
-
+#include "BKE_node.h"
+#include "BKE_utildefines.h"
+#include "BKE_node.h"
#include "PIL_time.h"
-
#include "CMP_node.h"
#include "intern/CMP_util.h" /* stupid include path... */
@@ -62,22 +71,14 @@ ListBase node_all_textures = {NULL, NULL};
/* ************** Type stuff ********** */
-static bNodeType *node_get_type(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
+static bNodeType *node_get_type(bNodeTree *ntree, int type, ID *id)
{
- if(type==NODE_GROUP) {
- if(ngroup && GS(ngroup->id.name)==ID_NT) {
- return ngroup->owntype;
- }
- return NULL;
- }
- else {
- bNodeType *ntype = ntree->alltypes.first;
- for(; ntype; ntype= ntype->next)
- if(ntype->type==type && id==ntype->id )
- return ntype;
-
- return NULL;
- }
+ bNodeType *ntype = ntree->alltypes.first;
+ for(; ntype; ntype= ntype->next)
+ if(ntype->type==type && id==ntype->id )
+ return ntype;
+
+ return NULL;
}
void ntreeInitTypes(bNodeTree *ntree)
@@ -100,11 +101,11 @@ void ntreeInitTypes(bNodeTree *ntree)
if(node->type==NODE_DYNAMIC) {
bNodeType *stype= NULL;
if(node->id==NULL) { /* empty script node */
- stype= node_get_type(ntree, node->type, NULL, NULL);
+ stype= node_get_type(ntree, node->type, NULL);
} else { /* not an empty script node */
- stype= node_get_type(ntree, node->type, NULL, node->id);
+ stype= node_get_type(ntree, node->type, node->id);
if(!stype) {
- stype= node_get_type(ntree, node->type, NULL, NULL);
+ stype= node_get_type(ntree, node->type, NULL);
/* needed info if the pynode script fails now: */
if (node->id) node->storage= ntree;
} else {
@@ -116,7 +117,7 @@ void ntreeInitTypes(bNodeTree *ntree)
if(node->typeinfo)
node->typeinfo->initfunc(node);
} else {
- node->typeinfo= node_get_type(ntree, node->type, (bNodeTree *)node->id, NULL);
+ node->typeinfo= node_get_type(ntree, node->type, NULL);
}
if(node->typeinfo==NULL) {
@@ -150,9 +151,6 @@ static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype)
else sock->limit= stype->limit;
sock->type= stype->type;
- sock->to_index= stype->own_index;
- sock->tosock= stype->internsock;
-
sock->ns.vec[0]= stype->val1;
sock->ns.vec[1]= stype->val2;
sock->ns.vec[2]= stype->val3;
@@ -166,6 +164,30 @@ static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype)
return sock;
}
+static bNodeSocket *node_add_group_socket(ListBase *lb, bNodeSocket *gsock)
+{
+ bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock");
+
+ /* make a copy of the group socket */
+ *sock = *gsock;
+ sock->link = NULL;
+ sock->next = sock->prev = NULL;
+ sock->new_sock = NULL;
+ sock->ns.data = NULL;
+
+ sock->own_index = gsock->own_index;
+ sock->groupsock = gsock;
+ /* XXX hack: group socket input/output roles are inverted internally,
+ * need to change the limit value when making actual node sockets from them.
+ */
+ sock->limit = (gsock->limit==1 ? 0xFFF : 1);
+
+ if(lb)
+ BLI_addtail(lb, sock);
+
+ return sock;
+}
+
static void node_rem_socket(bNodeTree *ntree, ListBase *lb, bNodeSocket *sock)
{
bNodeLink *link, *next;
@@ -186,18 +208,16 @@ static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype)
bNodeSocket *sock;
for(sock= lb->first; sock; sock= sock->next) {
- /* both indices are zero for non-groups, otherwise it's a unique index */
- if(sock->to_index==stype->own_index)
- if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0)
- break;
+ if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0)
+ break;
}
if(sock) {
sock->type= stype->type; /* in future, read this from tydefs! */
if(stype->limit==0) sock->limit= 0xFFF;
else sock->limit= stype->limit;
+
sock->ns.min= stype->min;
sock->ns.max= stype->max;
- sock->tosock= stype->internsock;
BLI_remlink(lb, sock);
@@ -208,6 +228,37 @@ static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype)
}
}
+static bNodeSocket *verify_group_socket(ListBase *lb, bNodeSocket *gsock)
+{
+ bNodeSocket *sock;
+
+ for(sock= lb->first; sock; sock= sock->next) {
+ if(sock->own_index==gsock->own_index)
+ break;
+ }
+ if(sock) {
+ sock->groupsock = gsock;
+
+ strcpy(sock->name, gsock->name);
+ sock->type= gsock->type;
+
+ /* XXX hack: group socket input/output roles are inverted internally,
+ * need to change the limit value when making actual node sockets from them.
+ */
+ sock->limit = (gsock->limit==1 ? 0xFFF : 1);
+
+ sock->ns.min= gsock->ns.min;
+ sock->ns.max= gsock->ns.max;
+
+ BLI_remlink(lb, sock);
+
+ return sock;
+ }
+ else {
+ return node_add_group_socket(NULL, gsock);
+ }
+}
+
static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType *stype_first)
{
bNodeSocketType *stype;
@@ -236,15 +287,41 @@ static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType *
}
}
-void nodeVerifyType(bNodeTree *ntree, bNode *node)
+static void verify_group_socket_list(bNodeTree *ntree, ListBase *lb, ListBase *glb)
{
- bNodeType *ntype= node->typeinfo;
+ bNodeSocket *gsock;
- if(ntype) {
- /* might add some other verify stuff here */
-
- verify_socket_list(ntree, &node->inputs, ntype->inputs);
- verify_socket_list(ntree, &node->outputs, ntype->outputs);
+ /* step by step compare */
+ for (gsock= glb->first; gsock; gsock=gsock->next) {
+ /* abusing new_sock pointer for verification here! only used inside this function */
+ gsock->new_sock= verify_group_socket(lb, gsock);
+ }
+ /* leftovers are removed */
+ while(lb->first)
+ node_rem_socket(ntree, lb, lb->first);
+ /* and we put back the verified sockets */
+ for (gsock= glb->first; gsock; gsock=gsock->next) {
+ BLI_addtail(lb, gsock->new_sock);
+ gsock->new_sock = NULL;
+ }
+}
+
+void nodeVerifyType(bNodeTree *ntree, bNode *node)
+{
+ /* node groups don't have static sock lists, but use external sockets from the tree instead */
+ if (node->type==NODE_GROUP) {
+ bNodeTree *ngroup= (bNodeTree*)node->id;
+ if (ngroup) {
+ verify_group_socket_list(ntree, &node->inputs, &ngroup->inputs);
+ verify_group_socket_list(ntree, &node->outputs, &ngroup->outputs);
+ }
+ }
+ else {
+ bNodeType *ntype= node->typeinfo;
+ if(ntype) {
+ verify_socket_list(ntree, &node->inputs, ntype->inputs);
+ verify_socket_list(ntree, &node->outputs, ntype->outputs);
+ }
}
}
@@ -263,193 +340,38 @@ void ntreeVerifyTypes(bNodeTree *ntree)
/* ************** Group stuff ********** */
-bNodeType node_group_typeinfo= {
- /* next,prev */ NULL, NULL,
- /* type code */ NODE_GROUP,
- /* name */ "Group",
- /* width+range */ 120, 60, 200,
- /* class+opts */ NODE_CLASS_GROUP, NODE_OPTIONS,
- /* input sock */ NULL,
- /* output sock */ NULL,
- /* storage */ "",
- /* execfunc */ NULL,
- /* butfunc */ NULL,
- /* initfunc */ NULL,
- /* freestoragefunc */ NULL,
- /* copystoragefunc */ NULL,
- /* id */ NULL
-};
-
-/* tag internal sockets */
-static void group_tag_internal_sockets(bNodeTree *ngroup)
-{
- bNode *node;
- bNodeSocket *sock;
- bNodeLink *link;
-
- /* clear intern tag, but check already for hidden sockets */
- for(node= ngroup->nodes.first; node; node= node->next) {
- for(sock= node->inputs.first; sock; sock= sock->next)
- sock->intern= sock->flag & SOCK_HIDDEN;
- for(sock= node->outputs.first; sock; sock= sock->next)
- sock->intern= sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL);
- }
- /* set tag */
- for(link= ngroup->links.first; link; link= link->next) {
- link->fromsock->intern= 1;
- link->tosock->intern= 1;
- }
-
- /* remove link pointer to external links (only happens on create group) */
- for(node= ngroup->nodes.first; node; node= node->next) {
- for(sock= node->inputs.first; sock; sock= sock->next)
- if(sock->intern==0)
- sock->link= NULL;
- }
+/* XXX group typeinfo struct is used directly in ntreeMakeOwnType, needs cleanup */
+static bNodeType ntype_group;
- /* set all intern sockets to own_index zero, makes sure that later use won't mixup */
- for(node= ngroup->nodes.first; node; node= node->next) {
- for(sock= node->inputs.first; sock; sock= sock->next)
- if(sock->intern)
- sock->own_index= 0;
- for(sock= node->outputs.first; sock; sock= sock->next)
- if(sock->intern)
- sock->own_index= 0;
- }
-}
-
-/* after editing group, new sockets are zero */
-/* this routine ensures unique identifiers for zero sockets that are exposed */
-static void group_verify_own_indices(bNodeTree *ngroup)
+/* groups display their internal tree name as label */
+static const char *group_label(bNode *node)
{
- bNode *node;
- bNodeSocket *sock;
-
- for(node= ngroup->nodes.first; node; node= node->next) {
- for(sock= node->inputs.first; sock; sock= sock->next)
- if(sock->own_index==0 && sock->intern==0)
- sock->own_index= ++(ngroup->cur_index);
- for(sock= node->outputs.first; sock; sock= sock->next)
- if(sock->own_index==0 && sock->intern==0)
- sock->own_index= ++(ngroup->cur_index);
- }
- //printf("internal index %d\n", ngroup->cur_index);
+ return node->id->name+2;
}
-
-/* nodetrees can be used as groups, so we need typeinfo structs generated */
-void ntreeMakeOwnType(bNodeTree *ngroup)
+void register_node_type_group(ListBase *lb)
{
- bNode *node;
- bNodeSocket *sock;
- int totin= 0, totout=0, a;
-
- /* tags socket when internal linked */
- group_tag_internal_sockets(ngroup);
-
- /* ensure all sockets have own unique id */
- group_verify_own_indices(ngroup);
-
- /* counting stats */
- for(node= ngroup->nodes.first; node; node= node->next) {
- if(node->type==NODE_GROUP)
- break;
- for(sock= node->inputs.first; sock; sock= sock->next)
- if(sock->intern==0)
- totin++;
- for(sock= node->outputs.first; sock; sock= sock->next)
- if(sock->intern==0)
- totout++;
- }
- /* debug: nodetrees in nodetrees not handled yet */
- if(node) {
- printf("group in group, not supported yet\n");
- return;
- }
-
- /* free own type struct */
- if(ngroup->owntype) {
- if(ngroup->owntype->inputs)
- MEM_freeN(ngroup->owntype->inputs);
- if(ngroup->owntype->outputs)
- MEM_freeN(ngroup->owntype->outputs);
- MEM_freeN(ngroup->owntype);
- }
-
- /* make own type struct */
- ngroup->owntype= MEM_callocN(sizeof(bNodeType), "group type");
- *ngroup->owntype= node_group_typeinfo; /* copy data, for init */
-
- /* input type arrays */
- if(totin) {
- bNodeSocketType *stype;
- bNodeSocketType *inputs= MEM_callocN(sizeof(bNodeSocketType)*(totin+1), "bNodeSocketType");
- a= 0;
-
- for(node= ngroup->nodes.first; node; node= node->next) {
- /* nodes are presumed fully verified, stype and socket list are in sync */
- stype= node->typeinfo->inputs;
- for(sock= node->inputs.first; sock; sock= sock->next, stype++) {
- if(sock->intern==0) {
- /* debug only print */
- if(stype==NULL || stype->type==-1) printf("group verification error %s\n", ngroup->id.name);
-
- inputs[a]= *stype;
- inputs[a].own_index= sock->own_index;
- inputs[a].internsock= sock;
- a++;
- }
- }
- }
- inputs[a].type= -1; /* terminator code */
- ngroup->owntype->inputs= inputs;
- }
-
- /* output type arrays */
- if(totout) {
- bNodeSocketType *stype;
- bNodeSocketType *outputs= MEM_callocN(sizeof(bNodeSocketType)*(totout+1), "bNodeSocketType");
- a= 0;
-
- for(node= ngroup->nodes.first; node; node= node->next) {
- /* nodes are presumed fully verified, stype and socket list are in sync */
- stype= node->typeinfo->outputs;
- for(sock= node->outputs.first; sock; sock= sock->next, stype++) {
- if(sock->intern==0) {
- /* debug only print */
- if(stype==NULL || stype->type==-1) printf("group verification error %s\n", ngroup->id.name);
-
- outputs[a]= *stype;
- outputs[a].own_index= sock->own_index;
- outputs[a].internsock= sock;
- a++;
- }
- }
- }
- outputs[a].type= -1; /* terminator code */
- ngroup->owntype->outputs= outputs;
- }
+ node_type_base(&ntype_group, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS, NULL, NULL);
+ node_type_size(&ntype_group, 120, 60, 200);
+ node_type_label(&ntype_group, group_label);
- /* voila, the nodetree has the full definition for generating group-node instances! */
+ nodeRegisterType(lb, &ntype_group);
}
-
-static bNodeSocket *groupnode_find_tosock(bNode *gnode, int index)
+static bNodeSocket *find_group_node_input(bNode *gnode, bNodeSocket *gsock)
{
bNodeSocket *sock;
-
- for(sock= gnode->inputs.first; sock; sock= sock->next)
- if(sock->to_index==index)
+ for (sock=gnode->inputs.first; sock; sock=sock->next)
+ if (sock->groupsock == gsock)
return sock;
return NULL;
}
-static bNodeSocket *groupnode_find_fromsock(bNode *gnode, int index)
+static bNodeSocket *find_group_node_output(bNode *gnode, bNodeSocket *gsock)
{
bNodeSocket *sock;
-
- for(sock= gnode->outputs.first; sock; sock= sock->next)
- if(sock->to_index==index)
+ for (sock=gnode->outputs.first; sock; sock=sock->next)
+ if (sock->groupsock == gsock)
return sock;
return NULL;
}
@@ -458,8 +380,9 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
{
bNodeLink *link, *linkn;
bNode *node, *gnode, *nextn;
- bNodeSocket *sock;
bNodeTree *ngroup;
+ bNodeSocket *gsock;
+ ListBase anim_basepaths = {NULL, NULL};
float min[2], max[2];
int totnode=0;
@@ -481,9 +404,9 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
/* check if all connections are OK, no unselected node has both
inputs and outputs to a selection */
for(link= ntree->links.first; link; link= link->next) {
- if(link->fromnode->flag & NODE_SELECT)
+ if(link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT)
link->tonode->done |= 1;
- if(link->tonode->flag & NODE_SELECT)
+ if(link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT)
link->fromnode->done |= 2;
}
@@ -496,41 +419,50 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
return NULL;
/* OK! new nodetree */
- ngroup= alloc_libblock(&G.main->nodetree, ID_NT, "NodeGroup");
- ngroup->type= ntree->type;
- ngroup->alltypes= ntree->alltypes;
+ ngroup= ntreeAddTree("NodeGroup", ntree->type, TRUE);
/* move nodes over */
for(node= ntree->nodes.first; node; node= nextn) {
nextn= node->next;
if(node->flag & NODE_SELECT) {
+ /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
+ * if the old nodetree has animation data which potentially covers this node
+ */
+ if (ntree->adt) {
+ PointerRNA ptr;
+ char *path;
+
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
+ path = RNA_path_from_ID_to_struct(&ptr);
+
+ if (path)
+ BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
+ }
+
+ /* change node-collection membership */
BLI_remlink(&ntree->nodes, node);
BLI_addtail(&ngroup->nodes, node);
+
node->locx-= 0.5f*(min[0]+max[0]);
node->locy-= 0.5f*(min[1]+max[1]);
-
- /* set socket own_index to zero since it can still have a value
- * from being in a group before, otherwise it doesn't get a unique
- * index in group_verify_own_indices */
- for(sock= node->inputs.first; sock; sock= sock->next)
- sock->own_index= 0;
- for(sock= node->outputs.first; sock; sock= sock->next)
- sock->own_index= 0;
}
}
- /* move links over */
- for(link= ntree->links.first; link; link= linkn) {
- linkn= link->next;
- if(link->fromnode->flag & link->tonode->flag & NODE_SELECT) {
- BLI_remlink(&ntree->links, link);
- BLI_addtail(&ngroup->links, link);
+ /* move animation data over */
+ if (ntree->adt) {
+ LinkData *ld, *ldn=NULL;
+
+ BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
+
+ /* paths + their wrappers need to be freed */
+ for (ld = anim_basepaths.first; ld; ld = ldn) {
+ ldn = ld->next;
+
+ MEM_freeN(ld->data);
+ BLI_freelinkN(&anim_basepaths, ld);
}
}
- /* now we can make own group typeinfo */
- ntreeMakeOwnType(ngroup);
-
/* make group node */
gnode= nodeAddNodeType(ntree, NODE_GROUP, ngroup, NULL);
gnode->locx= 0.5f*(min[0]+max[0]);
@@ -540,35 +472,29 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
for(link= ntree->links.first; link; link= linkn) {
linkn= link->next;
- if(link->tonode->flag & NODE_SELECT) {
- link->tonode= gnode;
- sock= groupnode_find_tosock(gnode, link->tosock->own_index);
- if(sock==NULL) {
- nodeRemLink(ntree, link);
- printf("Removed link, cannot mix internal and external sockets in group\n");
- }
- else link->tosock= sock;
+ if(link->fromnode && link->tonode && (link->fromnode->flag & link->tonode->flag & NODE_SELECT)) {
+ BLI_remlink(&ntree->links, link);
+ BLI_addtail(&ngroup->links, link);
}
- else if(link->fromnode->flag & NODE_SELECT) {
- link->fromnode= gnode;
- sock= groupnode_find_fromsock(gnode, link->fromsock->own_index);
- if(sock==NULL) {
- nodeRemLink(ntree, link);
- printf("Removed link, cannot mix internal and external sockets in group\n");
- }
- else link->fromsock= sock;
+ else if(link->tonode && (link->tonode->flag & NODE_SELECT)) {
+ gsock = nodeGroupExposeSocket(ngroup, link->tosock, SOCK_IN);
+ link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
+ link->tosock = node_add_group_socket(&gnode->inputs, gsock);
+ link->tonode = gnode;
}
- }
-
- /* initialize variables of unused input sockets */
- for(node= ngroup->nodes.first; node; node= node->next) {
- for(sock= node->inputs.first; sock; sock= sock->next) {
- if(sock->intern==0) {
- bNodeSocket *nsock= groupnode_find_tosock(gnode, sock->own_index);
- if(nsock) {
- QUATCOPY(nsock->ns.vec, sock->ns.vec);
- }
+ else if(link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
+ /* search for existing group node socket */
+ for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next)
+ if (gsock->link && gsock->link->fromsock==link->fromsock)
+ break;
+ if (!gsock) {
+ gsock = nodeGroupExposeSocket(ngroup, link->fromsock, SOCK_OUT);
+ gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
+ link->fromsock = node_add_group_socket(&gnode->outputs, gsock);
}
+ else
+ link->fromsock = find_group_node_output(gnode, gsock);
+ link->fromnode = gnode;
}
}
@@ -578,35 +504,21 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
return gnode;
}
-/* note: ungroup: group_indices zero! */
-
/* here's a nasty little one, need to check users... */
/* should become callbackable... */
-void nodeVerifyGroup(bNodeTree *ngroup)
+void nodeGroupVerify(bNodeTree *ngroup)
{
-
/* group changed, so we rebuild the type definition */
- ntreeMakeOwnType(ngroup);
+// ntreeMakeGroupSockets(ngroup);
if(ngroup->type==NTREE_SHADER) {
Material *ma;
for(ma= G.main->mat.first; ma; ma= ma->id.next) {
if(ma->nodetree) {
bNode *node;
-
- /* find if group is in tree */
for(node= ma->nodetree->nodes.first; node; node= node->next)
if(node->id == (ID *)ngroup)
- break;
-
- if(node) {
- /* set all type pointers OK */
- ntreeInitTypes(ma->nodetree);
-
- for(node= ma->nodetree->nodes.first; node; node= node->next)
- if(node->id == (ID *)ngroup)
- nodeVerifyType(ma->nodetree, node);
- }
+ nodeVerifyType(ma->nodetree, node);
}
}
}
@@ -615,20 +527,9 @@ void nodeVerifyGroup(bNodeTree *ngroup)
for(sce= G.main->scene.first; sce; sce= sce->id.next) {
if(sce->nodetree) {
bNode *node;
-
- /* find if group is in tree */
for(node= sce->nodetree->nodes.first; node; node= node->next)
if(node->id == (ID *)ngroup)
- break;
-
- if(node) {
- /* set all type pointers OK */
- ntreeInitTypes(sce->nodetree);
-
- for(node= sce->nodetree->nodes.first; node; node= node->next)
- if(node->id == (ID *)ngroup)
- nodeVerifyType(sce->nodetree, node);
- }
+ nodeVerifyType(sce->nodetree, node);
}
}
}
@@ -637,20 +538,9 @@ void nodeVerifyGroup(bNodeTree *ngroup)
for(tx= G.main->tex.first; tx; tx= tx->id.next) {
if(tx->nodetree) {
bNode *node;
-
- /* find if group is in tree */
for(node= tx->nodetree->nodes.first; node; node= node->next)
if(node->id == (ID *)ngroup)
- break;
-
- if(node) {
- /* set all type pointers OK */
- ntreeInitTypes(tx->nodetree);
-
- for(node= tx->nodetree->nodes.first; node; node= node->next)
- if(node->id == (ID *)ngroup)
- nodeVerifyType(tx->nodetree, node);
- }
+ nodeVerifyType(tx->nodetree, node);
}
}
}
@@ -677,15 +567,15 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup)
for(ma= G.main->mat.first; ma; ma= ma->id.next) {
if(ma->nodetree) {
for(node= ma->nodetree->nodes.first; node; node= node->next) {
- if(node->id==(ID *)ngroup) {
+ if(node->id==&ngroup->id) {
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->link)
- if(sock->tosock)
- sock->tosock->flag |= SOCK_IN_USE;
+ if(sock->groupsock)
+ sock->groupsock->flag |= SOCK_IN_USE;
for(sock= node->outputs.first; sock; sock= sock->next)
if(nodeCountSocketLinks(ma->nodetree, sock))
- if(sock->tosock)
- sock->tosock->flag |= SOCK_IN_USE;
+ if(sock->groupsock)
+ sock->groupsock->flag |= SOCK_IN_USE;
}
}
}
@@ -699,12 +589,12 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup)
if(node->id==(ID *)ngroup) {
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->link)
- if(sock->tosock)
- sock->tosock->flag |= SOCK_IN_USE;
+ if(sock->groupsock)
+ sock->groupsock->flag |= SOCK_IN_USE;
for(sock= node->outputs.first; sock; sock= sock->next)
if(nodeCountSocketLinks(sce->nodetree, sock))
- if(sock->tosock)
- sock->tosock->flag |= SOCK_IN_USE;
+ if(sock->groupsock)
+ sock->groupsock->flag |= SOCK_IN_USE;
}
}
}
@@ -718,12 +608,12 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup)
if(node->id==(ID *)ngroup) {
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->link)
- if(sock->tosock)
- sock->tosock->flag |= SOCK_IN_USE;
+ if(sock->groupsock)
+ sock->groupsock->flag |= SOCK_IN_USE;
for(sock= node->outputs.first; sock; sock= sock->next)
if(nodeCountSocketLinks(tx->nodetree, sock))
- if(sock->tosock)
- sock->tosock->flag |= SOCK_IN_USE;
+ if(sock->groupsock)
+ sock->groupsock->flag |= SOCK_IN_USE;
}
}
}
@@ -738,21 +628,27 @@ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
}
/* finds a node based on given socket */
-int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
+int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex, int *in_out)
{
bNode *node;
bNodeSocket *tsock;
int index= 0;
for(node= ntree->nodes.first; node; node= node->next) {
- for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++)
- if(tsock==sock)
+ for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++) {
+ if(tsock==sock) {
+ if (in_out) *in_out= SOCK_IN;
break;
+ }
+ }
if(tsock)
break;
- for(index=0, tsock= node->outputs.first; tsock; tsock= tsock->next, index++)
- if(tsock==sock)
+ for(index=0, tsock= node->outputs.first; tsock; tsock= tsock->next, index++) {
+ if(tsock==sock) {
+ if (in_out) *in_out= SOCK_OUT;
break;
+ }
+ }
if(tsock)
break;
}
@@ -773,7 +669,7 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
bNodeLink *link, *linkn;
bNode *node, *nextn;
bNodeTree *ngroup, *wgroup;
- int index;
+ ListBase anim_basepaths = {NULL, NULL};
ngroup= (bNodeTree *)gnode->id;
if(ngroup==NULL) return 0;
@@ -781,98 +677,261 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
/* clear new pointers, set in copytree */
for(node= ntree->nodes.first; node; node= node->next)
node->new_node= NULL;
-
- wgroup= ntreeCopyTree(ngroup, 0);
+
+ /* wgroup is a temporary copy of the NodeTree we're merging in
+ * - all of wgroup's nodes are transferred across to their new home
+ * - ngroup (i.e. the source NodeTree) is left unscathed
+ */
+ wgroup= ntreeCopyTree(ngroup);
/* add the nodes into the ntree */
for(node= wgroup->nodes.first; node; node= nextn) {
nextn= node->next;
+
+ /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
+ * if the old nodetree has animation data which potentially covers this node
+ */
+ if (wgroup->adt) {
+ PointerRNA ptr;
+ char *path;
+
+ RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
+ path = RNA_path_from_ID_to_struct(&ptr);
+
+ if (path)
+ BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
+ }
+
+ /* migrate node */
BLI_remlink(&wgroup->nodes, node);
BLI_addtail(&ntree->nodes, node);
+
node->locx+= gnode->locx;
node->locy+= gnode->locy;
+
node->flag |= NODE_SELECT;
}
- /* and the internal links */
- for(link= wgroup->links.first; link; link= linkn) {
- linkn= link->next;
- BLI_remlink(&wgroup->links, link);
- BLI_addtail(&ntree->links, link);
- }
-
- /* restore links to and from the gnode */
+
+ /* restore external links to and from the gnode */
for(link= ntree->links.first; link; link= link->next) {
- if(link->tonode==gnode) {
- /* link->tosock->tosock is on the node we look for */
- nodeFindNode(ngroup, link->tosock->tosock, &nextn, &index);
- if(nextn==NULL) printf("wrong stuff!\n");
- else if(nextn->new_node==NULL) printf("wrong stuff too!\n");
- else {
- link->tonode= nextn->new_node;
- link->tosock= BLI_findlink(&link->tonode->inputs, index);
+ if (link->fromnode==gnode) {
+ if (link->fromsock->groupsock) {
+ bNodeSocket *gsock= link->fromsock->groupsock;
+ if (gsock->link) {
+ if (gsock->link->fromnode) {
+ /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
+ link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
+ link->fromsock = gsock->link->fromsock->new_sock;
+ }
+ else {
+ /* group output directly maps to group input */
+ bNodeSocket *insock= find_group_node_input(gnode, gsock->link->fromsock);
+ if (insock->link) {
+ link->fromnode = insock->link->fromnode;
+ link->fromsock = insock->link->fromsock;
+ }
+ }
+ }
+ else {
+ /* constant group output: copy the stack value to the external socket.
+ * the link is kept here until all possible external users have been fixed.
+ */
+ QUATCOPY(link->tosock->ns.vec, gsock->ns.vec);
+ }
}
}
- else if(link->fromnode==gnode) {
- /* link->fromsock->tosock is on the node we look for */
- nodeFindNode(ngroup, link->fromsock->tosock, &nextn, &index);
- if(nextn==NULL) printf("1 wrong stuff!\n");
- else if(nextn->new_node==NULL) printf("1 wrong stuff too!\n");
+ }
+ /* remove internal output links, these are not used anymore */
+ for(link=wgroup->links.first; link; link= linkn) {
+ linkn = link->next;
+ if (!link->tonode)
+ nodeRemLink(wgroup, link);
+ }
+ /* restore links from internal nodes */
+ for(link= wgroup->links.first; link; link= link->next) {
+ /* indicates link to group input */
+ if (!link->fromnode) {
+ /* NB: can't use find_group_node_input here,
+ * because gnode sockets still point to the old tree!
+ */
+ bNodeSocket *insock;
+ for (insock= gnode->inputs.first; insock; insock= insock->next)
+ if (insock->groupsock->new_sock == link->fromsock)
+ break;
+ if (insock->link) {
+ link->fromnode = insock->link->fromnode;
+ link->fromsock = insock->link->fromsock;
+ }
else {
- link->fromnode= nextn->new_node;
- link->fromsock= BLI_findlink(&link->fromnode->outputs, index);
+ /* uses group constant input. copy the input value and remove the dead link. */
+ QUATCOPY(link->tosock->ns.vec, insock->ns.vec);
+ nodeRemLink(wgroup, link);
}
}
}
- /* remove the gnode & work tree */
- free_libblock(&G.main->nodetree, wgroup);
+ /* add internal links to the ntree */
+ for(link= wgroup->links.first; link; link= linkn) {
+ linkn= link->next;
+ BLI_remlink(&wgroup->links, link);
+ BLI_addtail(&ntree->links, link);
+ }
+
+ /* and copy across the animation */
+ if (wgroup->adt) {
+ LinkData *ld, *ldn=NULL;
+ bAction *waction;
+
+ /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
+ waction = wgroup->adt->action = copy_action(wgroup->adt->action);
+
+ /* now perform the moving */
+ BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
+
+ /* paths + their wrappers need to be freed */
+ for (ld = anim_basepaths.first; ld; ld = ldn) {
+ ldn = ld->next;
+
+ MEM_freeN(ld->data);
+ BLI_freelinkN(&anim_basepaths, ld);
+ }
+
+ /* free temp action too */
+ free_libblock(&G.main->action, waction);
+ }
+ /* delete the group instance. this also removes old input links! */
nodeFreeNode(ntree, gnode);
+ /* free the group tree (takes care of user count) */
+ free_libblock(&G.main->nodetree, wgroup);
+
/* solve order goes fine, but the level tags not... doing it twice works for now. solve this once */
+ /* XXX is this still necessary with new groups? it may have been caused by non-updated sock->link pointers. lukas */
ntreeSolveOrder(ntree);
ntreeSolveOrder(ntree);
return 1;
}
-void nodeCopyGroup(bNode *gnode)
+void nodeGroupCopy(bNode *gnode)
{
bNodeSocket *sock;
gnode->id->us--;
- gnode->id= (ID *)ntreeCopyTree((bNodeTree *)gnode->id, 0);
+ gnode->id= (ID *)ntreeCopyTree((bNodeTree *)gnode->id);
/* new_sock was set in nodeCopyNode */
for(sock=gnode->inputs.first; sock; sock=sock->next)
- if(sock->tosock)
- sock->tosock= sock->tosock->new_sock;
+ if(sock->groupsock)
+ sock->groupsock= sock->groupsock->new_sock;
for(sock=gnode->outputs.first; sock; sock=sock->next)
- if(sock->tosock)
- sock->tosock= sock->tosock->new_sock;
+ if(sock->groupsock)
+ sock->groupsock= sock->groupsock->new_sock;
+}
+
+bNodeSocket *nodeGroupAddSocket(bNodeTree *ngroup, const char *name, int type, int in_out)
+{
+ bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket");
+
+ strncpy(gsock->name, name, sizeof(gsock->name));
+ gsock->type = type;
+ gsock->ns.sockettype = type;
+ gsock->ns.min = INT_MIN;
+ gsock->ns.max = INT_MAX;
+ zero_v4(gsock->ns.vec);
+ gsock->ns.data = NULL;
+ gsock->flag = 0;
+
+ gsock->next = gsock->prev = NULL;
+ gsock->new_sock = NULL;
+ gsock->link = NULL;
+ gsock->ns.data = NULL;
+ /* assign new unique index */
+ gsock->own_index = ngroup->cur_index++;
+ gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1);
+
+ BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
+
+ return gsock;
+}
+
+bNodeSocket *nodeGroupExposeSocket(bNodeTree *ngroup, bNodeSocket *sock, int in_out)
+{
+ bNodeSocket *gsock= nodeGroupAddSocket(ngroup, sock->name, sock->type, in_out);
+ /* initialize the default socket value */
+ QUATCOPY(gsock->ns.vec, sock->ns.vec);
+ return gsock;
+}
+
+void nodeGroupExposeAllSockets(bNodeTree *ngroup)
+{
+ bNode *node;
+ bNodeSocket *sock, *gsock;
+
+ for (node=ngroup->nodes.first; node; node=node->next) {
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ if (!sock->link && !(sock->flag & SOCK_HIDDEN)) {
+ gsock = nodeGroupAddSocket(ngroup, sock->name, sock->type, SOCK_IN);
+ /* initialize the default socket value */
+ QUATCOPY(gsock->ns.vec, sock->ns.vec);
+ sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock);
+ }
+ }
+ for (sock=node->outputs.first; sock; sock=sock->next) {
+ if (nodeCountSocketLinks(ngroup, sock)==0 && !(sock->flag & SOCK_HIDDEN)) {
+ gsock = nodeGroupAddSocket(ngroup, sock->name, sock->type, SOCK_OUT);
+ /* initialize the default socket value */
+ QUATCOPY(gsock->ns.vec, sock->ns.vec);
+ gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock);
+ }
+ }
+ }
+}
+
+void nodeGroupRemoveSocket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out)
+{
+ nodeRemSocketLinks(ngroup, gsock);
+ switch (in_out) {
+ case SOCK_IN: BLI_remlink(&ngroup->inputs, gsock); break;
+ case SOCK_OUT: BLI_remlink(&ngroup->outputs, gsock); break;
+ }
}
/* ************** Add stuff ********** */
void nodeAddSockets(bNode *node, bNodeType *ntype)
{
- bNodeSocketType *stype;
-
- if(ntype->inputs) {
- stype= ntype->inputs;
- while(stype->type != -1) {
- node_add_socket_type(&node->inputs, stype);
- stype++;
+ if (node->type==NODE_GROUP) {
+ bNodeTree *ntree= (bNodeTree*)node->id;
+ if (ntree) {
+ bNodeSocket *gsock;
+ for (gsock=ntree->inputs.first; gsock; gsock=gsock->next)
+ node_add_group_socket(&node->inputs, gsock);
+ for (gsock=ntree->outputs.first; gsock; gsock=gsock->next)
+ node_add_group_socket(&node->outputs, gsock);
}
}
- if(ntype->outputs) {
- stype= ntype->outputs;
- while(stype->type != -1) {
- node_add_socket_type(&node->outputs, stype);
- stype++;
+ else {
+ bNodeSocketType *stype;
+
+ if(ntype->inputs) {
+ stype= ntype->inputs;
+ while(stype->type != -1) {
+ node_add_socket_type(&node->inputs, stype);
+ stype++;
+ }
+ }
+ if(ntype->outputs) {
+ stype= ntype->outputs;
+ while(stype->type != -1) {
+ node_add_socket_type(&node->outputs, stype);
+ stype++;
+ }
}
}
}
+
/* Find the first available, non-duplicate name for a given node */
void nodeUniqueName(bNodeTree *ntree, bNode *node)
{
@@ -884,6 +943,11 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
bNode *node= NULL;
bNodeType *ntype= NULL;
+ if (ngroup && BLI_findindex(&G.main->nodetree, ngroup)==-1) {
+ printf("nodeAddNodeType() error: '%s' not in main->nodetree\n", ngroup->id.name);
+ return NULL;
+ }
+
if(type>=NODE_DYNAMIC_MENU) {
int a=0, idx= type-NODE_DYNAMIC_MENU;
ntype= ntree->alltypes.first;
@@ -896,7 +960,7 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
ntype= ntype->next;
}
} else
- ntype= node_get_type(ntree, type, ngroup, id);
+ ntype= node_get_type(ntree, type, id);
node= MEM_callocN(sizeof(bNode), "new node");
BLI_addtail(&ntree->nodes, node);
@@ -960,7 +1024,7 @@ void nodeUpdateType(bNodeTree *ntree, bNode* node, bNodeType *ntype)
/* keep socket listorder identical, for copying links */
/* ntree is the target tree */
-bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal)
+bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
{
bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node");
bNodeSocket *sock, *oldsock;
@@ -974,15 +1038,11 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal)
oldsock= node->inputs.first;
for(sock= nnode->inputs.first; sock; sock= sock->next, oldsock= oldsock->next) {
oldsock->new_sock= sock;
- if(internal)
- sock->own_index= 0;
}
BLI_duplicatelist(&nnode->outputs, &node->outputs);
oldsock= node->outputs.first;
for(sock= nnode->outputs.first; sock; sock= sock->next, oldsock= oldsock->next) {
- if(internal)
- sock->own_index= 0;
sock->stack_index= 0;
sock->ns.data= NULL;
oldsock->new_sock= sock;
@@ -1000,15 +1060,61 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal)
return nnode;
}
+/* fromsock and tosock can be NULL */
+/* also used via rna api, so we check for proper input output direction */
bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
{
- bNodeLink *link= MEM_callocN(sizeof(bNodeLink), "link");
+ bNodeSocket *sock;
+ bNodeLink *link= NULL;
+ int from= 0, to= 0;
- BLI_addtail(&ntree->links, link);
- link->fromnode= fromnode;
- link->fromsock= fromsock;
- link->tonode= tonode;
- link->tosock= tosock;
+ if(fromnode) {
+ /* test valid input */
+ for(sock= fromnode->outputs.first; sock; sock= sock->next)
+ if(sock==fromsock)
+ break;
+ if(sock)
+ from= 1; /* OK */
+ else {
+ for(sock= fromnode->inputs.first; sock; sock= sock->next)
+ if(sock==fromsock)
+ break;
+ if(sock)
+ from= -1; /* OK but flip */
+ }
+ }
+ if(tonode) {
+ for(sock= tonode->inputs.first; sock; sock= sock->next)
+ if(sock==tosock)
+ break;
+ if(sock)
+ to= 1; /* OK */
+ else {
+ for(sock= tonode->outputs.first; sock; sock= sock->next)
+ if(sock==tosock)
+ break;
+ if(sock)
+ to= -1; /* OK but flip */
+ }
+ }
+
+ /* this allows NULL sockets to work */
+ if(from >= 0 && to >= 0) {
+ link= MEM_callocN(sizeof(bNodeLink), "link");
+ BLI_addtail(&ntree->links, link);
+ link->fromnode= fromnode;
+ link->fromsock= fromsock;
+ link->tonode= tonode;
+ link->tosock= tosock;
+ }
+ else if(from <= 0 && to <= 0) {
+ link= MEM_callocN(sizeof(bNodeLink), "link");
+ BLI_addtail(&ntree->links, link);
+ link->fromnode= tonode;
+ link->fromsock= tosock;
+ link->tonode= fromnode;
+ link->tosock= fromsock;
+ }
return link;
}
@@ -1034,104 +1140,83 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
}
-bNodeTree *ntreeAddTree(int type)
+bNodeTree *ntreeAddTree(const char *name, int type, const short is_group)
{
- bNodeTree *ntree= MEM_callocN(sizeof(bNodeTree), "new node tree");
+ bNodeTree *ntree;
+
+ if (is_group)
+ ntree= alloc_libblock(&G.main->nodetree, ID_NT, name);
+ else {
+ ntree= MEM_callocN(sizeof(bNodeTree), "new node tree");
+ *( (short *)ntree->id.name )= ID_NT; /* not "type", as that is ntree->type */
+ BLI_strncpy(ntree->id.name+2, name, sizeof(ntree->id.name));
+ }
+
ntree->type= type;
ntree->alltypes.first = NULL;
ntree->alltypes.last = NULL;
- /* this helps RNA identify ID pointers as nodetree */
- if(ntree->type==NTREE_SHADER)
- BLI_strncpy(ntree->id.name, "NTShader Nodetree", sizeof(ntree->id.name));
- else if(ntree->type==NTREE_COMPOSIT)
- BLI_strncpy(ntree->id.name, "NTCompositing Nodetree", sizeof(ntree->id.name));
- else if(ntree->type==NTREE_TEXTURE)
- BLI_strncpy(ntree->id.name, "NTTexture Nodetree", sizeof(ntree->id.name));
-
ntreeInitTypes(ntree);
return ntree;
}
/* Warning: this function gets called during some rather unexpected times
- * - internal_select is only 1 when used for duplicating selected nodes (i.e. Shift-D duplicate operator)
* - this gets called when executing compositing updates (for threaded previews)
* - when the nodetree datablock needs to be copied (i.e. when users get copied)
* - for scene duplication use ntreeSwapID() after so we dont have stale pointers.
*/
-bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
+bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
bNodeTree *newtree;
bNode *node, *nnode, *last;
- bNodeLink *link, *nlink;
- bNodeSocket *sock;
- int a;
+ bNodeLink *link;
+ bNodeSocket *gsock, *oldgsock;
if(ntree==NULL) return NULL;
- if(internal_select==0) {
- /* is ntree part of library? */
- for(newtree=G.main->nodetree.first; newtree; newtree= newtree->id.next)
- if(newtree==ntree) break;
- if(newtree) {
- newtree= copy_libblock(ntree);
- } else {
- newtree= MEM_dupallocN(ntree);
- copy_libblock_data(&newtree->id, &ntree->id); /* copy animdata and ID props */
- }
- newtree->nodes.first= newtree->nodes.last= NULL;
- newtree->links.first= newtree->links.last= NULL;
+ /* is ntree part of library? */
+ for(newtree=G.main->nodetree.first; newtree; newtree= newtree->id.next)
+ if(newtree==ntree) break;
+ if(newtree) {
+ newtree= copy_libblock(ntree);
+ } else {
+ newtree= MEM_dupallocN(ntree);
+ copy_libblock_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */
}
- else
- newtree= ntree;
+ newtree->nodes.first= newtree->nodes.last= NULL;
+ newtree->links.first= newtree->links.last= NULL;
- last= ntree->nodes.last;
+ last = ntree->nodes.last;
for(node= ntree->nodes.first; node; node= node->next) {
-
node->new_node= NULL;
- if(internal_select==0 || (node->flag & NODE_SELECT)) {
- nnode= nodeCopyNode(newtree, node, internal_select); /* sets node->new */
- if(internal_select) {
- node->flag &= ~(NODE_SELECT|NODE_ACTIVE);
- nnode->flag |= NODE_SELECT;
- }
- }
+ nnode= nodeCopyNode(newtree, node); /* sets node->new */
if(node==last) break;
}
- /* check for copying links */
- for(link= ntree->links.first; link; link= link->next) {
- if(link->fromnode==NULL || link->tonode==NULL);
- else if(link->fromnode->new_node && link->tonode->new_node) {
- nlink= nodeAddLink(newtree, link->fromnode->new_node, NULL, link->tonode->new_node, NULL);
- /* sockets were copied in order */
- for(a=0, sock= link->fromnode->outputs.first; sock; sock= sock->next, a++) {
- if(sock==link->fromsock)
- break;
- }
- nlink->fromsock= BLI_findlink(&link->fromnode->new_node->outputs, a);
-
- for(a=0, sock= link->tonode->inputs.first; sock; sock= sock->next, a++) {
- if(sock==link->tosock)
- break;
- }
- nlink->tosock= BLI_findlink(&link->tonode->new_node->inputs, a);
- }
+ /* socket definition for group usage */
+ BLI_duplicatelist(&newtree->inputs, &ntree->inputs);
+ for(gsock= newtree->inputs.first, oldgsock= ntree->inputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) {
+ oldgsock->new_sock= gsock;
+ gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL);
}
- /* own type definition for group usage */
- if(internal_select==0) {
- if(ntree->owntype) {
- newtree->owntype= MEM_dupallocN(ntree->owntype);
- if(ntree->owntype->inputs)
- newtree->owntype->inputs= MEM_dupallocN(ntree->owntype->inputs);
- if(ntree->owntype->outputs)
- newtree->owntype->outputs= MEM_dupallocN(ntree->owntype->outputs);
- }
+ BLI_duplicatelist(&newtree->outputs, &ntree->outputs);
+ for(gsock= newtree->outputs.first, oldgsock= ntree->outputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) {
+ oldgsock->new_sock= gsock;
+ gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL);
+ }
+
+ /* copy links */
+ BLI_duplicatelist(&newtree->links, &ntree->links);
+ for(link= newtree->links.first; link; link= link->next) {
+ link->fromnode = (link->fromnode ? link->fromnode->new_node : NULL);
+ link->fromsock = (link->fromsock ? link->fromsock->new_sock : NULL);
+ link->tonode = (link->tonode ? link->tonode->new_node : NULL);
+ link->tosock = (link->tosock ? link->tosock->new_sock : NULL);
+ /* update the link socket's pointer */
+ if (link->tosock)
+ link->tosock->link = link;
}
- /* weird this is required... there seem to be link pointers wrong still? */
- /* anyhoo, doing this solves crashes on copying entire tree (copy scene) and delete nodes */
- ntreeSolveOrder(newtree);
return newtree;
}
@@ -1182,12 +1267,11 @@ static void node_init_preview(bNode *node, int xsize, int ysize)
}
if(node->preview->rect==NULL) {
- node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect");
+ node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(char)*4, "node preview rect");
node->preview->xsize= xsize;
node->preview->ysize= ysize;
}
- else
- memset(node->preview->rect, 0, 4*xsize + xsize*ysize*sizeof(float)*4);
+ /* no clear, makes nicer previews */
}
void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)
@@ -1237,12 +1321,18 @@ void nodeAddToPreview(bNode *node, float *col, int x, int y)
if(x>=0 && y>=0) {
if(x<preview->xsize && y<preview->ysize) {
unsigned char *tar= preview->rect+ 4*((preview->xsize*y) + x);
- //if(tar[0]==0.0f) {
- tar[0]= FTOCHAR(col[0]);
- tar[1]= FTOCHAR(col[1]);
- tar[2]= FTOCHAR(col[2]);
+
+ if(TRUE) {
+ tar[0]= FTOCHAR(linearrgb_to_srgb(col[0]));
+ tar[1]= FTOCHAR(linearrgb_to_srgb(col[1]));
+ tar[2]= FTOCHAR(linearrgb_to_srgb(col[2]));
+ }
+ else {
+ tar[0]= FTOCHAR(col[0]);
+ tar[1]= FTOCHAR(col[1]);
+ tar[2]= FTOCHAR(col[2]);
+ }
tar[3]= FTOCHAR(col[3]);
- //}
}
//else printf("prv out bound x y %d %d\n", x, y);
}
@@ -1265,7 +1355,8 @@ void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
if(link->fromnode==node) {
lb= &node->outputs;
- NodeTagChanged(ntree, link->tonode);
+ if (link->tonode)
+ NodeTagChanged(ntree, link->tonode);
}
else if(link->tonode==node)
lb= &node->inputs;
@@ -1335,13 +1426,8 @@ void ntreeFreeTree(bNodeTree *ntree)
nodeFreeNode(ntree, node);
}
- if(ntree->owntype) {
- if(ntree->owntype->inputs)
- MEM_freeN(ntree->owntype->inputs);
- if(ntree->owntype->outputs)
- MEM_freeN(ntree->owntype->outputs);
- MEM_freeN(ntree->owntype);
- }
+ BLI_freelistN(&ntree->inputs);
+ BLI_freelistN(&ntree->outputs);
}
void ntreeFreeCache(bNodeTree *ntree)
@@ -1367,9 +1453,9 @@ void ntreeMakeLocal(bNodeTree *ntree)
if(ntree->id.lib==NULL) return;
if(ntree->id.us==1) {
- ntree->id.lib= 0;
+ ntree->id.lib= NULL;
ntree->id.flag= LIB_LOCAL;
- new_id(0, (ID *)ntree, 0);
+ new_id(NULL, (ID *)ntree, NULL);
return;
}
@@ -1427,11 +1513,11 @@ void ntreeMakeLocal(bNodeTree *ntree)
if(local && lib==0) {
ntree->id.lib= NULL;
ntree->id.flag= LIB_LOCAL;
- new_id(0, (ID *)ntree, 0);
+ new_id(NULL, (ID *)ntree, NULL);
}
else if(local && lib) {
/* this is the mixed case, we copy the tree and assign it to local users */
- bNodeTree *newtree= ntreeCopyTree(ntree, 0);
+ bNodeTree *newtree= ntreeCopyTree(ntree);
newtree->id.us= 0;
@@ -1675,7 +1761,7 @@ static int node_recurs_check(bNode *node, bNode ***nsort, int level)
if(sock->link) {
has_inputlinks= 1;
fromnode= sock->link->fromnode;
- if(fromnode->done==0) {
+ if(fromnode && fromnode->done==0) {
fromnode->level= node_recurs_check(fromnode, nsort, level);
}
}
@@ -1690,6 +1776,59 @@ static int node_recurs_check(bNode *node, bNode ***nsort, int level)
return 0xFFF;
}
+
+static void ntreeSetOutput(bNodeTree *ntree)
+{
+ bNode *node;
+
+ /* find the active outputs, might become tree type dependant handler */
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+ bNode *tnode;
+ int output= 0;
+
+ /* we need a check for which output node should be tagged like this, below an exception */
+ if(node->type==CMP_NODE_OUTPUT_FILE)
+ continue;
+
+ /* there is more types having output class, each one is checked */
+ for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
+ if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+
+ if(ntree->type==NTREE_COMPOSIT) {
+
+ /* same type, exception for viewer */
+ if(tnode->type==node->type ||
+ (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) &&
+ ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) {
+ if(tnode->flag & NODE_DO_OUTPUT) {
+ output++;
+ if(output>1)
+ tnode->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+ }
+ else {
+ /* same type */
+ if(tnode->type==node->type) {
+ if(tnode->flag & NODE_DO_OUTPUT) {
+ output++;
+ if(output>1)
+ tnode->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+ }
+ }
+ }
+ if(output==0)
+ node->flag |= NODE_DO_OUTPUT;
+ }
+ }
+
+ /* here we could recursively set which nodes have to be done,
+ might be different for editor or for "real" use... */
+}
+
void ntreeSolveOrder(bNodeTree *ntree)
{
bNode *node, **nodesort, **nsort;
@@ -1708,6 +1847,9 @@ void ntreeSolveOrder(bNodeTree *ntree)
for(sock= node->inputs.first; sock; sock= sock->next)
sock->link= NULL;
}
+ /* clear group socket links */
+ for(sock= ntree->outputs.first; sock; sock= sock->next)
+ sock->link= NULL;
if(totnode==0)
return;
@@ -1738,38 +1880,11 @@ void ntreeSolveOrder(bNodeTree *ntree)
}
MEM_freeN(nodesort);
-
- /* find the active outputs, might become tree type dependant handler */
- for(node= ntree->nodes.first; node; node= node->next) {
- if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
- bNode *tnode;
- int output= 0;
-
- /* we need a check for which output node should be tagged like this, below an exception */
- if(node->type==CMP_NODE_OUTPUT_FILE)
- continue;
-
- /* there is more types having output class, each one is checked */
- for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
- if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) {
- if(tnode->type==node->type) {
- if(tnode->flag & NODE_DO_OUTPUT) {
- output++;
- if(output>1)
- tnode->flag &= ~NODE_DO_OUTPUT;
- }
- }
- }
- }
- if(output==0)
- node->flag |= NODE_DO_OUTPUT;
- }
- }
-
- /* here we could recursively set which nodes have to be done,
- might be different for editor or for "real" use... */
+
+ ntreeSetOutput(ntree);
}
+
/* Should be callback! */
/* Do not call execs here */
void NodeTagChanged(bNodeTree *ntree, bNode *node)
@@ -1787,51 +1902,65 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node)
}
}
-void NodeTagIDChanged(bNodeTree *ntree, ID *id)
+int NodeTagIDChanged(bNodeTree *ntree, ID *id)
{
- if(id==NULL)
- return;
+ int change = FALSE;
+
+ if(ELEM(NULL, id, ntree))
+ return change;
if(ntree->type==NTREE_COMPOSIT) {
bNode *node;
- for(node= ntree->nodes.first; node; node= node->next)
- if(node->id==id)
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->id==id) {
+ change= TRUE;
NodeTagChanged(ntree, node);
+ }
+ }
}
+
+ return change;
}
/* ******************* executing ************* */
+/* for a given socket, find the actual stack entry */
+static bNodeStack *get_socket_stack(bNodeStack *stack, bNodeSocket *sock, bNodeStack **gin)
+{
+ switch (sock->stack_type) {
+ case SOCK_STACK_LOCAL:
+ return stack + sock->stack_index;
+ case SOCK_STACK_EXTERN:
+ return (gin ? gin[sock->stack_index] : NULL);
+ case SOCK_STACK_CONST:
+ return sock->stack_ptr;
+ }
+ return NULL;
+}
+
/* see notes at ntreeBeginExecTree */
-static void group_node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out, bNodeStack **gin, bNodeStack **gout)
+static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out, bNodeStack **gin)
{
bNodeSocket *sock;
/* build pointer stack */
- for(sock= node->inputs.first; sock; sock= sock->next) {
- if(sock->intern) {
- /* yep, intern can have link or is hidden socket */
- if(sock->link)
- *(in++)= stack + sock->link->fromsock->stack_index;
- else
- *(in++)= &sock->ns;
+ if (in) {
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ *(in++) = get_socket_stack(stack, sock, gin);
}
- else
- *(in++)= gin[sock->stack_index_ext];
}
- for(sock= node->outputs.first; sock; sock= sock->next) {
- if(sock->intern)
- *(out++)= stack + sock->stack_index;
- else
- *(out++)= gout[sock->stack_index_ext];
+ if (out) {
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ *(out++) = get_socket_stack(stack, sock, gin);
+ }
}
}
-static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNodeStack **in, bNodeStack **out)
+static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNodeStack **in)
{
bNode *node;
bNodeTree *ntree= (bNodeTree *)gnode->id;
@@ -1844,7 +1973,7 @@ static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNod
for(node= ntree->nodes.first; node; node= node->next) {
if(node->typeinfo->execfunc) {
- group_node_get_stack(node, stack, nsin, nsout, in, out);
+ node_get_stack(node, stack, nsin, nsout, in);
/* for groups, only execute outputs for edited group */
if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
@@ -1856,19 +1985,27 @@ static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNod
}
}
- /* free internal group output nodes */
- if(ntree->type==NTREE_COMPOSIT) {
- for(node= ntree->nodes.first; node; node= node->next) {
- if(node->typeinfo->execfunc) {
- bNodeSocket *sock;
-
- for(sock= node->outputs.first; sock; sock= sock->next) {
- if(sock->intern) {
- bNodeStack *ns= stack + sock->stack_index;
- if(ns->data) {
- free_compbuf(ns->data);
- ns->data= NULL;
- }
+ /* free internal buffers */
+ if (ntree->type==NTREE_COMPOSIT) {
+ bNodeSocket *sock;
+ bNodeStack *ns;
+ for (sock=ntree->outputs.first; sock; sock=sock->next) {
+ /* use the hasoutput flag to tag external sockets */
+ if (sock->stack_type==SOCK_STACK_LOCAL) {
+ ns= get_socket_stack(stack, sock, in);
+ ns->hasoutput = 0;
+ }
+ }
+ /* now free all stacks that are not used from outside */
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock=node->outputs.first; sock; sock=sock->next) {
+ if (sock->stack_type==SOCK_STACK_LOCAL ) {
+ ns= get_socket_stack(stack, sock, in);
+ if (ns->hasoutput!=0 && ns->data) {
+ free_compbuf(ns->data);
+ ns->data = NULL;
+ /* reset the flag */
+ ns->hasoutput = 1;
}
}
}
@@ -1876,37 +2013,134 @@ static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNod
}
}
+static int set_stack_indexes_default(bNode *node, int index)
+{
+ bNodeSocket *sock;
+
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ if (sock->link && sock->link->fromsock) {
+ sock->stack_type = sock->link->fromsock->stack_type;
+ sock->stack_index = sock->link->fromsock->stack_index;
+ sock->stack_ptr = sock->link->fromsock->stack_ptr;
+ }
+ else {
+ sock->stack_type = SOCK_STACK_CONST;
+ sock->stack_index = -1;
+ sock->stack_ptr = &sock->ns;
+ }
+ }
+
+ for (sock=node->outputs.first; sock; sock=sock->next) {
+ sock->stack_type = SOCK_STACK_LOCAL;
+ sock->stack_index = index++;
+ sock->stack_ptr = NULL;
+ }
+
+ return index;
+}
+
+static int ntree_begin_exec_tree(bNodeTree *ntree);
+static int set_stack_indexes_group(bNode *node, int index)
+{
+ bNodeTree *ngroup= (bNodeTree*)node->id;
+ bNodeSocket *sock;
+
+ if((ngroup->init & NTREE_TYPE_INIT)==0)
+ ntreeInitTypes(ngroup);
+
+ node->stack_index = index;
+ index += ntree_begin_exec_tree(ngroup);
+
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ if (sock->link && sock->link->fromsock) {
+ sock->stack_type = sock->link->fromsock->stack_type;
+ sock->stack_index = sock->link->fromsock->stack_index;
+ sock->stack_ptr = sock->link->fromsock->stack_ptr;
+ }
+ else {
+ sock->stack_type = SOCK_STACK_CONST;
+ sock->stack_index = -1;
+ sock->stack_ptr = &sock->ns;
+ }
+ }
+
+ /* identify group node outputs from internal group sockets */
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if (sock->groupsock) {
+ bNodeSocket *insock, *gsock = sock->groupsock;
+ switch (gsock->stack_type) {
+ case SOCK_STACK_EXTERN:
+ /* extern stack is resolved for this group node instance */
+ insock= find_group_node_input(node, gsock->link->fromsock);
+ sock->stack_type = insock->stack_type;
+ sock->stack_index = insock->stack_index;
+ sock->stack_ptr = insock->stack_ptr;
+ break;
+ case SOCK_STACK_LOCAL:
+ sock->stack_type = SOCK_STACK_LOCAL;
+ /* local stack index must be offset by group node instance */
+ sock->stack_index = gsock->stack_index + node->stack_index;
+ sock->stack_ptr = NULL;
+ break;
+ case SOCK_STACK_CONST:
+ sock->stack_type = SOCK_STACK_CONST;
+ sock->stack_index = -1;
+ sock->stack_ptr = gsock->stack_ptr;
+ break;
+ }
+ }
+ else {
+ sock->stack_type = SOCK_STACK_LOCAL;
+ sock->stack_index = index++;
+ sock->stack_ptr = NULL;
+ }
+ }
+
+ return index;
+}
+
/* recursively called for groups */
/* we set all trees on own local indices, but put a total counter
in the groups, so each instance of a group has own stack */
static int ntree_begin_exec_tree(bNodeTree *ntree)
{
bNode *node;
- bNodeSocket *sock;
- int index= 0, index_in= 0, index_out= 0;
+ bNodeSocket *gsock;
+ int index= 0, i;
if((ntree->init & NTREE_TYPE_INIT)==0)
ntreeInitTypes(ntree);
+ /* group inputs are numbered 0..totinputs, so external stack can easily be addressed */
+ i = 0;
+ for(gsock=ntree->inputs.first; gsock; gsock = gsock->next) {
+ gsock->stack_type = SOCK_STACK_EXTERN;
+ gsock->stack_index = i++;
+ gsock->stack_ptr = NULL;
+ }
+
/* create indices for stack, check preview */
for(node= ntree->nodes.first; node; node= node->next) {
-
- for(sock= node->inputs.first; sock; sock= sock->next) {
- if(sock->intern==0)
- sock->stack_index_ext= index_in++;
- }
-
- for(sock= node->outputs.first; sock; sock= sock->next) {
- sock->stack_index= index++;
- if(sock->intern==0)
- sock->stack_index_ext= index_out++;
+ /* XXX can this be done by a generic one-for-all function?
+ * otherwise should use node-type callback.
+ */
+ if(node->type==NODE_GROUP)
+ index = set_stack_indexes_group(node, index);
+ else
+ index = set_stack_indexes_default(node, index);
+ }
+
+ /* group outputs */
+ for(gsock=ntree->outputs.first; gsock; gsock = gsock->next) {
+ if (gsock->link && gsock->link->fromsock) {
+ gsock->stack_type = gsock->link->fromsock->stack_type;
+ gsock->stack_index = gsock->link->fromsock->stack_index;
+ gsock->stack_ptr = gsock->link->fromsock->stack_ptr;
}
-
- if(node->type==NODE_GROUP) {
- if(node->id) {
- node->stack_index= index;
- index+= ntree_begin_exec_tree((bNodeTree *)node->id);
- }
+ else {
+ gsock->stack_type = SOCK_STACK_CONST;
+ gsock->stack_index = -1;
+ gsock->stack_ptr = &gsock->ns;
}
}
@@ -1914,7 +2148,7 @@ static int ntree_begin_exec_tree(bNodeTree *ntree)
}
/* copy socket compbufs to stack, initialize usage of curve nodes */
-static void composit_begin_exec(bNodeTree *ntree, int is_group)
+static void composit_begin_exec(bNodeTree *ntree, bNodeStack *stack)
{
bNode *node;
bNodeSocket *sock;
@@ -1924,16 +2158,14 @@ static void composit_begin_exec(bNodeTree *ntree, int is_group)
/* initialize needed for groups */
node->exec= 0;
- if(is_group==0) {
- for(sock= node->outputs.first; sock; sock= sock->next) {
- bNodeStack *ns= ntree->stack + sock->stack_index;
-
- if(sock->ns.data) {
- ns->data= sock->ns.data;
- sock->ns.data= NULL;
- }
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ bNodeStack *ns= get_socket_stack(stack, sock, NULL);
+ if(ns && sock->ns.data) {
+ ns->data= sock->ns.data;
+ sock->ns.data= NULL;
}
}
+
/* cannot initialize them while using in threads */
if(ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) {
curvemapping_initialize(node->storage);
@@ -1941,75 +2173,60 @@ static void composit_begin_exec(bNodeTree *ntree, int is_group)
curvemapping_premultiply(node->storage, 0);
}
if(node->type==NODE_GROUP)
- composit_begin_exec((bNodeTree *)node->id, 1);
+ composit_begin_exec((bNodeTree *)node->id, stack + node->stack_index);
}
}
/* copy stack compbufs to sockets */
-static void composit_end_exec(bNodeTree *ntree, int is_group)
+static void composit_end_exec(bNodeTree *ntree, bNodeStack *stack)
{
- extern void print_compbuf(char *str, struct CompBuf *cbuf);
bNode *node;
bNodeStack *ns;
- int a;
for(node= ntree->nodes.first; node; node= node->next) {
- if(is_group==0) {
- bNodeSocket *sock;
+ bNodeSocket *sock;
- for(sock= node->outputs.first; sock; sock= sock->next) {
- ns= ntree->stack + sock->stack_index;
- if(ns->data) {
- sock->ns.data= ns->data;
- ns->data= NULL;
- }
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ ns = get_socket_stack(stack, sock, NULL);
+ if(ns && ns->data) {
+ sock->ns.data= ns->data;
+ ns->data= NULL;
}
}
+
if(node->type==CMP_NODE_CURVE_RGB)
curvemapping_premultiply(node->storage, 1);
if(node->type==NODE_GROUP)
- composit_end_exec((bNodeTree *)node->id, 1);
+ composit_end_exec((bNodeTree *)node->id, stack + node->stack_index);
node->need_exec= 0;
}
-
- if(is_group==0) {
- /* internally, group buffers are not stored */
- for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) {
- if(ns->data) {
- printf("freed leftover buffer from stack\n");
- free_compbuf(ns->data);
- ns->data= NULL;
- }
- }
- }
}
-static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack)
+static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack, bNodeStack **gin)
{
bNodeTree *ntree= (bNodeTree *)gnode->id;
bNode *node;
+ bNodeSocket *sock;
stack+= gnode->stack_index;
for(node= ntree->nodes.first; node; node= node->next) {
if(node->typeinfo->execfunc) {
- bNodeSocket *sock;
-
for(sock= node->inputs.first; sock; sock= sock->next) {
- if(sock->intern) {
- if(sock->link) {
- bNodeStack *ns= stack + sock->link->fromsock->stack_index;
- ns->hasoutput= 1;
- ns->sockettype= sock->link->fromsock->type;
- }
- else
- sock->ns.sockettype= sock->type;
- }
+ bNodeStack *ns = get_socket_stack(stack, sock, gin);
+ ns->hasoutput= 1;
}
}
+
+ /* set stack types (for local stack entries) */
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ bNodeStack *ns = get_socket_stack(stack, sock, NULL);
+ if (ns)
+ ns->sockettype = sock->type;
+ }
}
}
@@ -2067,6 +2284,8 @@ static void tex_end_exec(bNodeTree *ntree)
void ntreeBeginExecTree(bNodeTree *ntree)
{
+ bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
+
/* let's make it sure */
if(ntree->init & NTREE_EXEC_INIT)
return;
@@ -2098,13 +2317,9 @@ void ntreeBeginExecTree(bNodeTree *ntree)
node->need_exec= 1;
for(sock= node->inputs.first; sock; sock= sock->next) {
- if(sock->link) {
- ns= ntree->stack + sock->link->fromsock->stack_index;
- ns->hasoutput= 1;
- ns->sockettype= sock->link->fromsock->type;
- }
- else
- sock->ns.sockettype= sock->type;
+ ns = get_socket_stack(ntree->stack, sock, NULL);
+ if (ns)
+ ns->hasoutput = 1;
if(sock->link) {
bNodeLink *link= sock->link;
@@ -2118,13 +2333,21 @@ void ntreeBeginExecTree(bNodeTree *ntree)
}
}
- if(node->type==NODE_GROUP && node->id)
- group_tag_used_outputs(node, ntree->stack);
+ /* set stack types (for local stack entries) */
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ ns = get_socket_stack(ntree->stack, sock, NULL);
+ if (ns)
+ ns->sockettype = sock->type;
+ }
+ if(node->type==NODE_GROUP && node->id) {
+ node_get_stack(node, ntree->stack, nsin, NULL, NULL);
+ group_tag_used_outputs(node, ntree->stack, nsin);
+ }
}
if(ntree->type==NTREE_COMPOSIT)
- composit_begin_exec(ntree, 0);
+ composit_begin_exec(ntree, ntree->stack);
}
ntree->init |= NTREE_EXEC_INIT;
@@ -2132,14 +2355,24 @@ void ntreeBeginExecTree(bNodeTree *ntree)
void ntreeEndExecTree(bNodeTree *ntree)
{
+ bNodeStack *ns;
if(ntree->init & NTREE_EXEC_INIT) {
bNodeThreadStack *nts;
int a;
/* another callback candidate! */
- if(ntree->type==NTREE_COMPOSIT)
- composit_end_exec(ntree, 0);
+ if(ntree->type==NTREE_COMPOSIT) {
+ composit_end_exec(ntree, ntree->stack);
+
+ for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) {
+ if(ns->data) {
+ printf("freed leftover buffer from stack\n");
+ free_compbuf(ns->data);
+ ns->data= NULL;
+ }
+ }
+ }
else if(ntree->type==NTREE_TEXTURE)
tex_end_exec(ntree);
@@ -2163,23 +2396,6 @@ void ntreeEndExecTree(bNodeTree *ntree)
}
}
-static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
-{
- bNodeSocket *sock;
-
- /* build pointer stack */
- for(sock= node->inputs.first; sock; sock= sock->next) {
- if(sock->link)
- *(in++)= stack + sock->link->fromsock->stack_index;
- else
- *(in++)= &sock->ns;
- }
-
- for(sock= node->outputs.first; sock; sock= sock->next) {
- *(out++)= stack + sock->stack_index;
- }
-}
-
/* nodes are presorted, so exec is in order of list */
void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
{
@@ -2192,7 +2408,7 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
/* only when initialized */
if((ntree->init & NTREE_EXEC_INIT)==0)
ntreeBeginExecTree(ntree);
-
+
/* composite does 1 node per thread, so no multiple stacks needed */
if(ntree->type==NTREE_COMPOSIT) {
stack= ntree->stack;
@@ -2205,12 +2421,12 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
for(node= ntree->nodes.first; node; node= node->next) {
if(node->need_exec) {
if(node->typeinfo->execfunc) {
- node_get_stack(node, stack, nsin, nsout);
+ node_get_stack(node, stack, nsin, nsout, NULL);
node->typeinfo->execfunc(callerdata, node, nsin, nsout);
}
else if(node->type==NODE_GROUP && node->id) {
- node_get_stack(node, stack, nsin, nsout);
- node_group_execute(stack, callerdata, node, nsin, nsout);
+ node_get_stack(node, stack, nsin, NULL, NULL);
+ node_group_execute(stack, callerdata, node, nsin);
}
}
}
@@ -2256,7 +2472,7 @@ static void *exec_composite_node(void *node_v)
bNode *node= node_v;
ThreadData *thd= (ThreadData *)node->threaddata;
- node_get_stack(node, thd->stack, nsin, nsout);
+ node_get_stack(node, thd->stack, nsin, nsout, NULL);
if((node->flag & NODE_MUTED) && (!node_only_value(node))) {
/* viewers we execute, for feedback to user */
@@ -2269,11 +2485,11 @@ static void *exec_composite_node(void *node_v)
node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
}
else if(node->type==NODE_GROUP && node->id) {
- node_group_execute(thd->stack, thd->rd, node, nsin, nsout);
+ node_group_execute(thd->stack, thd->rd, node, nsin);
}
node->exec |= NODE_READY;
- return 0;
+ return NULL;
}
/* return total of executable nodes, for timecursor */
@@ -2297,7 +2513,7 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd)
for(node= ntree->nodes.first; node; node= node->next) {
int a;
- node_get_stack(node, thd->stack, nsin, nsout);
+ node_get_stack(node, thd->stack, nsin, nsout, NULL);
/* test the outputs */
/* skip value-only nodes (should be in type!) */
@@ -2362,7 +2578,7 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd)
for(node= ntree->nodes.first; node; node= node->next) {
if(node->need_exec==0 && node_only_value(node)) {
if(node->typeinfo->execfunc) {
- node_get_stack(node, thd->stack, nsin, nsout);
+ node_get_stack(node, thd->stack, nsin, nsout, NULL);
node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
}
}
@@ -2400,8 +2616,8 @@ static void freeExecutableNode(bNodeTree *ntree)
for(node= ntree->nodes.first; node; node= node->next) {
if(node->exec & NODE_FREEBUFS) {
for(sock= node->outputs.first; sock; sock= sock->next) {
- bNodeStack *ns= ntree->stack + sock->stack_index;
- if(ns->data) {
+ bNodeStack *ns= get_socket_stack(ntree->stack, sock, NULL);
+ if(ns && ns->data) {
free_compbuf(ns->data);
ns->data= NULL;
// printf("freed buf node %s \n", node->name);
@@ -2421,7 +2637,7 @@ static bNode *getExecutableNode(bNodeTree *ntree)
/* input sockets should be ready */
for(sock= node->inputs.first; sock; sock= sock->next) {
- if(sock->link)
+ if(sock->link && sock->link->fromnode)
if((sock->link->fromnode->exec & NODE_READY)==0)
break;
}
@@ -2432,6 +2648,25 @@ static bNode *getExecutableNode(bNodeTree *ntree)
return NULL;
}
+/* check if texture nodes need exec or end */
+static void ntree_composite_texnode(bNodeTree *ntree, int init)
+{
+ bNode *node;
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->type==CMP_NODE_TEXTURE && node->id) {
+ Tex *tex= (Tex *)node->id;
+ if(tex->nodetree && tex->use_nodes) {
+ /* has internal flag to detect it only does it once */
+ if(init)
+ ntreeBeginExecTree(tex->nodetree);
+ else
+ ntreeEndExecTree(tex->nodetree);
+ }
+ }
+ }
+
+}
/* optimized tree execute test for compositing */
void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
@@ -2447,6 +2682,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
ntreeInitPreview(ntree, 0, 0);
ntreeBeginExecTree(ntree);
+ ntree_composite_texnode(ntree, 1);
/* prevent unlucky accidents */
if(G.background)
@@ -2459,6 +2695,9 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
/* fixed seed, for example noise texture */
BLI_srandom(rd->cfra);
+ /* ensures only a single output node is enabled */
+ ntreeSetOutput(ntree);
+
/* sets need_exec tags in nodes */
curnode = totnode= setExecutableNodes(ntree, &thdata);
@@ -2469,7 +2708,6 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
if(BLI_available_threads(&threads)) {
node= getExecutableNode(ntree);
if(node) {
-
if(ntree->progress && totnode)
ntree->progress(ntree->prh, (1.0 - curnode/(float)totnode));
if(ntree->stats_draw) {
@@ -2544,7 +2782,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
}
/* node copy func */
- ltree= ntreeCopyTree(ntree, 0);
+ ltree= ntreeCopyTree(ntree);
if(adt) {
AnimData *ladt= BKE_animdata_from_id(&ltree->id);
@@ -2557,9 +2795,10 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
}
/* end animdata uglyness */
-
- /* move over the compbufs */
- /* right after ntreeCopyTree() oldsock pointers are valid */
+
+ /* ensures only a single output node is enabled */
+ ntreeSetOutput(ntree);
+
for(node= ntree->nodes.first; node; node= node->next) {
/* store new_node pointer to original */
@@ -2567,22 +2806,27 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
/* ensure new user input gets handled ok */
node->need_exec= 0;
- if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- if(node->id) {
- if(node->flag & NODE_DO_OUTPUT)
- node->new_node->id= (ID *)copy_image((Image *)node->id);
- else
- node->new_node->id= NULL;
- }
- }
-
- for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(ntree->type==NTREE_COMPOSIT) {
+ /* move over the compbufs */
+ /* right after ntreeCopyTree() oldsock pointers are valid */
- sock->new_sock->ns.data= sock->ns.data;
- compbuf_set_node(sock->new_sock->ns.data, node->new_node);
+ if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if(node->id) {
+ if(node->flag & NODE_DO_OUTPUT)
+ node->new_node->id= (ID *)copy_image((Image *)node->id);
+ else
+ node->new_node->id= NULL;
+ }
+ }
- sock->ns.data= NULL;
- sock->new_sock->new_sock= sock;
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+
+ sock->new_sock->ns.data= sock->ns.data;
+ compbuf_set_node(sock->new_sock->ns.data, node->new_node);
+
+ sock->ns.data= NULL;
+ sock->new_sock->new_sock= sock;
+ }
}
}
@@ -2610,19 +2854,38 @@ static int outsocket_exists(bNode *node, bNodeSocket *testsock)
/* sync local composite with real tree */
/* local composite is supposed to be running, be careful moving previews! */
+/* is called by jobs manager, outside threads, so it doesnt happen during draw */
void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
{
bNode *lnode;
- /* move over the compbufs and previews */
- for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
- if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
+ if(ntree->type==NTREE_COMPOSIT) {
+ /* move over the compbufs and previews */
+ for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
+ if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
+ if(node_exists(ntree, lnode->new_node)) {
+
+ if(lnode->preview && lnode->preview->rect) {
+ node_free_preview(lnode->new_node);
+ lnode->new_node->preview= lnode->preview;
+ lnode->preview= NULL;
+ }
+ }
+ }
+ }
+ }
+ else if(ntree->type==NTREE_SHADER) {
+ /* copy over contents of previews */
+ for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
if(node_exists(ntree, lnode->new_node)) {
+ bNode *node= lnode->new_node;
- if(lnode->preview && lnode->preview->rect) {
- node_free_preview(lnode->new_node);
- lnode->new_node->preview= lnode->preview;
- lnode->preview= NULL;
+ if(node->preview && node->preview->rect) {
+ if(lnode->preview && lnode->preview->rect) {
+ int xsize= node->preview->xsize;
+ int ysize= node->preview->ysize;
+ memcpy(node->preview->rect, lnode->preview->rect, 4*xsize + xsize*ysize*sizeof(char)*4);
+ }
}
}
}
@@ -2693,7 +2956,7 @@ static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack
gs[i].name = "";
gs[i].hasinput= ns[i]->hasinput && ns[i]->data;
- gs[i].hasoutput= ns[i]->hasinput && ns[i]->data;
+ gs[i].hasoutput= ns[i]->hasoutput && ns[i]->data;
gs[i].sockettype= ns[i]->sockettype;
}
@@ -2707,13 +2970,11 @@ static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack
for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
ns[i]->data= gs[i].link;
- ns[i]->hasinput= gs[i].hasinput && gs[i].link;
- ns[i]->hasoutput= gs[i].hasoutput;
ns[i]->sockettype= gs[i].sockettype;
}
}
-static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out)
+static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in)
{
bNode *node;
bNodeTree *ntree= (bNodeTree *)gnode->id;
@@ -2728,7 +2989,7 @@ static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *g
for(node= ntree->nodes.first; node; node= node->next) {
if(node->typeinfo->gpufunc) {
- group_node_get_stack(node, stack, nsin, nsout, in, out);
+ node_get_stack(node, stack, nsin, nsout, in);
doit = 0;
@@ -2766,15 +3027,15 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
for(node= ntree->nodes.first; node; node= node->next) {
if(node->typeinfo->gpufunc) {
- node_get_stack(node, stack, nsin, nsout);
+ node_get_stack(node, stack, nsin, nsout, NULL);
gpu_from_node_stack(&node->inputs, nsin, gpuin);
gpu_from_node_stack(&node->outputs, nsout, gpuout);
if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
data_from_gpu_stack(&node->outputs, nsout, gpuout);
}
else if(node->type==NODE_GROUP && node->id) {
- node_get_stack(node, stack, nsin, nsout);
- gpu_node_group_execute(stack, mat, node, nsin, nsout);
+ node_get_stack(node, stack, nsin, nsout, NULL);
+ gpu_node_group_execute(stack, mat, node, nsin);
}
}
@@ -2884,6 +3145,8 @@ void ntreeCompositTagRender(Scene *curscene)
for(node= sce->nodetree->nodes.first; node; node= node->next) {
if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE)
NodeTagChanged(sce->nodetree, node);
+ else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */
+ NodeTagChanged(sce->nodetree, node);
}
}
}
@@ -2899,7 +3162,7 @@ static int node_animation_properties(bNodeTree *ntree, bNode *node)
/* check to see if any of the node's properties have fcurves */
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
- lb = RNA_struct_defined_properties(ptr.type);
+ lb = RNA_struct_type_properties(ptr.type);
for (link=lb->first; link; link=link->next) {
int driven, len=1, index;
@@ -2961,10 +3224,7 @@ int ntreeCompositTagAnimated(bNodeTree *ntree)
NodeTagChanged(ntree, node);
tagged= 1;
}
- else if(node->type==CMP_NODE_R_LAYERS) {
- NodeTagChanged(ntree, node);
- tagged= 1;
- }
+ /* here was tag render layer, but this is called after a render, so re-composites fail */
else if(node->type==NODE_GROUP) {
if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) {
NodeTagChanged(ntree, node);
@@ -2989,6 +3249,21 @@ void ntreeCompositTagGenerators(bNodeTree *ntree)
}
}
+/* XXX after render animation system gets a refresh, this call allows composite to end clean */
+void ntreeClearTags(bNodeTree *ntree)
+{
+ bNode *node;
+
+ if(ntree==NULL) return;
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ node->need_exec= 0;
+ if(node->type==NODE_GROUP)
+ ntreeClearTags((bNodeTree *)node->id);
+ }
+}
+
+
int ntreeTexTagAnimated(bNodeTree *ntree)
{
bNode *node;
@@ -3012,6 +3287,62 @@ int ntreeTexTagAnimated(bNodeTree *ntree)
/* ************* node definition init ********** */
+void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag,
+ struct bNodeSocketType *inputs, struct bNodeSocketType *outputs)
+{
+ memset(ntype, 0, sizeof(bNodeType));
+
+ ntype->type = type;
+ ntype->name = name;
+ ntype->nclass = nclass;
+ ntype->flag = flag;
+
+ ntype->inputs = inputs;
+ ntype->outputs = outputs;
+
+ /* default size values */
+ ntype->width = 140;
+ ntype->minwidth = 100;
+ ntype->maxwidth = 320;
+}
+
+void node_type_init(bNodeType *ntype, void (*initfunc)(struct bNode *))
+{
+ ntype->initfunc = initfunc;
+}
+
+void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
+{
+ ntype->width = width;
+ ntype->minwidth = minwidth;
+ ntype->maxwidth = maxwidth;
+}
+
+void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *))
+{
+ if (storagename)
+ strncpy(ntype->storagename, storagename, sizeof(ntype->storagename));
+ else
+ ntype->storagename[0] = '\0';
+ ntype->copystoragefunc = copystoragefunc;
+ ntype->freestoragefunc = freestoragefunc;
+}
+
+void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **))
+{
+ ntype->execfunc = execfunc;
+}
+
+void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out))
+{
+ ntype->gpufunc = gpufunc;
+}
+
+void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *))
+{
+ ntype->labelfunc = labelfunc;
+}
+
static bNodeType *is_nodetype_registered(ListBase *typelist, int type, ID *id)
{
bNodeType *ntype= typelist->first;
@@ -3037,147 +3368,150 @@ void nodeRegisterType(ListBase *typelist, const bNodeType *ntype)
static void registerCompositNodes(ListBase *ntypelist)
{
- nodeRegisterType(ntypelist, &node_group_typeinfo);
- nodeRegisterType(ntypelist, &cmp_node_rlayers);
- nodeRegisterType(ntypelist, &cmp_node_image);
- nodeRegisterType(ntypelist, &cmp_node_texture);
- nodeRegisterType(ntypelist, &cmp_node_value);
- nodeRegisterType(ntypelist, &cmp_node_rgb);
- nodeRegisterType(ntypelist, &cmp_node_curve_time);
-
- nodeRegisterType(ntypelist, &cmp_node_composite);
- nodeRegisterType(ntypelist, &cmp_node_viewer);
- nodeRegisterType(ntypelist, &cmp_node_splitviewer);
- nodeRegisterType(ntypelist, &cmp_node_output_file);
- nodeRegisterType(ntypelist, &cmp_node_view_levels);
-
- nodeRegisterType(ntypelist, &cmp_node_curve_rgb);
- nodeRegisterType(ntypelist, &cmp_node_mix_rgb);
- nodeRegisterType(ntypelist, &cmp_node_hue_sat);
- nodeRegisterType(ntypelist, &cmp_node_brightcontrast);
- nodeRegisterType(ntypelist, &cmp_node_gamma);
- nodeRegisterType(ntypelist, &cmp_node_invert);
- nodeRegisterType(ntypelist, &cmp_node_alphaover);
- nodeRegisterType(ntypelist, &cmp_node_zcombine);
- nodeRegisterType(ntypelist, &cmp_node_colorbalance);
- nodeRegisterType(ntypelist, &cmp_node_huecorrect);
-
- nodeRegisterType(ntypelist, &cmp_node_normal);
- nodeRegisterType(ntypelist, &cmp_node_curve_vec);
- nodeRegisterType(ntypelist, &cmp_node_map_value);
- nodeRegisterType(ntypelist, &cmp_node_normalize);
-
- nodeRegisterType(ntypelist, &cmp_node_filter);
- nodeRegisterType(ntypelist, &cmp_node_blur);
- nodeRegisterType(ntypelist, &cmp_node_dblur);
- nodeRegisterType(ntypelist, &cmp_node_bilateralblur);
- nodeRegisterType(ntypelist, &cmp_node_vecblur);
- nodeRegisterType(ntypelist, &cmp_node_dilateerode);
- nodeRegisterType(ntypelist, &cmp_node_defocus);
-
- nodeRegisterType(ntypelist, &cmp_node_valtorgb);
- nodeRegisterType(ntypelist, &cmp_node_rgbtobw);
- nodeRegisterType(ntypelist, &cmp_node_setalpha);
- nodeRegisterType(ntypelist, &cmp_node_idmask);
- nodeRegisterType(ntypelist, &cmp_node_math);
- nodeRegisterType(ntypelist, &cmp_node_seprgba);
- nodeRegisterType(ntypelist, &cmp_node_combrgba);
- nodeRegisterType(ntypelist, &cmp_node_sephsva);
- nodeRegisterType(ntypelist, &cmp_node_combhsva);
- nodeRegisterType(ntypelist, &cmp_node_sepyuva);
- nodeRegisterType(ntypelist, &cmp_node_combyuva);
- nodeRegisterType(ntypelist, &cmp_node_sepycca);
- nodeRegisterType(ntypelist, &cmp_node_combycca);
- nodeRegisterType(ntypelist, &cmp_node_premulkey);
-
- nodeRegisterType(ntypelist, &cmp_node_diff_matte);
- nodeRegisterType(ntypelist, &cmp_node_distance_matte);
- nodeRegisterType(ntypelist, &cmp_node_chroma_matte);
- nodeRegisterType(ntypelist, &cmp_node_color_matte);
- nodeRegisterType(ntypelist, &cmp_node_channel_matte);
- nodeRegisterType(ntypelist, &cmp_node_color_spill);
- nodeRegisterType(ntypelist, &cmp_node_luma_matte);
-
- nodeRegisterType(ntypelist, &cmp_node_translate);
- nodeRegisterType(ntypelist, &cmp_node_rotate);
- nodeRegisterType(ntypelist, &cmp_node_scale);
- nodeRegisterType(ntypelist, &cmp_node_flip);
- nodeRegisterType(ntypelist, &cmp_node_crop);
- nodeRegisterType(ntypelist, &cmp_node_displace);
- nodeRegisterType(ntypelist, &cmp_node_mapuv);
- nodeRegisterType(ntypelist, &cmp_node_glare);
- nodeRegisterType(ntypelist, &cmp_node_tonemap);
- nodeRegisterType(ntypelist, &cmp_node_lensdist);
+ register_node_type_group(ntypelist);
+
+ register_node_type_cmp_rlayers(ntypelist);
+ register_node_type_cmp_image(ntypelist);
+ register_node_type_cmp_texture(ntypelist);
+ register_node_type_cmp_value(ntypelist);
+ register_node_type_cmp_rgb(ntypelist);
+ register_node_type_cmp_curve_time(ntypelist);
+
+ register_node_type_cmp_composite(ntypelist);
+ register_node_type_cmp_viewer(ntypelist);
+ register_node_type_cmp_splitviewer(ntypelist);
+ register_node_type_cmp_output_file(ntypelist);
+ register_node_type_cmp_view_levels(ntypelist);
+
+ register_node_type_cmp_curve_rgb(ntypelist);
+ register_node_type_cmp_mix_rgb(ntypelist);
+ register_node_type_cmp_hue_sat(ntypelist);
+ register_node_type_cmp_brightcontrast(ntypelist);
+ register_node_type_cmp_gamma(ntypelist);
+ register_node_type_cmp_invert(ntypelist);
+ register_node_type_cmp_alphaover(ntypelist);
+ register_node_type_cmp_zcombine(ntypelist);
+ register_node_type_cmp_colorbalance(ntypelist);
+ register_node_type_cmp_huecorrect(ntypelist);
+
+ register_node_type_cmp_normal(ntypelist);
+ register_node_type_cmp_curve_vec(ntypelist);
+ register_node_type_cmp_map_value(ntypelist);
+ register_node_type_cmp_normalize(ntypelist);
+
+ register_node_type_cmp_filter(ntypelist);
+ register_node_type_cmp_blur(ntypelist);
+ register_node_type_cmp_dblur(ntypelist);
+ register_node_type_cmp_bilateralblur(ntypelist);
+ register_node_type_cmp_vecblur(ntypelist);
+ register_node_type_cmp_dilateerode(ntypelist);
+ register_node_type_cmp_defocus(ntypelist);
+
+ register_node_type_cmp_valtorgb(ntypelist);
+ register_node_type_cmp_rgbtobw(ntypelist);
+ register_node_type_cmp_setalpha(ntypelist);
+ register_node_type_cmp_idmask(ntypelist);
+ register_node_type_cmp_math(ntypelist);
+ register_node_type_cmp_seprgba(ntypelist);
+ register_node_type_cmp_combrgba(ntypelist);
+ register_node_type_cmp_sephsva(ntypelist);
+ register_node_type_cmp_combhsva(ntypelist);
+ register_node_type_cmp_sepyuva(ntypelist);
+ register_node_type_cmp_combyuva(ntypelist);
+ register_node_type_cmp_sepycca(ntypelist);
+ register_node_type_cmp_combycca(ntypelist);
+ register_node_type_cmp_premulkey(ntypelist);
+
+ register_node_type_cmp_diff_matte(ntypelist);
+ register_node_type_cmp_distance_matte(ntypelist);
+ register_node_type_cmp_chroma_matte(ntypelist);
+ register_node_type_cmp_color_matte(ntypelist);
+ register_node_type_cmp_channel_matte(ntypelist);
+ register_node_type_cmp_color_spill(ntypelist);
+ register_node_type_cmp_luma_matte(ntypelist);
+
+ register_node_type_cmp_translate(ntypelist);
+ register_node_type_cmp_rotate(ntypelist);
+ register_node_type_cmp_scale(ntypelist);
+ register_node_type_cmp_flip(ntypelist);
+ register_node_type_cmp_crop(ntypelist);
+ register_node_type_cmp_displace(ntypelist);
+ register_node_type_cmp_mapuv(ntypelist);
+ register_node_type_cmp_glare(ntypelist);
+ register_node_type_cmp_tonemap(ntypelist);
+ register_node_type_cmp_lensdist(ntypelist);
}
static void registerShaderNodes(ListBase *ntypelist)
{
- nodeRegisterType(ntypelist, &node_group_typeinfo);
- nodeRegisterType(ntypelist, &sh_node_output);
- nodeRegisterType(ntypelist, &sh_node_mix_rgb);
- nodeRegisterType(ntypelist, &sh_node_valtorgb);
- nodeRegisterType(ntypelist, &sh_node_rgbtobw);
- nodeRegisterType(ntypelist, &sh_node_normal);
- nodeRegisterType(ntypelist, &sh_node_geom);
- nodeRegisterType(ntypelist, &sh_node_mapping);
- nodeRegisterType(ntypelist, &sh_node_curve_vec);
- nodeRegisterType(ntypelist, &sh_node_curve_rgb);
- nodeRegisterType(ntypelist, &sh_node_math);
- nodeRegisterType(ntypelist, &sh_node_vect_math);
- nodeRegisterType(ntypelist, &sh_node_squeeze);
- nodeRegisterType(ntypelist, &sh_node_camera);
- nodeRegisterType(ntypelist, &sh_node_material);
- nodeRegisterType(ntypelist, &sh_node_material_ext);
- nodeRegisterType(ntypelist, &sh_node_value);
- nodeRegisterType(ntypelist, &sh_node_rgb);
- nodeRegisterType(ntypelist, &sh_node_texture);
- nodeRegisterType(ntypelist, &node_dynamic_typeinfo);
- nodeRegisterType(ntypelist, &sh_node_invert);
- nodeRegisterType(ntypelist, &sh_node_seprgb);
- nodeRegisterType(ntypelist, &sh_node_combrgb);
- nodeRegisterType(ntypelist, &sh_node_hue_sat);
+ register_node_type_group(ntypelist);
+
+ register_node_type_sh_output(ntypelist);
+ register_node_type_sh_mix_rgb(ntypelist);
+ register_node_type_sh_valtorgb(ntypelist);
+ register_node_type_sh_rgbtobw(ntypelist);
+ register_node_type_sh_normal(ntypelist);
+ register_node_type_sh_geom(ntypelist);
+ register_node_type_sh_mapping(ntypelist);
+ register_node_type_sh_curve_vec(ntypelist);
+ register_node_type_sh_curve_rgb(ntypelist);
+ register_node_type_sh_math(ntypelist);
+ register_node_type_sh_vect_math(ntypelist);
+ register_node_type_sh_squeeze(ntypelist);
+ register_node_type_sh_camera(ntypelist);
+ register_node_type_sh_material(ntypelist);
+ register_node_type_sh_material_ext(ntypelist);
+ register_node_type_sh_value(ntypelist);
+ register_node_type_sh_rgb(ntypelist);
+ register_node_type_sh_texture(ntypelist);
+// register_node_type_sh_dynamic(ntypelist);
+ register_node_type_sh_invert(ntypelist);
+ register_node_type_sh_seprgb(ntypelist);
+ register_node_type_sh_combrgb(ntypelist);
+ register_node_type_sh_hue_sat(ntypelist);
}
static void registerTextureNodes(ListBase *ntypelist)
{
- nodeRegisterType(ntypelist, &node_group_typeinfo);
- nodeRegisterType(ntypelist, &tex_node_math);
- nodeRegisterType(ntypelist, &tex_node_mix_rgb);
- nodeRegisterType(ntypelist, &tex_node_valtorgb);
- nodeRegisterType(ntypelist, &tex_node_rgbtobw);
- nodeRegisterType(ntypelist, &tex_node_valtonor);
- nodeRegisterType(ntypelist, &tex_node_curve_rgb);
- nodeRegisterType(ntypelist, &tex_node_curve_time);
- nodeRegisterType(ntypelist, &tex_node_invert);
- nodeRegisterType(ntypelist, &tex_node_hue_sat);
- nodeRegisterType(ntypelist, &tex_node_coord);
- nodeRegisterType(ntypelist, &tex_node_distance);
- nodeRegisterType(ntypelist, &tex_node_compose);
- nodeRegisterType(ntypelist, &tex_node_decompose);
-
- nodeRegisterType(ntypelist, &tex_node_output);
- nodeRegisterType(ntypelist, &tex_node_viewer);
-
- nodeRegisterType(ntypelist, &tex_node_checker);
- nodeRegisterType(ntypelist, &tex_node_texture);
- nodeRegisterType(ntypelist, &tex_node_bricks);
- nodeRegisterType(ntypelist, &tex_node_image);
-
- nodeRegisterType(ntypelist, &tex_node_rotate);
- nodeRegisterType(ntypelist, &tex_node_translate);
- nodeRegisterType(ntypelist, &tex_node_scale);
- nodeRegisterType(ntypelist, &tex_node_at);
-
- nodeRegisterType(ntypelist, &tex_node_proc_voronoi);
- nodeRegisterType(ntypelist, &tex_node_proc_blend);
- nodeRegisterType(ntypelist, &tex_node_proc_magic);
- nodeRegisterType(ntypelist, &tex_node_proc_marble);
- nodeRegisterType(ntypelist, &tex_node_proc_clouds);
- nodeRegisterType(ntypelist, &tex_node_proc_wood);
- nodeRegisterType(ntypelist, &tex_node_proc_musgrave);
- nodeRegisterType(ntypelist, &tex_node_proc_noise);
- nodeRegisterType(ntypelist, &tex_node_proc_stucci);
- nodeRegisterType(ntypelist, &tex_node_proc_distnoise);
+ register_node_type_group(ntypelist);
+
+ register_node_type_tex_math(ntypelist);
+ register_node_type_tex_mix_rgb(ntypelist);
+ register_node_type_tex_valtorgb(ntypelist);
+ register_node_type_tex_rgbtobw(ntypelist);
+ register_node_type_tex_valtonor(ntypelist);
+ register_node_type_tex_curve_rgb(ntypelist);
+ register_node_type_tex_curve_time(ntypelist);
+ register_node_type_tex_invert(ntypelist);
+ register_node_type_tex_hue_sat(ntypelist);
+ register_node_type_tex_coord(ntypelist);
+ register_node_type_tex_distance(ntypelist);
+ register_node_type_tex_compose(ntypelist);
+ register_node_type_tex_decompose(ntypelist);
+
+ register_node_type_tex_output(ntypelist);
+ register_node_type_tex_viewer(ntypelist);
+
+ register_node_type_tex_checker(ntypelist);
+ register_node_type_tex_texture(ntypelist);
+ register_node_type_tex_bricks(ntypelist);
+ register_node_type_tex_image(ntypelist);
+
+ register_node_type_tex_rotate(ntypelist);
+ register_node_type_tex_translate(ntypelist);
+ register_node_type_tex_scale(ntypelist);
+ register_node_type_tex_at(ntypelist);
+
+ register_node_type_tex_proc_voronoi(ntypelist);
+ register_node_type_tex_proc_blend(ntypelist);
+ register_node_type_tex_proc_magic(ntypelist);
+ register_node_type_tex_proc_marble(ntypelist);
+ register_node_type_tex_proc_clouds(ntypelist);
+ register_node_type_tex_proc_wood(ntypelist);
+ register_node_type_tex_proc_musgrave(ntypelist);
+ register_node_type_tex_proc_noise(ntypelist);
+ register_node_type_tex_proc_stucci(ntypelist);
+ register_node_type_tex_proc_distnoise(ntypelist);
}
static void remove_dynamic_typeinfos(ListBase *list)
@@ -3191,7 +3525,7 @@ static void remove_dynamic_typeinfos(ListBase *list)
if(ntype->inputs) {
bNodeSocketType *sock= ntype->inputs;
while(sock->type!=-1) {
- MEM_freeN(sock->name);
+ MEM_freeN((void *)sock->name);
sock++;
}
MEM_freeN(ntype->inputs);
@@ -3199,13 +3533,13 @@ static void remove_dynamic_typeinfos(ListBase *list)
if(ntype->outputs) {
bNodeSocketType *sock= ntype->outputs;
while(sock->type!=-1) {
- MEM_freeN(sock->name);
+ MEM_freeN((void *)sock->name);
sock++;
}
MEM_freeN(ntype->outputs);
}
if(ntype->name) {
- MEM_freeN(ntype->name);
+ MEM_freeN((void *)ntype->name);
}
MEM_freeN(ntype);
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index eddcceb560f..9910392e2d0 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -57,12 +57,11 @@
#include "BLI_editVert.h"
#include "BLI_math.h"
#include "BLI_pbvh.h"
-
-#include "BKE_utildefines.h"
+#include "BLI_utildefines.h"
#include "BKE_main.h"
#include "BKE_global.h"
-
+#include "BKE_idprop.h"
#include "BKE_armature.h"
#include "BKE_action.h"
#include "BKE_bullet.h"
@@ -97,7 +96,7 @@
#include "LBM_fluidsim.h"
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -246,6 +245,13 @@ void free_sculptsession(Object *ob)
if(ss->layer_co)
MEM_freeN(ss->layer_co);
+ if(ss->orig_cos)
+ MEM_freeN(ss->orig_cos);
+ if(ss->deform_cos)
+ MEM_freeN(ss->deform_cos);
+ if(ss->deform_imats)
+ MEM_freeN(ss->deform_imats);
+
MEM_freeN(ss);
ob->sculpt = NULL;
@@ -268,7 +274,7 @@ void free_object(Object *ob)
else if(ob->type==OB_CURVE) unlink_curve(ob->data);
else if(ob->type==OB_MBALL) unlink_mball(ob->data);
}
- ob->data= 0;
+ ob->data= NULL;
}
for(a=0; a<ob->totcol; a++) {
@@ -276,12 +282,12 @@ void free_object(Object *ob)
}
if(ob->mat) MEM_freeN(ob->mat);
if(ob->matbits) MEM_freeN(ob->matbits);
- ob->mat= 0;
- ob->matbits= 0;
+ ob->mat= NULL;
+ ob->matbits= NULL;
if(ob->bb) MEM_freeN(ob->bb);
- ob->bb= 0;
+ ob->bb= NULL;
if(ob->path) free_path(ob->path);
- ob->path= 0;
+ ob->path= NULL;
if(ob->adt) BKE_free_animdata((ID *)ob);
if(ob->poselib) ob->poselib->id.us--;
if(ob->gpd) ((ID *)ob->gpd)->us--;
@@ -317,11 +323,11 @@ static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Objec
if (*obpoin==unlinkOb) {
*obpoin = NULL;
- ob->recalc |= OB_RECALC_ALL; // XXX: should this just be OB_RECALC_DATA?
+ ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; // XXX: should this just be OB_RECALC_DATA?
}
}
-void unlink_object(Scene *scene, Object *ob)
+void unlink_object(Object *ob)
{
Main *bmain= G.main;
Object *obt;
@@ -358,7 +364,7 @@ void unlink_object(Scene *scene, Object *ob)
if(obt->parent==ob) {
obt->parent= NULL;
- obt->recalc |= OB_RECALC_ALL;
+ obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
}
modifiers_foreachObjectLink(obt, unlink_object__unlinkModifierLinks, ob);
@@ -368,15 +374,15 @@ void unlink_object(Scene *scene, Object *ob)
if(cu->bevobj==ob) {
cu->bevobj= NULL;
- obt->recalc |= OB_RECALC_ALL;
+ obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
}
if(cu->taperobj==ob) {
cu->taperobj= NULL;
- obt->recalc |= OB_RECALC_ALL;
+ obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
}
if(cu->textoncurve==ob) {
cu->textoncurve= NULL;
- obt->recalc |= OB_RECALC_ALL;
+ obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
}
}
else if(obt->type==OB_ARMATURE && obt->pose) {
@@ -533,12 +539,10 @@ void unlink_object(Scene *scene, Object *ob)
}
/* textures */
- tex= bmain->tex.first;
- while(tex) {
- if(tex->env) {
- if(tex->env->object == ob) tex->env->object= NULL;
- }
- tex= tex->id.next;
+ for(tex= bmain->tex.first; tex; tex= tex->id.next) {
+ if(tex->env && (ob==tex->env->object)) tex->env->object= NULL;
+ if(tex->pd && (ob==tex->pd->object)) tex->pd->object= NULL;
+ if(tex->vd && (ob==tex->vd->object)) tex->vd->object= NULL;
}
/* worlds */
@@ -696,7 +700,7 @@ int exist_object(Object *obtest)
return 0;
}
-void *add_camera(char *name)
+void *add_camera(const char *name)
{
Camera *cam;
@@ -718,7 +722,6 @@ Camera *copy_camera(Camera *cam)
Camera *camn;
camn= copy_libblock(cam);
- camn->adt= BKE_copy_animdata(cam->adt);
return camn;
}
@@ -737,11 +740,11 @@ void make_local_camera(Camera *cam)
* - mixed: make copy
*/
- if(cam->id.lib==0) return;
+ if(cam->id.lib==NULL) return;
if(cam->id.us==1) {
- cam->id.lib= 0;
+ cam->id.lib= NULL;
cam->id.flag= LIB_LOCAL;
- new_id(0, (ID *)cam, 0);
+ new_id(NULL, (ID *)cam, NULL);
return;
}
@@ -755,9 +758,9 @@ void make_local_camera(Camera *cam)
}
if(local && lib==0) {
- cam->id.lib= 0;
+ cam->id.lib= NULL;
cam->id.flag= LIB_LOCAL;
- new_id(0, (ID *)cam, 0);
+ new_id(NULL, (ID *)cam, NULL);
}
else if(local && lib) {
camn= copy_camera(cam);
@@ -767,7 +770,7 @@ void make_local_camera(Camera *cam)
while(ob) {
if(ob->data==cam) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
ob->data= camn;
camn->id.us++;
cam->id.us--;
@@ -798,7 +801,7 @@ float dof_camera(Object *ob)
return cam->YF_dofdist;
}
-void *add_lamp(char *name)
+void *add_lamp(const char *name)
{
Lamp *la;
@@ -886,11 +889,11 @@ void make_local_lamp(Lamp *la)
* - mixed: make copy
*/
- if(la->id.lib==0) return;
+ if(la->id.lib==NULL) return;
if(la->id.us==1) {
- la->id.lib= 0;
+ la->id.lib= NULL;
la->id.flag= LIB_LOCAL;
- new_id(0, (ID *)la, 0);
+ new_id(NULL, (ID *)la, NULL);
return;
}
@@ -904,9 +907,9 @@ void make_local_lamp(Lamp *la)
}
if(local && lib==0) {
- la->id.lib= 0;
+ la->id.lib= NULL;
la->id.flag= LIB_LOCAL;
- new_id(0, (ID *)la, 0);
+ new_id(NULL, (ID *)la, NULL);
}
else if(local && lib) {
lan= copy_lamp(la);
@@ -916,7 +919,7 @@ void make_local_lamp(Lamp *la)
while(ob) {
if(ob->data==la) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
ob->data= lan;
lan->id.us++;
la->id.us--;
@@ -973,7 +976,7 @@ static void *add_obdata_from_type(int type)
}
}
-static char *get_obdata_defname(int type)
+static const char *get_obdata_defname(int type)
{
switch (type) {
case OB_MESH: return "Mesh";
@@ -993,7 +996,7 @@ static char *get_obdata_defname(int type)
}
/* more general add: creates minimum required data, but without vertices etc. */
-Object *add_only_object(int type, char *name)
+Object *add_only_object(int type, const char *name)
{
Object *ob;
@@ -1011,10 +1014,13 @@ Object *add_only_object(int type, char *name)
* but rotations default to quaternions
*/
ob->rotmode= ROT_MODE_EUL;
- /* axis-angle must not have a 0,0,0 axis, so set y-axis as default... */
- ob->rotAxis[1]= ob->drotAxis[1]= 1.0f;
- /* quaternions should be 1,0,0,0 by default.... */
- ob->quat[0]= ob->dquat[0]= 1.0f;
+
+ unit_axis_angle(ob->rotAxis, &ob->rotAngle);
+ unit_axis_angle(ob->drotAxis, &ob->drotAngle);
+
+ unit_qt(ob->quat);
+ unit_qt(ob->dquat);
+
/* rotation locks should be 4D for 4 component rotations by default... */
ob->protectflag = OB_LOCK_ROT4D;
@@ -1022,7 +1028,7 @@ Object *add_only_object(int type, char *name)
unit_m4(ob->parentinv);
unit_m4(ob->obmat);
ob->dt= OB_TEXTURE;
- ob->empty_drawtype= OB_ARROWS;
+ ob->empty_drawtype= OB_PLAINAXES;
ob->empty_drawsize= 1.0;
if(type==OB_CAMERA || type==OB_LAMP) {
@@ -1073,7 +1079,7 @@ Object *add_object(struct Scene *scene, int type)
Base *base;
char name[32];
- strcpy(name, get_obdata_defname(type));
+ BLI_strncpy(name, get_obdata_defname(type), sizeof(name));
ob = add_only_object(type, name);
ob->data= add_obdata_from_type(type);
@@ -1082,7 +1088,7 @@ Object *add_object(struct Scene *scene, int type)
base= scene_add_base(scene, ob);
scene_select_base(scene, base);
- ob->recalc |= OB_RECALC_ALL;
+ ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
return ob;
}
@@ -1122,7 +1128,7 @@ BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
return bsbn;
}
-ParticleSystem *copy_particlesystem(ParticleSystem *psys)
+static ParticleSystem *copy_particlesystem(ParticleSystem *psys)
{
ParticleSystem *psysn;
ParticleData *pa;
@@ -1267,6 +1273,17 @@ static void copy_object_pose(Object *obn, Object *ob)
}
}
+static void copy_object_transform(Object *ob_tar, Object *ob_src)
+{
+ copy_v3_v3(ob_tar->loc, ob_src->loc);
+ copy_v3_v3(ob_tar->rot, ob_src->rot);
+ copy_v3_v3(ob_tar->quat, ob_src->quat);
+ copy_v3_v3(ob_tar->rotAxis, ob_src->rotAxis);
+ ob_tar->rotAngle= ob_src->rotAngle;
+ ob_tar->rotmode= ob_src->rotmode;
+ copy_v3_v3(ob_tar->size, ob_src->size);
+}
+
Object *copy_object(Object *ob)
{
Object *obn;
@@ -1315,8 +1332,8 @@ Object *copy_object(Object *ob)
/* increase user numbers */
id_us_plus((ID *)obn->data);
+ id_us_plus((ID *)obn->gpd);
id_lib_extern((ID *)obn->dup_group);
-
for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
@@ -1339,6 +1356,8 @@ Object *copy_object(Object *ob)
obn->gpulamp.first = obn->gpulamp.last = NULL;
obn->pc_ids.first = obn->pc_ids.last = NULL;
+
+ obn->mpath= NULL;
return obn;
}
@@ -1466,7 +1485,7 @@ static void armature_set_id_extern(Object *ob)
{
bArmature *arm= ob->data;
bPoseChannel *pchan;
- int lay= arm->layer_protected;
+ unsigned int lay= arm->layer_protected;
for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
if(!(pchan->bone->layer & lay))
@@ -1529,25 +1548,25 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
ob->proxy_group= gob;
id_lib_extern(&target->id);
- ob->recalc= target->recalc= OB_RECALC_ALL;
+ ob->recalc= target->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
- /* copy transform */
+ /* copy transform
+ * - gob means this proxy comes from a group, just apply the matrix
+ * so the object wont move from its dupli-transform.
+ *
+ * - no gob means this is being made from a linked object,
+ * this is closer to making a copy of the object - in-place. */
if(gob) {
- VECCOPY(ob->loc, gob->loc);
- VECCOPY(ob->rot, gob->rot);
- VECCOPY(ob->size, gob->size);
-
- group_tag_recalc(gob->dup_group);
+ ob->rotmode= target->rotmode;
+ mul_m4_m4m4(ob->obmat, target->obmat, gob->obmat);
+ object_apply_mat4(ob, ob->obmat, FALSE, TRUE);
}
else {
- VECCOPY(ob->loc, target->loc);
- VECCOPY(ob->rot, target->rot);
- VECCOPY(ob->size, target->size);
+ copy_object_transform(ob, target);
+ ob->parent= target->parent; /* libdata */
+ copy_m4_m4(ob->parentinv, target->parentinv);
}
- ob->parent= target->parent; /* libdata */
- copy_m4_m4(ob->parentinv, target->parentinv);
-
/* copy animdata stuff - drivers only for now... */
object_copy_proxy_drivers(ob, target);
@@ -1588,7 +1607,17 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
armature_set_id_extern(ob);
}
-
+
+ /* copy IDProperties */
+ if(ob->id.properties) {
+ IDP_FreeProperty(ob->id.properties);
+ MEM_freeN(ob->id.properties);
+ ob->id.properties= NULL;
+ }
+ if(target->id.properties) {
+ ob->id.properties= IDP_CopyProperty(target->id.properties);
+ }
+
/* copy drawtype info */
ob->dt= target->dt;
}
@@ -1598,7 +1627,7 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
/* there is also a timing calculation in drawobject() */
-int no_speed_curve= 0;
+static int no_speed_curve= 0;
void disable_speed_curve(int val)
{
@@ -1607,7 +1636,7 @@ void disable_speed_curve(int val)
// XXX THIS CRUFT NEEDS SERIOUS RECODING ASAP!
/* ob can be NULL */
-float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs)
+float bsystem_time(struct Scene *scene, Object *UNUSED(ob), float cfra, float ofs)
{
/* returns float ( see BKE_curframe in scene.c) */
cfra += scene->r.subframe;
@@ -1636,7 +1665,7 @@ void object_scale_to_mat3(Object *ob, float mat[][3])
size_to_mat3( mat,vec);
}
-// TODO: this should take rotation orders into account later...
+
void object_rot_to_mat3(Object *ob, float mat[][3])
{
float rmat[3][3], dmat[3][3];
@@ -1659,41 +1688,67 @@ void object_rot_to_mat3(Object *ob, float mat[][3])
}
else {
/* quats are normalised before use to eliminate scaling issues */
- normalize_qt(ob->quat);
- quat_to_mat3( rmat,ob->quat);
- quat_to_mat3( dmat,ob->dquat);
+ float tquat[4];
+
+ normalize_qt_qt(tquat, ob->quat);
+ quat_to_mat3(rmat, tquat);
+
+ normalize_qt_qt(tquat, ob->dquat);
+ quat_to_mat3(dmat, tquat);
}
/* combine these rotations */
- // XXX is this correct? if errors, change the order of multiplication...
mul_m3_m3m3(mat, dmat, rmat);
}
-void object_mat3_to_rot(Object *ob, float mat[][3], int use_compat)
+void object_mat3_to_rot(Object *ob, float mat[][3], short use_compat)
{
- if (ob->rotmode == ROT_MODE_QUAT)
- mat3_to_quat(ob->quat, mat);
- else if (ob->rotmode == ROT_MODE_AXISANGLE)
- mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat);
- else {
- if(use_compat) {
- float eul[3];
- VECCOPY(eul, ob->rot);
- mat3_to_compatible_eulO(ob->rot, eul, ob->rotmode, mat);
+ switch(ob->rotmode) {
+ case ROT_MODE_QUAT:
+ {
+ float dquat[4];
+ mat3_to_quat(ob->quat, mat);
+ normalize_qt_qt(dquat, ob->dquat);
+ invert_qt(dquat);
+ mul_qt_qtqt(ob->quat, dquat, ob->quat);
}
- else
- mat3_to_eulO(ob->rot, ob->rotmode, mat);
+ break;
+ case ROT_MODE_AXISANGLE:
+ mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat);
+ sub_v3_v3(ob->rotAxis, ob->drotAxis);
+ ob->rotAngle -= ob->drotAngle;
+ break;
+ default: /* euler */
+ if(use_compat) mat3_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, mat);
+ else mat3_to_eulO(ob->rot, ob->rotmode, mat);
+ sub_v3_v3(ob->rot, ob->drot);
}
}
/* see pchan_apply_mat4() for the equivalent 'pchan' function */
-void object_apply_mat4(Object *ob, float mat[][4])
+void object_apply_mat4(Object *ob, float mat[][4], const short use_compat, const short use_parent)
{
- float mat3[3][3];
- copy_v3_v3(ob->loc, mat[3]);
- mat4_to_size(ob->size, mat);
- copy_m3_m4(mat3, mat);
- object_mat3_to_rot(ob, mat3, 0);
+ float rot[3][3];
+
+ if(use_parent && ob->parent) {
+ float rmat[4][4], diff_mat[4][4], imat[4][4];
+ mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat);
+ invert_m4_m4(imat, diff_mat);
+ mul_m4_m4m4(rmat, mat, imat); /* get the parent relative matrix */
+ object_apply_mat4(ob, rmat, use_compat, FALSE);
+
+ /* same as below, use rmat rather then mat */
+ mat4_to_loc_rot_size(ob->loc, rot, ob->size, rmat);
+ object_mat3_to_rot(ob, rot, use_compat);
+ }
+ else {
+ mat4_to_loc_rot_size(ob->loc, rot, ob->size, mat);
+ object_mat3_to_rot(ob, rot, use_compat);
+ }
+
+ sub_v3_v3(ob->loc, ob->dloc);
+ sub_v3_v3(ob->size, ob->dsize);
+ /* object_mat3_to_rot handles delta rotations */
}
void object_to_mat3(Object *ob, float mat[][3]) /* no parent */
@@ -1721,12 +1776,13 @@ void object_to_mat4(Object *ob, float mat[][4])
add_v3_v3v3(mat[3], ob->loc, ob->dloc);
}
+/* extern */
int enable_cu_speed= 1;
static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
{
Curve *cu;
- float q[4], vec[4], dir[3], quat[4], radius, x1, ctime;
+ float vec[4], dir[3], quat[4], radius, ctime;
float timeoffs = 0.0, sf_orig = 0.0;
unit_m4(mat);
@@ -1754,12 +1810,17 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
* we divide the curvetime calculated in the previous step by the length of the path, to get a time
* factor, which then gets clamped to lie within 0.0 - 1.0 range
*/
- ctime= cu->ctime / cu->pathlen;
+ if (IS_EQ(cu->pathlen, 0.0f) == 0)
+ ctime= cu->ctime / cu->pathlen;
+ else
+ ctime= cu->ctime;
+
CLAMP(ctime, 0.0, 1.0);
}
else {
ctime= scene->r.cfra - give_timeoffset(ob);
- ctime /= cu->pathlen;
+ if (IS_EQ(cu->pathlen, 0.0f) == 0)
+ ctime /= cu->pathlen;
CLAMP(ctime, 0.0, 1.0);
}
@@ -1774,9 +1835,11 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
/* vec: 4 items! */
- if( where_on_path(par, ctime, vec, dir, NULL, &radius, NULL) ) {
+ if( where_on_path(par, ctime, vec, dir, cu->flag & CU_FOLLOW ? quat:NULL, &radius, NULL) ) {
if(cu->flag & CU_FOLLOW) {
+#if 0
+ float x1, q[4];
vec_to_quat( quat,dir, ob->trackflag, ob->upflag);
/* the tilt */
@@ -1787,8 +1850,11 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
q[2]= -x1*dir[1];
q[3]= -x1*dir[2];
mul_qt_qtqt(quat, q, quat);
-
- quat_to_mat4( mat,quat);
+#else
+ quat_apply_track(quat, ob->trackflag, ob->upflag);
+#endif
+ normalize_qt(quat);
+ quat_to_mat4(mat, quat);
}
if(cu->flag & CU_PATH_RADIUS) {
@@ -2044,7 +2110,7 @@ void where_is_object_time(Scene *scene, Object *ob, float ctime)
}
/* solve constraints */
- if (ob->constraints.first && !(ob->flag & OB_NO_CONSTRAINTS)) {
+ if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
bConstraintOb *cob;
cob= constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
@@ -2129,7 +2195,7 @@ static void solve_parenting (Scene *scene, Object *ob, Object *par, float obmat[
copy_m3_m4(originmat, tmat);
// origin, voor help line
- if( (ob->partype & 15)==PARSKEL ) {
+ if( (ob->partype & PARTYPE)==PARSKEL ) {
VECCOPY(ob->orig, par->obmat[3]);
}
else {
@@ -2215,7 +2281,7 @@ void what_does_parent(Scene *scene, Object *ob, Object *workob)
where_is_object(scene, workob);
}
-BoundBox *unit_boundbox()
+BoundBox *unit_boundbox(void)
{
BoundBox *bb;
float min[3] = {-1.0f,-1.0f,-1.0f}, max[3] = {-1.0f,-1.0f,-1.0f};
@@ -2516,46 +2582,64 @@ void object_handle_update(Scene *scene, Object *ob)
if (G.f & G_DEBUG)
printf("recalcdata %s\n", ob->id.name+2);
- /* includes all keys and modifiers */
- if(ob->type==OB_MESH) {
- BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL;
-
+
+ if(adt) {
/* evaluate drivers */
- // XXX: should we push this to derivedmesh instead?
+ // XXX: for mesh types, should we push this to derivedmesh instead?
BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
+
- // here was vieweditdatamask? XXX
- if(em) {
- makeDerivedMesh(scene, ob, em, CD_MASK_BAREMESH);
- } else
- makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH);
}
- else if(ob->type==OB_MBALL) {
- makeDispListMBall(scene, ob);
- }
- else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- makeDispListCurveTypes(scene, ob, 0);
- }
- else if(ELEM(ob->type, OB_CAMERA, OB_LAMP)) {
- /* evaluate drivers */
- BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
- }
- else if(ob->type==OB_LATTICE) {
- lattice_calc_modifiers(scene, ob);
- }
- else if(ob->type==OB_ARMATURE) {
- /* evaluate drivers */
- BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
-
+
+ /* includes all keys and modifiers */
+ switch(ob->type) {
+ case OB_MESH:
+ {
+#if 0 // XXX, comment for 2.56a release, background wont set 'scene->customdata_mask'
+ BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL;
+ BLI_assert((scene->customdata_mask & CD_MASK_BAREMESH) == CD_MASK_BAREMESH);
+ if(em) {
+ makeDerivedMesh(scene, ob, em, scene->customdata_mask); /* was CD_MASK_BAREMESH */
+ } else
+ makeDerivedMesh(scene, ob, NULL, scene->customdata_mask);
+
+#else /* ensure CD_MASK_BAREMESH for now */
+ BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL;
+ if(em) {
+ makeDerivedMesh(scene, ob, em, scene->customdata_mask | CD_MASK_BAREMESH); /* was CD_MASK_BAREMESH */
+ } else
+ makeDerivedMesh(scene, ob, NULL, scene->customdata_mask | CD_MASK_BAREMESH);
+#endif
+
+ }
+ break;
+
+ case OB_ARMATURE:
if(ob->id.lib && ob->proxy_from) {
- copy_pose_result(ob->pose, ob->proxy_from->pose);
// printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
+ copy_pose_result(ob->pose, ob->proxy_from->pose);
}
else {
where_is_pose(scene, ob);
}
+ break;
+
+ case OB_MBALL:
+ makeDispListMBall(scene, ob);
+ break;
+
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ makeDispListCurveTypes(scene, ob, 0);
+ break;
+
+ case OB_LATTICE:
+ lattice_calc_modifiers(scene, ob);
+ break;
}
+
if(ob->particlesystem.first) {
ParticleSystem *tpsys, *psys;
DerivedMesh *dm;
@@ -2879,7 +2963,7 @@ void object_delete_ptcache(Object *ob, int index)
/* shape key utility function */
/************************* Mesh ************************/
-static KeyBlock *insert_meshkey(Scene *scene, Object *ob, char *name, int from_mix)
+static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int from_mix)
{
Mesh *me= ob->data;
Key *key= me->key;
@@ -2910,7 +2994,7 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, char *name, int from_m
return kb;
}
/************************* Lattice ************************/
-static KeyBlock *insert_lattkey(Scene *scene, Object *ob, char *name, int from_mix)
+static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int from_mix)
{
Lattice *lt= ob->data;
Key *key= lt->key;
@@ -2942,7 +3026,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, char *name, int from_m
return kb;
}
/************************* Curve ************************/
-static KeyBlock *insert_curvekey(Scene *scene, Object *ob, char *name, int from_mix)
+static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int from_mix)
{
Curve *cu= ob->data;
Key *key= cu->key;
@@ -2978,7 +3062,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, char *name, int from_
return kb;
}
-KeyBlock *object_insert_shape_key(Scene *scene, Object *ob, char *name, int from_mix)
+KeyBlock *object_insert_shape_key(Scene *scene, Object *ob, const char *name, int from_mix)
{
if(ob->type==OB_MESH) return insert_meshkey(scene, ob, name, from_mix);
else if ELEM(ob->type, OB_CURVE, OB_SURF)return insert_curvekey(scene, ob, name, from_mix);
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 919a724d1ec..981b3b31e71 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -1,4 +1,4 @@
-/**
+/*
* blenkernel/packedFile.c - (cleaned up mar-01 nzc)
*
* $Id$
@@ -47,6 +47,7 @@
#include "DNA_packedFile_types.h"
#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
@@ -162,7 +163,7 @@ PackedFile *newPackedFileMemory(void *mem, int memlen)
return pf;
}
-PackedFile *newPackedFile(ReportList *reports, char *filename)
+PackedFile *newPackedFile(ReportList *reports, const char *filename)
{
PackedFile *pf = NULL;
int file, filelen;
@@ -179,7 +180,7 @@ PackedFile *newPackedFile(ReportList *reports, char *filename)
// convert relative filenames to absolute filenames
strcpy(name, filename);
- BLI_path_abs(name, G.sce);
+ BLI_path_abs(name, G.main->name);
// open the file
// and create a PackedFile structure
@@ -214,13 +215,20 @@ void packAll(Main *bmain, ReportList *reports)
Image *ima;
VFont *vf;
bSound *sound;
-
- for(ima=bmain->image.first; ima; ima=ima->id.next)
- if(ima->packedfile == NULL && ima->id.lib==NULL && ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE))
- ima->packedfile = newPackedFile(reports, ima->name);
+
+ for(ima=bmain->image.first; ima; ima=ima->id.next) {
+ if(ima->packedfile == NULL && ima->id.lib==NULL) {
+ if(ima->source==IMA_SRC_FILE) {
+ ima->packedfile = newPackedFile(reports, ima->name);
+ }
+ else if(ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported.", ima->id.name+2);
+ }
+ }
+ }
for(vf=bmain->vfont.first; vf; vf=vf->id.next)
- if(vf->packedfile == NULL && vf->id.lib==NULL && strcmp(vf->name, "<builtin>") != 0)
+ if(vf->packedfile == NULL && vf->id.lib==NULL && strcmp(vf->name, FO_BUILTIN_NAME) != 0)
vf->packedfile = newPackedFile(reports, vf->name);
for(sound=bmain->sound.first; sound; sound=sound->id.next)
@@ -256,7 +264,7 @@ static char *find_new_name(char *name)
*/
-int writePackedFile(ReportList *reports, char *filename, PackedFile *pf, int guimode)
+int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, int guimode)
{
int file, number, remove_tmp = FALSE;
int ret_value = RET_OK;
@@ -267,7 +275,7 @@ int writePackedFile(ReportList *reports, char *filename, PackedFile *pf, int gui
if (guimode) {} //XXX waitcursor(1);
strcpy(name, filename);
- BLI_path_abs(name, G.sce);
+ BLI_path_abs(name, G.main->name);
if (BLI_exists(name)) {
for (number = 1; number <= 999; number++) {
@@ -324,7 +332,7 @@ PF_NOFILE - the original file doens't exist
*/
-int checkPackedFile(char *filename, PackedFile *pf)
+int checkPackedFile(const char *filename, PackedFile *pf)
{
struct stat st;
int ret_val, i, len, file;
@@ -332,7 +340,7 @@ int checkPackedFile(char *filename, PackedFile *pf)
char name[FILE_MAXDIR + FILE_MAXFILE];
strcpy(name, filename);
- BLI_path_abs(name, G.sce);
+ BLI_path_abs(name, G.main->name);
if (stat(name, &st)) {
ret_val = PF_NOFILE;
@@ -451,7 +459,7 @@ int unpackVFont(ReportList *reports, VFont *vfont, int how)
if (newname != NULL) {
ret_value = RET_OK;
freePackedFile(vfont->packedfile);
- vfont->packedfile = 0;
+ vfont->packedfile = NULL;
strcpy(vfont->name, newname);
MEM_freeN(newname);
}
@@ -460,7 +468,7 @@ int unpackVFont(ReportList *reports, VFont *vfont, int how)
return (ret_value);
}
-int unpackSound(ReportList *reports, bSound *sound, int how)
+int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
{
char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
char *newname;
@@ -477,9 +485,9 @@ int unpackSound(ReportList *reports, bSound *sound, int how)
MEM_freeN(newname);
freePackedFile(sound->packedfile);
- sound->packedfile = 0;
+ sound->packedfile = NULL;
- sound_load(NULL, sound);
+ sound_load(bmain, sound);
ret_value = RET_OK;
}
@@ -529,6 +537,6 @@ void unpackAll(Main *bmain, ReportList *reports, int how)
for(sound=bmain->sound.first; sound; sound=sound->id.next)
if(sound->packedfile)
- unpackSound(reports, sound, how);
+ unpackSound(bmain, reports, sound, how);
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index ffb99c10c40..e53888127f2 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1,4 +1,6 @@
/*
+ * $Id$
+ *
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -23,7 +25,7 @@
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
- */
+ */
#include "DNA_object_types.h"
@@ -31,6 +33,9 @@
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
+#include "BLI_utildefines.h"
+
+
#include "BKE_brush.h"
#include "BKE_library.h"
#include "BKE_paint.h"
@@ -100,7 +105,7 @@ void paint_init(Paint *p, const char col[3])
p->flags |= PAINT_SHOW_BRUSH;
}
-void free_paint(Paint *paint)
+void free_paint(Paint *UNUSED(paint))
{
/* nothing */
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index dbc598071f9..4b3b30e6cd2 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -46,6 +46,8 @@
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BLI_kdtree.h"
#include "BLI_rand.h"
#include "BLI_threads.h"
@@ -62,7 +64,7 @@
#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_lattice.h"
-#include "BKE_utildefines.h"
+
#include "BKE_displist.h"
#include "BKE_particle.h"
#include "BKE_object.h"
@@ -77,8 +79,6 @@
#include "RE_render_ext.h"
-static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index,
- float *fuv, float *orco, ParticleTexture *ptex, int event);
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
static void do_child_modifiers(ParticleSimulationData *sim,
@@ -159,21 +159,21 @@ static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *buf
ParticleSystem *psys_get_current(Object *ob)
{
ParticleSystem *psys;
- if(ob==0) return 0;
+ if(ob==NULL) return NULL;
for(psys=ob->particlesystem.first; psys; psys=psys->next){
if(psys->flag & PSYS_CURRENT)
return psys;
}
- return 0;
+ return NULL;
}
short psys_get_current_num(Object *ob)
{
ParticleSystem *psys;
short i;
- if(ob==0) return 0;
+ if(ob==NULL) return 0;
for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++)
if(psys->flag & PSYS_CURRENT)
@@ -186,7 +186,7 @@ void psys_set_current_num(Object *ob, int index)
ParticleSystem *psys;
short i;
- if(ob==0) return;
+ if(ob==NULL) return;
for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) {
if(i == index)
@@ -197,7 +197,7 @@ void psys_set_current_num(Object *ob, int index)
}
Object *psys_find_object(Scene *scene, ParticleSystem *psys)
{
- Base *base = scene->base.first;
+ Base *base;
ParticleSystem *tpsys;
for(base = scene->base.first; base; base = base->next) {
@@ -211,7 +211,7 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys)
}
Object *psys_get_lattice(ParticleSimulationData *sim)
{
- Object *lattice=0;
+ Object *lattice=NULL;
if(psys_in_edit_mode(sim->scene, sim->psys)==0){
@@ -225,7 +225,7 @@ Object *psys_get_lattice(ParticleSimulationData *sim)
}
}
if(lattice)
- init_latt_deform(lattice,0);
+ init_latt_deform(lattice, NULL);
}
return lattice;
@@ -273,7 +273,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
}
psmd= psys_get_modifier(ob, psys);
- if(psys->renderdata) {
+ if(psys->renderdata || G.rendering) {
if(!(psmd->modifier.mode & eModifierMode_Render))
return 0;
}
@@ -360,7 +360,7 @@ int psys_uses_gravity(ParticleSimulationData *sim)
/************************************************/
/* Freeing stuff */
/************************************************/
-void fluid_free_settings(SPHFluidSettings *fluid)
+static void fluid_free_settings(SPHFluidSettings *fluid)
{
if(fluid)
MEM_freeN(fluid);
@@ -368,6 +368,8 @@ void fluid_free_settings(SPHFluidSettings *fluid)
void psys_free_settings(ParticleSettings *part)
{
+ MTex *mtex;
+ int a;
BKE_free_animdata(&part->id);
free_partdeflect(part->pd);
free_partdeflect(part->pd2);
@@ -379,15 +381,18 @@ void psys_free_settings(ParticleSettings *part)
boid_free_settings(part->boids);
fluid_free_settings(part->fluid);
+
+ for(a=0; a<MAX_MTEX; a++) {
+ mtex= part->mtex[a];
+ if(mtex && mtex->tex) mtex->tex->id.us--;
+ if(mtex) MEM_freeN(mtex);
+ }
}
-void free_hair(Object *ob, ParticleSystem *psys, int dynamics)
+void free_hair(Object *UNUSED(ob), ParticleSystem *psys, int dynamics)
{
PARTICLE_P;
- if(psys->part->type != PART_HAIR)
- return;
-
LOOP_PARTICLES {
if(pa->hair)
MEM_freeN(pa->hair);
@@ -406,9 +411,10 @@ void free_hair(Object *ob, ParticleSystem *psys, int dynamics)
modifier_free((ModifierData*)psys->clmd);
psys->clmd = NULL;
+ psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
}
else {
- cloth_free_modifier(ob, psys->clmd);
+ cloth_free_modifier(psys->clmd);
}
}
@@ -463,7 +469,7 @@ void psys_free_children(ParticleSystem *psys)
{
if(psys->child) {
MEM_freeN(psys->child);
- psys->child=0;
+ psys->child= NULL;
psys->totchild=0;
}
@@ -533,7 +539,7 @@ void psys_free(Object *ob, ParticleSystem * psys)
if(psys->child){
MEM_freeN(psys->child);
- psys->child = 0;
+ psys->child = NULL;
psys->totchild = 0;
}
@@ -554,7 +560,7 @@ void psys_free(Object *ob, ParticleSystem * psys)
if(psys->part){
psys->part->id.us--;
- psys->part=0;
+ psys->part=NULL;
}
BKE_ptcache_free_list(&psys->ptcaches);
@@ -563,6 +569,9 @@ void psys_free(Object *ob, ParticleSystem * psys)
BLI_freelistN(&psys->targets);
BLI_kdtree_free(psys->tree);
+
+ if(psys->fluid_springs)
+ MEM_freeN(psys->fluid_springs);
pdEndEffectors(&psys->effectors);
@@ -1000,6 +1009,8 @@ static float interpolate_particle_value(float v1, float v2, float v3, float v4,
value= w[0]*v1 + w[1]*v2 + w[2]*v3;
if(four)
value += w[3]*v4;
+
+ CLAMP(value, 0.f, 1.f);
return value;
}
@@ -1055,9 +1066,10 @@ typedef struct ParticleInterpolationData {
} ParticleInterpolationData;
/* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */
/* It uses ParticleInterpolationData->pm to store the current memory cache frame so it's thread safe. */
-static void get_pointcache_keys_for_time(Object *ob, PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2)
+static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2)
{
static PTCacheMem *pm = NULL;
+ int index1, index2;
if(index < 0) { /* initialize */
*cur = cache->mem_cache.first;
@@ -1072,15 +1084,19 @@ static void get_pointcache_keys_for_time(Object *ob, PointCache *cache, PTCacheM
pm = *cur;
- BKE_ptcache_make_particle_key(key2, pm->index_array ? pm->index_array[index] - 1 : index, pm->data, (float)pm->frame);
- if(pm->prev->index_array && pm->prev->index_array[index] == 0)
+ index2 = BKE_ptcache_mem_index_find(pm, index);
+ index1 = BKE_ptcache_mem_index_find(pm->prev, index);
+
+ BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
+ if(index1 < 0)
copy_particle_key(key1, key2, 1);
else
- BKE_ptcache_make_particle_key(key1, pm->prev->index_array ? pm->prev->index_array[index] - 1 : index, pm->prev->data, (float)pm->prev->frame);
+ BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, (float)pm->prev->frame);
}
else if(cache->mem_cache.first) {
pm = cache->mem_cache.first;
- BKE_ptcache_make_particle_key(key2, pm->index_array ? pm->index_array[index] - 1 : index, pm->data, (float)pm->frame);
+ index2 = BKE_ptcache_mem_index_find(pm, index);
+ BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
copy_particle_key(key1, key2, 1);
}
}
@@ -1091,14 +1107,7 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float
int ret = 0;
for(pm=cache->mem_cache.first; pm; pm=pm->next) {
- if(pm->index_array) {
- if(pm->index_array[index]) {
- *start = pm->frame;
- ret++;
- break;
- }
- }
- else {
+ if(BKE_ptcache_mem_index_find(pm, index) >= 0) {
*start = pm->frame;
ret++;
break;
@@ -1106,14 +1115,7 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float
}
for(pm=cache->mem_cache.last; pm; pm=pm->prev) {
- if(pm->index_array) {
- if(pm->index_array[index]) {
- *end = pm->frame;
- ret++;
- break;
- }
- }
- else {
+ if(BKE_ptcache_mem_index_find(pm, index) >= 0) {
*end = pm->frame;
ret++;
break;
@@ -1128,13 +1130,8 @@ float psys_get_dietime_from_cache(PointCache *cache, int index) {
int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */
for(pm=cache->mem_cache.last; pm; pm=pm->prev) {
- if(pm->index_array) {
- if(pm->index_array[index])
- return (float)pm->frame;
- }
- else {
+ if(BKE_ptcache_mem_index_find(pm, index) >= 0)
return (float)pm->frame;
- }
}
return (float)dietime;
@@ -1161,7 +1158,7 @@ static void init_particle_interpolation(Object *ob, ParticleSystem *psys, Partic
pind->dietime = (key + pa->totkey - 1)->time;
}
else if(pind->cache) {
- float start, end;
+ float start=0.0f, end=0.0f;
get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL);
pind->birthtime = pa ? pa->time : pind->cache->startframe;
pind->dietime = pa ? pa->dietime : pind->cache->endframe;
@@ -1205,12 +1202,12 @@ static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey)
key->time = hkey->time;
}
-static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, float frs_sec, ParticleInterpolationData *pind, ParticleKey *result)
+static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, ParticleInterpolationData *pind, ParticleKey *result)
{
PTCacheEditPoint *point = pind->epoint;
ParticleKey keys[4];
int point_vel = (point && point->keys->vel);
- float real_t, dfra, keytime;
+ float real_t, dfra, keytime, invdt;
/* billboards wont fill in all of these, so start cleared */
memset(keys, 0, sizeof(keys));
@@ -1349,11 +1346,12 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData
dfra = keys[2].time - keys[1].time;
keytime = (real_t - keys[1].time) / dfra;
+ invdt = dfra * 0.04f * psys->part->timetweak;
/* convert velocity to timestep size */
if(pind->keyed || pind->cache || point_vel){
- mul_v3_fl(keys[1].vel, dfra / frs_sec);
- mul_v3_fl(keys[2].vel, dfra / frs_sec);
+ mul_v3_fl(keys[1].vel, invdt);
+ mul_v3_fl(keys[2].vel, invdt);
interp_qt_qtqt(result->rot,keys[1].rot,keys[2].rot,keytime);
}
@@ -1364,7 +1362,7 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData
/* the velocity needs to be converted back from cubic interpolation */
if(pind->keyed || pind->cache || point_vel)
- mul_v3_fl(result->vel, frs_sec / dfra);
+ mul_v3_fl(result->vel, 1.f/invdt);
}
/************************************************/
/* Particles on a dm */
@@ -1480,7 +1478,7 @@ void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*or
}
else {
VECCOPY(orco, vec);
- if(ornor)
+ if(ornor && nor)
VECCOPY(ornor, nor);
}
}
@@ -1650,7 +1648,7 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, float *
return DMCACHE_NOTFOUND;
}
-static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, int *mapindex, float *mapfw)
+static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float UNUSED(foffset), int *mapindex, float *mapfw)
{
if(index < 0)
return 0;
@@ -1806,7 +1804,7 @@ ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys)
/* Particles on a shape */
/************************************************/
/* ready for future use */
-static void psys_particle_on_shape(int distr, int index, float *fuv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor)
+static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), float *UNUSED(fuv), float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor)
{
/* TODO */
float zerovec[3]={0.0f,0.0f,0.0f};
@@ -1835,9 +1833,11 @@ static void psys_particle_on_shape(int distr, int index, float *fuv, float *vec,
void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor){
if(psmd){
if(psmd->psys->part->distr==PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT){
- if(vec){
- VECCOPY(vec,fuv);
- }
+ if(vec)
+ copy_v3_v3(vec,fuv);
+
+ if(orco)
+ copy_v3_v3(orco, fuv);
return;
}
/* we cant use the num_dmcache */
@@ -1865,144 +1865,186 @@ static float vert_weight(MDeformVert *dvert, int group)
return 0.0;
}
-static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, short type, short axis, float obmat[][4])
+static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, float flat, short type, short axis, float obmat[][4], int smooth_start)
{
- float vec[3]={0.0,0.0,0.0}, q1[4]={1,0,0,0},q2[4];
- float t;
+ float kink[3]={1.f,0.f,0.f}, par_vec[3], q1[4]={1.f,0.f,0.f,0.f};
+ float t, dt=1.f, result[3];
- CLAMP(time,0.0,1.0);
+ if(par == NULL || type == PART_KINK_NO)
+ return;
+
+ CLAMP(time, 0.f, 1.f);
if(shape!=0.0f && type!=PART_KINK_BRAID) {
if(shape<0.0f)
- time= (float)pow(time, 1.0+shape);
+ time= (float)pow(time, 1.f+shape);
else
- time= (float)pow(time, 1.0/(1.0-shape));
+ time= (float)pow(time, 1.f/(1.f-shape));
}
- t=time;
+ t = time * freq *(float)M_PI;
+
+ if(smooth_start) {
+ dt = fabs(t);
+ /* smooth the beginning of kink */
+ CLAMP(dt, 0.f, (float)M_PI);
+ dt = sin(dt/2.f);
+ }
- t*=(float)M_PI*freq;
+ if(type != PART_KINK_RADIAL) {
+ float temp[3];
- if(par==0) return;
+ kink[axis]=1.f;
- switch(type){
- case PART_KINK_CURL:
- vec[axis]=1.0;
- if(par_rot)
- QUATCOPY(q2,par_rot)
- else
- vec_to_quat( q2,par->vel,axis,(axis+1)%3);
- mul_qt_v3(q2,vec);
- mul_v3_fl(vec,amplitude);
- VECADD(state->co,state->co,vec);
+ if(obmat)
+ mul_mat3_m4_v3(obmat, kink);
+
+ if(par_rot)
+ mul_qt_v3(par_rot, kink);
- VECSUB(vec,state->co,par->co);
+ /* make sure kink is normal to strand */
+ project_v3_v3v3(temp, kink, par->vel);
+ sub_v3_v3(kink, temp);
+ normalize_v3(kink);
+ }
- if(t!=0.0)
- axis_angle_to_quat(q1,par->vel,t);
-
- mul_qt_v3(q1,vec);
-
- VECADD(state->co,par->co,vec);
- break;
- case PART_KINK_RADIAL:
- VECSUB(vec,state->co,par->co);
+ copy_v3_v3(result, state->co);
+ sub_v3_v3v3(par_vec, par->co, state->co);
- normalize_v3(vec);
- mul_v3_fl(vec,amplitude*(float)sin(t));
+ switch(type) {
+ case PART_KINK_CURL:
+ {
+ mul_v3_fl(par_vec, -1.f);
- VECADD(state->co,state->co,vec);
- break;
- case PART_KINK_WAVE:
- vec[axis]=1.0;
- if(obmat)
- mul_mat3_m4_v3(obmat,vec);
+ if(flat > 0.f) {
+ float proj[3];
+ project_v3_v3v3(proj, par_vec, par->vel);
+ madd_v3_v3fl(par_vec, proj, -flat);
- if(par_rot)
- mul_qt_v3(par_rot,vec);
+ project_v3_v3v3(proj, par_vec, kink);
+ madd_v3_v3fl(par_vec, proj, -flat);
+ }
- project_v3_v3v3(q1,vec,par->vel);
-
- VECSUB(vec,vec,q1);
- normalize_v3(vec);
+ axis_angle_to_quat(q1, kink, (float)M_PI/2.f);
- mul_v3_fl(vec,amplitude*(float)sin(t));
+ mul_qt_v3(q1, par_vec);
- VECADD(state->co,state->co,vec);
- break;
- case PART_KINK_BRAID:
- if(par){
- float y_vec[3]={0.0,1.0,0.0};
- float z_vec[3]={0.0,0.0,1.0};
- float vec_from_par[3], vec_one[3], radius, state_co[3];
- float inp_y,inp_z,length;
-
- if(par_rot)
- QUATCOPY(q2,par_rot)
- else
- vec_to_quat(q2,par->vel,axis,(axis+1)%3);
- mul_qt_v3(q2,y_vec);
- mul_qt_v3(q2,z_vec);
-
- VECSUB(vec_from_par,state->co,par->co);
- radius= normalize_v3_v3(vec_one, vec_from_par);
+ madd_v3_v3fl(par_vec, kink, amplitude);
- inp_y=dot_v3v3(y_vec,vec_one);
- inp_z=dot_v3v3(z_vec,vec_one);
+ /* rotate kink vector around strand tangent */
+ if(t!=0.f) {
+ axis_angle_to_quat(q1, par->vel, t);
+ mul_qt_v3(q1, par_vec);
+ }
- if(inp_y>0.5){
- VECCOPY(state_co,y_vec);
+ add_v3_v3v3(result, par->co, par_vec);
+ break;
+ }
+ case PART_KINK_RADIAL:
+ {
+ if(flat > 0.f) {
+ float proj[3];
+ /* flatten along strand */
+ project_v3_v3v3(proj, par_vec, par->vel);
+ madd_v3_v3fl(result, proj, flat);
+ }
- mul_v3_fl(y_vec,amplitude*(float)cos(t));
- mul_v3_fl(z_vec,amplitude/2.0f*(float)sin(2.0f*t));
- }
- else if(inp_z>0.0){
- VECCOPY(state_co,z_vec);
- mul_v3_fl(state_co,(float)sin(M_PI/3.0f));
- VECADDFAC(state_co,state_co,y_vec,-0.5f);
+ madd_v3_v3fl(result, par_vec, -amplitude*(float)sin(t));
+ break;
+ }
+ case PART_KINK_WAVE:
+ {
+ madd_v3_v3fl(result, kink, amplitude*(float)sin(t));
- mul_v3_fl(y_vec,-amplitude*(float)cos(t + M_PI/3.0f));
- mul_v3_fl(z_vec,amplitude/2.0f*(float)cos(2.0f*t + M_PI/6.0f));
- }
- else{
- VECCOPY(state_co,z_vec);
- mul_v3_fl(state_co,-(float)sin(M_PI/3.0f));
- VECADDFAC(state_co,state_co,y_vec,-0.5f);
+ if(flat > 0.f) {
+ float proj[3];
+ /* flatten along wave */
+ project_v3_v3v3(proj, par_vec, kink);
+ madd_v3_v3fl(result, proj, flat);
- mul_v3_fl(y_vec,amplitude*(float)-sin(t+M_PI/6.0f));
- mul_v3_fl(z_vec,amplitude/2.0f*(float)-sin(2.0f*t+M_PI/3.0f));
- }
+ /* flatten along strand */
+ project_v3_v3v3(proj, par_vec, par->vel);
+ madd_v3_v3fl(result, proj, flat);
+ }
+ break;
+ }
+ case PART_KINK_BRAID:
+ {
+ float y_vec[3]={0.f,1.f,0.f};
+ float z_vec[3]={0.f,0.f,1.f};
+ float vec_one[3], state_co[3];
+ float inp_y, inp_z, length;
+
+ if(par_rot) {
+ mul_qt_v3(par_rot, y_vec);
+ mul_qt_v3(par_rot, z_vec);
+ }
+
+ mul_v3_fl(par_vec, -1.f);
+ normalize_v3_v3(vec_one, par_vec);
- mul_v3_fl(state_co,amplitude);
- VECADD(state_co,state_co,par->co);
- VECSUB(vec_from_par,state->co,state_co);
+ inp_y=dot_v3v3(y_vec, vec_one);
+ inp_z=dot_v3v3(z_vec, vec_one);
- length=normalize_v3(vec_from_par);
- mul_v3_fl(vec_from_par,MIN2(length,amplitude/2.0f));
+ if(inp_y>0.5){
+ copy_v3_v3(state_co, y_vec);
- VECADD(state_co,par->co,y_vec);
- VECADD(state_co,state_co,z_vec);
- VECADD(state_co,state_co,vec_from_par);
+ mul_v3_fl(y_vec, amplitude*(float)cos(t));
+ mul_v3_fl(z_vec, amplitude/2.f*(float)sin(2.f*t));
+ }
+ else if(inp_z>0.0){
+ mul_v3_v3fl(state_co, z_vec, (float)sin(M_PI/3.f));
+ VECADDFAC(state_co,state_co,y_vec,-0.5f);
- shape=(2.0f*(float)M_PI)*(1.0f+shape);
+ mul_v3_fl(y_vec, -amplitude * (float)cos(t + M_PI/3.f));
+ mul_v3_fl(z_vec, amplitude/2.f * (float)cos(2.f*t + M_PI/6.f));
+ }
+ else{
+ mul_v3_v3fl(state_co, z_vec, -(float)sin(M_PI/3.f));
+ madd_v3_v3fl(state_co, y_vec, -0.5f);
- if(t<shape){
- shape=t/shape;
- shape=(float)sqrt((double)shape);
- interp_v3_v3v3(state->co,state->co,state_co,shape);
- }
- else{
- VECCOPY(state->co,state_co);
- }
- }
- break;
+ mul_v3_fl(y_vec, amplitude * (float)-sin(t + M_PI/6.f));
+ mul_v3_fl(z_vec, amplitude/2.f * (float)-sin(2.f*t + M_PI/3.f));
+ }
+
+ mul_v3_fl(state_co, amplitude);
+ add_v3_v3(state_co, par->co);
+ sub_v3_v3v3(par_vec, state->co, state_co);
+
+ length = normalize_v3(par_vec);
+ mul_v3_fl(par_vec, MIN2(length, amplitude/2.f));
+
+ add_v3_v3v3(state_co, par->co, y_vec);
+ add_v3_v3(state_co, z_vec);
+ add_v3_v3(state_co, par_vec);
+
+ shape = 2.f*(float)M_PI * (1.f+shape);
+
+ if(t<shape){
+ shape = t/shape;
+ shape = (float)sqrt((double)shape);
+ interp_v3_v3v3(result, result, state_co, shape);
+ }
+ else{
+ copy_v3_v3(result, state_co);
+ }
+ break;
+ }
}
+
+ /* blend the start of the kink */
+ if(dt < 1.f)
+ interp_v3_v3v3(state->co, state->co, result, dt);
+ else
+ copy_v3_v3(state->co, result);
}
-static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clumpfac, float clumppow, float pa_clump)
+static float do_clump(ParticleKey *state, ParticleKey *par, float time, float clumpfac, float clumppow, float pa_clump)
{
+ float clump = 0.f;
+
if(par && clumpfac!=0.0){
- float clump, cpow;
+ float cpow;
if(clumppow<0.0)
cpow=1.0f+clumppow;
@@ -2013,8 +2055,11 @@ static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clu
clump = -clumpfac*pa_clump*(float)pow(1.0-(double)time,(double)cpow);
else
clump = clumpfac*pa_clump*(float)pow((double)time,(double)cpow);
+
interp_v3_v3v3(state->co,state->co,par->co,clump);
}
+
+ return clump;
}
void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
{
@@ -2127,7 +2172,7 @@ int do_guides(ListBase *effectors, ParticleKey *state, int index, float time)
}
par.co[0] = par.co[1] = par.co[2] = 0.0f;
VECCOPY(key.co, vec_to_point);
- do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0);
+ do_kink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, 0.f, pd->kink, pd->kink_axis, 0, 0);
do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f);
VECCOPY(vec_to_point, key.co);
@@ -2188,7 +2233,7 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float
VECADDFAC(state->co,state->co,mat[0],rough[0]);
VECADDFAC(state->co,state->co,mat[1],rough[1]);
}
-static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec)
+static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *UNUSED(rootco), float effector, float UNUSED(dfra), float UNUSED(cfra), float *length, float *vec)
{
float force[3] = {0.0f,0.0f,0.0f};
ParticleKey eff_key;
@@ -2211,12 +2256,13 @@ static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheK
normalize_v3(force);
- VECADDFAC(ca->co, (ca-1)->co, force, *length);
-
- if(k < steps) {
+ if(k < steps)
sub_v3_v3v3(vec, (ca+1)->co, ca->co);
+
+ madd_v3_v3v3fl(ca->co, (ca-1)->co, force, *length);
+
+ if(k < steps)
*length = len_v3(vec);
- }
}
static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec)
{
@@ -2232,20 +2278,23 @@ static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *st
return k;
}
}
-static void offset_child(ChildParticle *cpa, ParticleKey *par, ParticleKey *child, float flat, float radius)
+static void offset_child(ChildParticle *cpa, ParticleKey *par, float *par_rot, ParticleKey *child, float flat, float radius)
{
- VECCOPY(child->co,cpa->fuv);
- mul_v3_fl(child->co,radius);
+ copy_v3_v3(child->co, cpa->fuv);
+ mul_v3_fl(child->co, radius);
child->co[0]*=flat;
- VECCOPY(child->vel,par->vel);
-
- mul_qt_v3(par->rot,child->co);
+ copy_v3_v3(child->vel, par->vel);
- QUATCOPY(child->rot,par->rot);
+ if(par_rot) {
+ mul_qt_v3(par_rot, child->co);
+ copy_qt_qt(child->rot, par_rot);
+ }
+ else
+ unit_qt(child->rot);
- VECADD(child->co,child->co,par->co);
+ add_v3_v3(child->co, par->co);
}
float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup)
{
@@ -2375,12 +2424,9 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
if(totchild==0) return 0;
/* init random number generator */
- if(ctx->sim.psys->part->flag & PART_ANIM_BRANCHING)
- seed= 31415926 + ctx->sim.psys->seed + (int)cfra;
- else
- seed= 31415926 + ctx->sim.psys->seed;
+ seed= 31415926 + ctx->sim.psys->seed;
- if(part->flag & PART_BRANCHING || ctx->editupdate || totchild < 10000)
+ if(ctx->editupdate || totchild < 10000)
totthread= 1;
for(i=0; i<totthread; i++) {
@@ -2423,7 +2469,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
}
/* note: this function must be thread safe, except for branching! */
-static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i)
+static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
{
ParticleThreadContext *ctx= thread->ctx;
Object *ob= ctx->sim.ob;
@@ -2431,44 +2477,29 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
ParticleSettings *part = psys->part;
ParticleCacheKey **cache= psys->childcache;
ParticleCacheKey **pcache= psys_in_edit_mode(ctx->sim.scene, psys) ? psys->edit->pathcache : psys->pathcache;
- ParticleCacheKey *state, *par = NULL, *key[4];
- ParticleData *pa=NULL;
+ ParticleCacheKey *child, *par = NULL, *key[4];
ParticleTexture ptex;
- float *cpa_fuv=0, *par_rot=0;
- float co[3], orco[3], ornor[3], hairmat[4][4], t, cpa_1st[3], dvec[3];
- float branch_begin, branch_end, branch_prob, rough_rand;
+ float *cpa_fuv=0, *par_rot=0, rot[4];
+ float orco[3], ornor[3], hairmat[4][4], t, dvec[3], off1[4][3], off2[4][3];
float length, max_length = 1.0f, cur_length = 0.0f;
- float eff_length, eff_vec[3];
+ float eff_length, eff_vec[3], weight[4];
int k, cpa_num;
short cpa_from;
if(!pcache)
return;
- if(part->flag & PART_BRANCHING) {
- branch_begin=rng_getFloat(thread->rng_path);
- branch_end=branch_begin+(1.0f-branch_begin)*rng_getFloat(thread->rng_path);
- branch_prob=rng_getFloat(thread->rng_path);
- rough_rand=rng_getFloat(thread->rng_path);
- }
- else {
- branch_begin= 0.0f;
- branch_end= 0.0f;
- branch_prob= 0.0f;
- rough_rand= 0.0f;
- }
-
- if(i<psys->totpart){
- branch_begin=0.0f;
- branch_end=1.0f;
- branch_prob=0.0f;
- }
-
if(ctx->between){
+ ParticleData *pa = psys->particles + cpa->pa[0];
int w, needupdate;
- float foffset;
-
- if(ctx->editupdate && !(part->flag & PART_BRANCHING)) {
+ float foffset, wsum=0.f;
+ float co[3];
+ float p_min = part->parting_min;
+ float p_max = part->parting_max;
+ /* Virtual parents don't work nicely with parting. */
+ float p_fac = part->parents > 0.f ? 0.f : part->parting_fac;
+
+ if(ctx->editupdate) {
needupdate= 0;
w= 0;
while(w<4 && cpa->pa[w]>=0) {
@@ -2482,223 +2513,223 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
if(!needupdate)
return;
else
- memset(keys, 0, sizeof(*keys)*(ctx->steps+1));
+ memset(child_keys, 0, sizeof(*child_keys)*(ctx->steps+1));
}
/* get parent paths */
- w= 0;
- while(w<4 && cpa->pa[w]>=0){
- key[w] = pcache[cpa->pa[w]];
- w++;
+ for(w=0; w<4; w++) {
+ if(cpa->pa[w] >= 0) {
+ key[w] = pcache[cpa->pa[w]];
+ weight[w] = cpa->w[w];
+ }
+ else {
+ key[w] = pcache[0];
+ weight[w] = 0.f;
+ }
+ }
+
+ /* modify weights to create parting */
+ if(p_fac > 0.f) {
+ for(w=0; w<4; w++) {
+ if(w && weight[w] > 0.f) {
+ float d;
+ if(part->flag & PART_CHILD_LONG_HAIR) {
+ /* For long hair use tip distance/root distance as parting factor instead of root to tip angle. */
+ float d1 = len_v3v3(key[0]->co, key[w]->co);
+ float d2 = len_v3v3((key[0]+key[0]->steps-1)->co, (key[w]+key[w]->steps-1)->co);
+
+ d = d1 > 0.f ? d2/d1 - 1.f : 10000.f;
+ }
+ else {
+ float v1[3], v2[3];
+ sub_v3_v3v3(v1, (key[0]+key[0]->steps-1)->co, key[0]->co);
+ sub_v3_v3v3(v2, (key[w]+key[w]->steps-1)->co, key[w]->co);
+ normalize_v3(v1);
+ normalize_v3(v2);
+
+ d = saacos(dot_v3v3(v1, v2)) * 180.f / M_PI;
+ }
+
+ if(p_max > p_min)
+ d = (d - p_min)/(p_max - p_min);
+ else
+ d = (d - p_min) <= 0.f ? 0.f : 1.f;
+
+ CLAMP(d, 0.f, 1.f);
+
+ if(d > 0.f)
+ weight[w] *= (1.f - d);
+ }
+ wsum += weight[w];
+ }
+ for(w=0; w<4; w++)
+ weight[w] /= wsum;
+
+ interp_v4_v4v4(weight, cpa->w, weight, p_fac);
}
/* get the original coordinates (orco) for texture usage */
cpa_num = cpa->num;
- foffset= cpa->foffset;
+ foffset = cpa->foffset;
cpa_fuv = cpa->fuv;
cpa_from = PART_FROM_FACE;
psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0);
- if(part->path_start==0.0f) {
- /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
- VECCOPY(cpa_1st,co);
- mul_m4_v3(ob->obmat,cpa_1st);
- }
+ mul_m4_v3(ob->obmat, co);
- pa = psys->particles + cpa->pa[0];
+ for(w=0; w<4; w++)
+ sub_v3_v3v3(off1[w], co, key[w]->co);
psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
-
- pa=0;
}
else{
- if(ctx->editupdate && !(part->flag & PART_BRANCHING)) {
+ ParticleData *pa = psys->particles + cpa->parent;
+ float co[3];
+ if(ctx->editupdate) {
if(!(psys->edit->points[cpa->parent].flag & PEP_EDIT_RECALC))
return;
- memset(keys, 0, sizeof(*keys)*(ctx->steps+1));
+ memset(child_keys, 0, sizeof(*child_keys)*(ctx->steps+1));
}
/* get the parent path */
- key[0]=pcache[cpa->parent];
+ key[0] = pcache[cpa->parent];
/* get the original coordinates (orco) for texture usage */
- pa=psys->particles+cpa->parent;
-
- cpa_from=part->from;
- cpa_num=pa->num;
- cpa_fuv=pa->fuv;
+ cpa_from = part->from;
+ cpa_num = pa->num;
+ cpa_fuv = pa->fuv;
psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0);
psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
}
- keys->steps = ctx->steps;
-
- /* correct child ipo timing */
-#if 0 // XXX old animation system
- if((part->flag&PART_ABS_TIME)==0 && part->ipo){
- float dsta=part->end-part->sta;
- calc_ipo(part->ipo, 100.0f*(ctx->cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0])));
- execute_ipo((ID *)part, part->ipo);
- }
-#endif // XXX old animation system
+ child_keys->steps = ctx->steps;
/* get different child parameters from textures & vgroups */
get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
if(ptex.exist < PSYS_FRAND(i + 24)) {
- keys->steps = -1;
+ child_keys->steps = -1;
return;
}
/* create the child path */
- for(k=0,state=keys; k<=ctx->steps; k++,state++){
+ for(k=0,child=child_keys; k<=ctx->steps; k++,child++){
if(ctx->between){
int w=0;
- state->co[0] = state->co[1] = state->co[2] = 0.0f;
- state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
- state->rot[0] = state->rot[1] = state->rot[2] = state->rot[3] = 0.0f;
+ zero_v3(child->co);
+ zero_v3(child->vel);
+ unit_qt(child->rot);
- //QUATCOPY(state->rot,key[0]->rot);
+ for(w=0; w<4; w++) {
+ copy_v3_v3(off2[w], off1[w]);
- /* child position is the weighted sum of parent positions */
- while(w<4 && cpa->pa[w]>=0){
- state->co[0] += cpa->w[w] * key[w]->co[0];
- state->co[1] += cpa->w[w] * key[w]->co[1];
- state->co[2] += cpa->w[w] * key[w]->co[2];
-
- state->vel[0] += cpa->w[w] * key[w]->vel[0];
- state->vel[1] += cpa->w[w] * key[w]->vel[1];
- state->vel[2] += cpa->w[w] * key[w]->vel[2];
- key[w]++;
- w++;
- }
- if(part->path_start==0.0f) {
- if(k==0){
- /* calculate the offset between actual child root position and first position interpolated from parents */
- VECSUB(cpa_1st,cpa_1st,state->co);
+ if(part->flag & PART_CHILD_LONG_HAIR) {
+ /* Use parent rotation (in addition to emission location) to determine child offset. */
+ if(k)
+ mul_qt_v3((key[w]+k)->rot, off2[w]);
+
+ /* Fade the effect of rotation for even lengths in the end */
+ project_v3_v3v3(dvec, off2[w], (key[w]+k)->vel);
+ madd_v3_v3fl(off2[w], dvec, -(float)k/(float)ctx->steps);
}
- /* apply offset for correct positioning */
- VECADD(state->co,state->co,cpa_1st);
+
+ add_v3_v3(off2[w], (key[w]+k)->co);
}
+
+ /* child position is the weighted sum of parent positions */
+ interp_v3_v3v3v3v3(child->co, off2[0], off2[1], off2[2], off2[3], weight);
+ interp_v3_v3v3v3v3(child->vel, (key[0]+k)->vel, (key[1]+k)->vel, (key[2]+k)->vel, (key[3]+k)->vel, weight);
+
+ copy_qt_qt(child->rot, (key[0]+k)->rot);
}
else{
+ if(k) {
+ mul_qt_qtqt(rot, (key[0]+k)->rot, key[0]->rot);
+ par_rot = rot;
+ }
+ else {
+ par_rot = key[0]->rot;
+ }
/* offset the child from the parent position */
- offset_child(cpa, (ParticleKey*)key[0], (ParticleKey*)state, part->childflat, part->childrad);
-
- key[0]++;
+ offset_child(cpa, (ParticleKey*)(key[0]+k), par_rot, (ParticleKey*)child, part->childflat, part->childrad);
}
}
/* apply effectors */
if(part->flag & PART_CHILD_EFFECT) {
- for(k=0,state=keys; k<=ctx->steps; k++,state++) {
+ for(k=0,child=child_keys; k<=ctx->steps; k++,child++) {
if(k) {
- do_path_effectors(&ctx->sim, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
+ do_path_effectors(&ctx->sim, cpa->pa[0], child, k, ctx->steps, child_keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
}
else {
- sub_v3_v3v3(eff_vec,(state+1)->co,state->co);
- eff_length= len_v3(eff_vec);
+ sub_v3_v3v3(eff_vec, (child+1)->co, child->co);
+ eff_length = len_v3(eff_vec);
}
}
}
- for(k=0,state=keys; k<=ctx->steps; k++,state++){
- t=(float)k/(float)ctx->steps;
+ for(k=0,child=child_keys; k<=ctx->steps; k++,child++){
+ t = (float)k/(float)ctx->steps;
+
+ if(ctx->totparent)
+ /* this is now threadsafe, virtual parents are calculated before rest of children */
+ par = (i >= ctx->totparent) ? cache[cpa->parent] : NULL;
+ else if(cpa->parent >= 0)
+ par = pcache[cpa->parent];
- if(ctx->totparent){
- if(i>=ctx->totparent) {
- /* this is now threadsafe, virtual parents are calculated before rest of children */
- par = cache[cpa->parent] + k;
+ if(par) {
+ if(k) {
+ mul_qt_qtqt(rot, (par+k)->rot, par->rot);
+ par_rot = rot;
}
- else
- par=0;
- }
- else if(cpa->parent>=0){
- par=pcache[cpa->parent]+k;
- par_rot = par->rot;
+ else {
+ par_rot = par->rot;
+ }
+ par += k;
}
/* apply different deformations to the child path */
- do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t);
-
- /* TODO: better branching */
- //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING)
- // rough_t = t * rough_rand;
- //else
- // rough_t = t;
-
- /* TODO: better branching */
- //if(part->flag & PART_BRANCHING && ctx->between==0){
- // if(branch_prob > part->branch_thres){
- // branchfac=0.0f;
- // }
- // else{
- // if(part->flag & PART_SYMM_BRANCHING){
- // if(t < branch_begin || t > branch_end)
- // branchfac=0.0f;
- // else{
- // if((t-branch_begin)/(branch_end-branch_begin)<0.5)
- // branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin);
- // else
- // branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin);
-
- // CLAMP(branchfac,0.0f,1.0f);
- // }
- // }
- // else{
- // if(t < branch_begin){
- // branchfac=0.0f;
- // }
- // else{
- // branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f);
- // CLAMP(branchfac,0.0f,1.0f);
- // }
- // }
- // }
-
- // if(i<psys->totpart)
- // interp_v3_v3v3(state->co, (pcache[i] + k)->co, state->co, branchfac);
- // else
- // /* this is not threadsafe, but should only happen for
- // * branching particles particles, which are not threaded */
- // interp_v3_v3v3(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac);
- //}
+ do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)child, t);
/* we have to correct velocity because of kink & clump */
if(k>1){
- VECSUB((state-1)->vel,state->co,(state-2)->co);
- mul_v3_fl((state-1)->vel,0.5);
+ sub_v3_v3v3((child-1)->vel, child->co, (child-2)->co);
+ mul_v3_fl((child-1)->vel, 0.5);
if(ctx->ma && (part->draw & PART_DRAW_MAT_COL))
- get_strand_normal(ctx->ma, ornor, cur_length, (state-1)->vel);
+ get_strand_normal(ctx->ma, ornor, cur_length, (child-1)->vel);
}
if(k == ctx->steps)
- VECSUB(state->vel,state->co,(state-1)->co);
+ sub_v3_v3v3(child->vel, child->co, (child-1)->co);
/* check if path needs to be cut before actual end of data points */
if(k){
- VECSUB(dvec,state->co,(state-1)->co);
- length=1.0f/(float)ctx->steps;
- k=check_path_length(k,keys,state,max_length,&cur_length,length,dvec);
+ sub_v3_v3v3(dvec, child->co, (child-1)->co);
+ length = 1.0f/(float)ctx->steps;
+ k = check_path_length(k, child_keys, child, max_length, &cur_length, length, dvec);
}
else{
/* initialize length calculation */
- max_length= ptex.length;
- cur_length= 0.0f;
+ max_length = ptex.length;
+ cur_length = 0.0f;
}
if(ctx->ma && (part->draw & PART_DRAW_MAT_COL)) {
- VECCOPY(state->col, &ctx->ma->r)
- get_strand_normal(ctx->ma, ornor, cur_length, state->vel);
+ VECCOPY(child->col, &ctx->ma->r)
+ get_strand_normal(ctx->ma, ornor, cur_length, child->vel);
}
}
+
+ /* Hide virtual parents */
+ if(i < ctx->totparent)
+ child_keys->steps = -1;
}
static void *exec_child_path_cache(void *data)
@@ -2724,10 +2755,8 @@ static void *exec_child_path_cache(void *data)
void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate)
{
- ParticleSettings *part = sim->psys->part;
ParticleThread *pthreads;
ParticleThreadContext *ctx;
- ParticleCacheKey **cache;
ListBase threads;
int i, totchild, totparent, totthread;
@@ -2745,8 +2774,8 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd
totchild= ctx->totchild;
totparent= ctx->totparent;
- if(editupdate && sim->psys->childcache && !(part->flag & PART_BRANCHING) && totchild == sim->psys->totchildcache) {
- cache = sim->psys->childcache;
+ if(editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) {
+ ; /* just overwrite the existing cache */
}
else {
/* clear out old and create new empty path cache */
@@ -2786,6 +2815,43 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd
psys_threads_free(pthreads);
}
+/* figure out incremental rotations along path starting from unit quat */
+static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCacheKey *key1, ParticleCacheKey *key2, float *prev_tangent, int i)
+{
+ float cosangle, angle, tangent[3], normal[3], q[4];
+
+ switch(i) {
+ case 0:
+ /* start from second key */
+ break;
+ case 1:
+ /* calculate initial tangent for incremental rotations */
+ sub_v3_v3v3(prev_tangent, key0->co, key1->co);
+ normalize_v3(prev_tangent);
+ unit_qt(key1->rot);
+ break;
+ default:
+ sub_v3_v3v3(tangent, key0->co, key1->co);
+ normalize_v3(tangent);
+
+ cosangle= dot_v3v3(tangent, prev_tangent);
+
+ /* note we do the comparison on cosangle instead of
+ * angle, since floating point accuracy makes it give
+ * different results across platforms */
+ if(cosangle > 0.999999f) {
+ QUATCOPY(key1->rot, key2->rot);
+ }
+ else {
+ angle= saacos(cosangle);
+ cross_v3_v3v3(normal, prev_tangent, tangent);
+ axis_angle_to_quat( q,normal, angle);
+ mul_qt_qtqt(key1->rot, q, key2->rot);
+ }
+
+ copy_v3_v3(prev_tangent, tangent);
+ }
+}
/* Calculates paths ready for drawing/rendering. */
/* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */
/* -Makes child strands possible and creates them too into the cache. */
@@ -2796,21 +2862,22 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
- ParticleCacheKey *ca, **cache= psys->pathcache;
+ ParticleCacheKey *ca, **cache;
- DerivedMesh *hair_dm = psys->hair_out_dm;
+ DerivedMesh *hair_dm = (psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) ? psys->hair_out_dm : NULL;
ParticleKey result;
Material *ma;
ParticleInterpolationData pind;
+ ParticleTexture ptex;
PARTICLE_P;
float birthtime = 0.0, dietime = 0.0;
- float t, time = 0.0, dfra = 1.0, frs_sec = sim->scene->r.frs_sec;
+ float t, time = 0.0, dfra = 1.0 /* , frs_sec = sim->scene->r.frs_sec*/ /*UNUSED*/;
float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
- float prev_tangent[3], hairmat[4][4];
+ float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
float rotmat[3][3];
int k;
int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step));
@@ -2831,7 +2898,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
BLI_srandom(psys->seed);
keyed = psys->flag & PSYS_KEYED;
- baked = !hair_dm && psys->pointcache->mem_cache.first;
+ baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR;
/* clear out old and create new empty path cache */
psys_free_path_cache(psys, psys->edit);
@@ -2853,8 +2920,8 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
/*---first main loop: create all actual particles' paths---*/
LOOP_SHOWN_PARTICLES {
if(!psys->totchild) {
- BLI_srandom(psys->seed + p);
- pa_length = 1.0f - part->randlength * BLI_frand();
+ psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
+ pa_length = ptex.length * (1.0f - part->randlength * PSYS_FRAND(psys->seed + p));
if(vg_length)
pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length);
}
@@ -2898,22 +2965,19 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
/*--interpolate actual path from data points--*/
for(k=0, ca=cache[p]; k<=steps; k++, ca++){
time = (float)k / (float)steps;
-
t = birthtime + time * (dietime - birthtime);
-
result.time = -t;
-
- do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, &result);
+ do_particle_interpolation(psys, p, pa, t, &pind, &result);
+ copy_v3_v3(ca->co, result.co);
/* dynamic hair is in object space */
/* keyed and baked are already in global space */
if(hair_dm)
- mul_m4_v3(sim->ob->obmat, result.co);
+ mul_m4_v3(sim->ob->obmat, ca->co);
else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR))
- mul_m4_v3(hairmat, result.co);
+ mul_m4_v3(hairmat, ca->co);
- VECCOPY(ca->co, result.co);
- VECCOPY(ca->col, col);
+ copy_v3_v3(ca->col, col);
}
/*--modify paths and calculate rotation & velocity--*/
@@ -2948,54 +3012,25 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
/* finally do rotation & velocity */
for(k=1, ca=cache[p]+1; k<=steps; k++, ca++) {
- /* figure out rotation */
- float cosangle, angle, tangent[3], normal[3], q[4];
-
- if(k == 1) {
- /* calculate initial tangent for incremental rotations */
- VECSUB(tangent, ca->co, (ca - 1)->co);
- normalize_v3_v3(prev_tangent, tangent);
-
- /* First rotation is based on emitting face orientation. */
- /* This is way better than having flipping rotations resulting */
- /* from using a global axis as a rotation pole (vec_to_quat()). */
- /* It's not an ideal solution though since it disregards the */
- /* initial tangent, but taking that in to account will allow */
- /* the possibility of flipping again. -jahka */
- mat3_to_quat_is_ok( (ca-1)->rot,rotmat);
- }
- else {
- VECSUB(tangent, ca->co, (ca - 1)->co);
- normalize_v3(tangent);
-
- cosangle= dot_v3v3(tangent, prev_tangent);
-
- /* note we do the comparison on cosangle instead of
- * angle, since floating point accuracy makes it give
- * different results across platforms */
- if(cosangle > 0.999999f) {
- QUATCOPY((ca - 1)->rot, (ca - 2)->rot);
- }
- else {
- angle= saacos(cosangle);
- cross_v3_v3v3(normal, prev_tangent, tangent);
- axis_angle_to_quat( q,normal, angle);
- mul_qt_qtqt((ca - 1)->rot, q, (ca - 2)->rot);
- }
-
- VECCOPY(prev_tangent, tangent);
- }
+ cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
if(k == steps)
- QUATCOPY(ca->rot, (ca - 1)->rot);
-
+ copy_qt_qt(ca->rot, (ca - 1)->rot);
/* set velocity */
- VECSUB(ca->vel, ca->co, (ca-1)->co);
+ sub_v3_v3v3(ca->vel, ca->co, (ca-1)->co);
if(k==1)
- VECCOPY((ca-1)->vel, ca->vel);
+ copy_v3_v3((ca-1)->vel, ca->vel);
}
+ /* First rotation is based on emitting face orientation.
+ * This is way better than having flipping rotations resulting
+ * from using a global axis as a rotation pole (vec_to_quat()).
+ * It's not an ideal solution though since it disregards the
+ * initial tangent, but taking that in to account will allow
+ * the possibility of flipping again. -jahka
+ */
+ mat3_to_quat_is_ok(cache[p]->rot, rotmat);
}
psys->totcached = totpart;
@@ -3028,7 +3063,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
float birthtime = 0.0, dietime = 0.0;
float t, time = 0.0, keytime = 0.0, frs_sec;
- float hairmat[4][4], rotmat[3][3], prev_tangent[3];
+ float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f};
int k, i;
int steps = (int)pow(2.0, (double)pset->draw_step);
int totpart = edit->totpoint, recalc_set=0;
@@ -3050,12 +3085,8 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
frs_sec = (psys || edit->pid.flag & PTCACHE_VEL_PER_SEC) ? 25.0f : 1.0f;
- if(pset->brushtype == PE_BRUSH_WEIGHT){
- /* use weight painting colors now... */
-#if 0
- sel_col[0] = sel_col[1] = sel_col[2] = 1.0f;
- nosel_col[0] = nosel_col[1] = nosel_col[2] = 0.0f;
-#endif
+ if(pset->brushtype == PE_BRUSH_WEIGHT) {
+ ;/* use weight painting colors now... */
}
else{
sel_col[0] = (float)edit->sel_col[0] / 255.0f;
@@ -3083,6 +3114,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
/* should init_particle_interpolation set this ? */
if(pset->brushtype==PE_BRUSH_WEIGHT){
pind.hkey[0] = NULL;
+ /* pa != NULL since the weight brush is only available for hair */
pind.hkey[1] = pa->hair;
}
@@ -3096,9 +3128,9 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
if(psys) {
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
- VECCOPY(rotmat[0], hairmat[2]);
- VECCOPY(rotmat[1], hairmat[1]);
- VECCOPY(rotmat[2], hairmat[0]);
+ copy_v3_v3(rotmat[0], hairmat[2]);
+ copy_v3_v3(rotmat[1], hairmat[1]);
+ copy_v3_v3(rotmat[2], hairmat[0]);
}
birthtime = pind.birthtime;
@@ -3112,66 +3144,32 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
/*--interpolate actual path from data points--*/
for(k=0, ca=cache[i]; k<=steps; k++, ca++){
time = (float)k / (float)steps;
-
t = birthtime + time * (dietime - birthtime);
-
result.time = -t;
-
- do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
+ do_particle_interpolation(psys, i, pa, t, &pind, &result);
+ copy_v3_v3(ca->co, result.co);
/* non-hair points are already in global space */
if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- mul_m4_v3(hairmat, result.co);
+ mul_m4_v3(hairmat, ca->co);
- /* create rotations for proper creation of children */
if(k) {
- float cosangle, angle, tangent[3], normal[3], q[4];
-
- if(k == 1) {
- /* calculate initial tangent for incremental rotations */
- VECSUB(tangent, ca->co, (ca - 1)->co);
- normalize_v3_v3(prev_tangent, tangent);
-
- /* First rotation is based on emitting face orientation. */
- /* This is way better than having flipping rotations resulting */
- /* from using a global axis as a rotation pole (vec_to_quat()). */
- /* It's not an ideal solution though since it disregards the */
- /* initial tangent, but taking that in to account will allow */
- /* the possibility of flipping again. -jahka */
- mat3_to_quat_is_ok( (ca-1)->rot,rotmat);
- }
- else {
- VECSUB(tangent, ca->co, (ca - 1)->co);
- normalize_v3(tangent);
-
- cosangle= dot_v3v3(tangent, prev_tangent);
-
- /* note we do the comparison on cosangle instead of
- * angle, since floating point accuracy makes it give
- * different results across platforms */
- if(cosangle > 0.999999f) {
- QUATCOPY((ca - 1)->rot, (ca - 2)->rot);
- }
- else {
- angle= saacos(cosangle);
- cross_v3_v3v3(normal, prev_tangent, tangent);
- axis_angle_to_quat( q,normal, angle);
- mul_qt_qtqt((ca - 1)->rot, q, (ca - 2)->rot);
- }
-
- VECCOPY(prev_tangent, tangent);
- }
+ cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
if(k == steps)
- QUATCOPY(ca->rot, (ca - 1)->rot);
- }
-
- }
+ copy_qt_qt(ca->rot, (ca - 1)->rot);
- VECCOPY(ca->co, result.co);
+ /* set velocity */
+ sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
- ca->vel[0] = ca->vel[1] = 0.0f;
- ca->vel[1] = 1.0f;
+ if(k==1)
+ copy_v3_v3((ca - 1)->vel, ca->vel);
+ }
+ }
+ else {
+ ca->vel[0] = ca->vel[1] = 0.0f;
+ ca->vel[1] = 1.0f;
+ }
/* selection coloring in edit mode */
if(pset->brushtype==PE_BRUSH_WEIGHT){
@@ -3219,12 +3217,27 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
ca->time = t;
}
+ if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
+ /* First rotation is based on emitting face orientation.
+ * This is way better than having flipping rotations resulting
+ * from using a global axis as a rotation pole (vec_to_quat()).
+ * It's not an ideal solution though since it disregards the
+ * initial tangent, but taking that in to account will allow
+ * the possibility of flipping again. -jahka
+ */
+ mat3_to_quat_is_ok(cache[i]->rot, rotmat);
+ }
}
edit->totcached = totpart;
if(psys) {
- ParticleSimulationData sim = {scene, ob, psys, psys_get_modifier(ob, psys), NULL};
+ ParticleSimulationData sim= {0};
+ sim.scene= scene;
+ sim.ob= ob;
+ sim.psys= psys;
+ sim.psmd= psys_get_modifier(ob, psys);
+
psys_cache_child_paths(&sim, cfra, 1);
}
@@ -3342,7 +3355,7 @@ static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float m
triatomat(v[0], v[1], v[2], (osface)? osface->uv: NULL, mat);
}
-void psys_mat_hair_to_object(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
+void psys_mat_hair_to_object(Object *UNUSED(ob), DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
{
float vec[3];
@@ -3384,7 +3397,7 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa
/************************************************/
/* ParticleSettings handling */
/************************************************/
-ModifierData *object_add_particle_system(Scene *scene, Object *ob, char *name)
+ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *name)
{
ParticleSystem *psys;
ModifierData *md;
@@ -3423,7 +3436,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, char *name)
psys->cfra=bsystem_time(scene,ob,scene->r.cfra+1,0.0);
DAG_scene_sort(G.main, scene);
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
return md;
}
@@ -3460,7 +3473,7 @@ void object_remove_particle_system(Scene *scene, Object *ob)
ob->mode &= ~OB_MODE_PARTICLE_EDIT;
DAG_scene_sort(G.main, scene);
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
static void default_particle_settings(ParticleSettings *part)
{
@@ -3471,7 +3484,7 @@ static void default_particle_settings(ParticleSettings *part)
part->bb_uv_split=1;
part->bb_align=PART_BB_VIEW;
part->bb_split_offset=PART_BB_OFF_LINEAR;
- part->flag=PART_REACT_MULTIPLE|PART_HAIR_GEOMETRY|PART_EDISTR|PART_TRAND;
+ part->flag=PART_EDISTR|PART_TRAND|PART_HIDE_ADVANCED_HAIR;
part->sta= 1.0;
part->end= 200.0;
@@ -3490,14 +3503,13 @@ static void default_particle_settings(ParticleSettings *part)
part->adapt_angle= 5;
part->adapt_pix= 3;
part->kink_axis= 2;
+ part->kink_amp_clump= 1.f;
part->reactevent= PART_EVENT_DEATH;
part->disp=100;
part->from= PART_FROM_FACE;
part->normfac= 1.0f;
- part->reactshape=1.0f;
-
part->mass=1.0;
part->size=0.05;
part->childsize=1.0;
@@ -3541,7 +3553,7 @@ static void default_particle_settings(ParticleSettings *part)
}
-ParticleSettings *psys_new_settings(char *name, Main *main)
+ParticleSettings *psys_new_settings(const char *name, Main *main)
{
ParticleSettings *part;
@@ -3558,13 +3570,23 @@ ParticleSettings *psys_new_settings(char *name, Main *main)
ParticleSettings *psys_copy_settings(ParticleSettings *part)
{
ParticleSettings *partn;
-
+ int a;
+
partn= copy_libblock(part);
- if(partn->pd) partn->pd= MEM_dupallocN(part->pd);
- if(partn->pd2) partn->pd2= MEM_dupallocN(part->pd2);
- partn->effector_weights = MEM_dupallocN(part->effector_weights);
+ partn->pd= MEM_dupallocN(part->pd);
+ partn->pd2= MEM_dupallocN(part->pd2);
+ partn->effector_weights= MEM_dupallocN(part->effector_weights);
+ partn->fluid= MEM_dupallocN(part->fluid);
partn->boids = boid_copy_settings(part->boids);
+
+ for(a=0; a<MAX_MTEX; a++) {
+ if(part->mtex[a]) {
+ partn->mtex[a]= MEM_mallocN(sizeof(MTex), "psys_copy_tex");
+ memcpy(partn->mtex[a], part->mtex[a], sizeof(MTex));
+ id_us_plus((ID *)partn->mtex[a]->tex);
+ }
+ }
return partn;
}
@@ -3671,82 +3693,128 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl
return 1;
}
-static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float *fw, float *orco, ParticleTexture *ptex, int event)
+#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) if((event & mtex->mapto) & type) {pvalue = texture_value_blend(def, pvalue, value, texfac, blend);}
+#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) if(event & type) { if(pvalue < 0.f) pvalue = 1.f+pvalue; CLAMP(pvalue, 0.0, 1.0); }
+#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) if(event & type) { CLAMP(pvalue, -1.0, 1.0); }
+
+static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, float *fw, float *orco, ParticleTexture *ptex, int event, float cfra)
{
- MTex *mtex;
- int m,setvars=0;
- float value, rgba[4], texco[3];
+ MTex *mtex, **mtexp = part->mtex;
+ int m;
+ float value, rgba[4], texvec[3];
- if(ma) for(m=0; m<MAX_MTEX; m++){
- mtex=ma->mtex[m];
- if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){
+ ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
+ ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink =
+ ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f;
+
+ ptex->length= 1.0f - part->randlength * PSYS_FRAND(child_index + 26);
+ ptex->length*= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f;
+
+ for(m=0; m<MAX_MTEX; m++, mtexp++){
+ mtex = *mtexp;
+ if(mtex && mtex->mapto){
float def=mtex->def_var;
short blend=mtex->blendtype;
+ short texco = mtex->texco;
- if((mtex->texco & TEXCO_UV) && fw) {
- if(!get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texco))
- VECCOPY(texco,orco);
- }
- else
- VECCOPY(texco,orco);
+ if(ELEM(texco, TEXCO_UV, TEXCO_ORCO) && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID))
+ texco = TEXCO_GLOB;
- externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3);
- if((event & mtex->pmapto) & MAP_PA_TIME){
- if((setvars&MAP_PA_TIME)==0){
- ptex->time=0.0;
- setvars|=MAP_PA_TIME;
- }
- ptex->time= texture_value_blend(mtex->def_var,ptex->time,value,mtex->timefac,blend);
+ switch(texco) {
+ case TEXCO_GLOB:
+ copy_v3_v3(texvec, par->state.co);
+ break;
+ case TEXCO_OBJECT:
+ copy_v3_v3(texvec, par->state.co);
+ if(mtex->object)
+ mul_m4_v3(mtex->object->imat, texvec);
+ break;
+ case TEXCO_UV:
+ if(fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec))
+ break;
+ /* no break, failed to get uv's, so let's try orco's */
+ case TEXCO_ORCO:
+ copy_v3_v3(texvec, orco);
+ break;
+ case TEXCO_PARTICLE:
+ /* texture coordinates in range [-1,1] */
+ texvec[0] = 2.f * (cfra - par->time)/(par->dietime-par->time) - 1.f;
+ texvec[1] = 0.f;
+ texvec[2] = 0.f;
+ break;
}
- if((event & mtex->pmapto) & MAP_PA_LENGTH)
- ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend);
- if((event & mtex->pmapto) & MAP_PA_CLUMP)
- ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend);
- if((event & mtex->pmapto) & MAP_PA_KINK)
- ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend);
- if((event & mtex->pmapto) & MAP_PA_ROUGH)
+
+ externtex(mtex, texvec, &value, rgba, rgba+1, rgba+2, rgba+3, 0);
+
+ if((event & mtex->mapto) & PAMAP_ROUGH)
ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,mtex->roughfac,blend);
- if((event & mtex->pmapto) & MAP_PA_DENS)
- ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend);
+
+ SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
+ SET_PARTICLE_TEXTURE(PAMAP_CLUMP, ptex->clump, mtex->clumpfac);
+ SET_PARTICLE_TEXTURE(PAMAP_KINK, ptex->kink, mtex->kinkfac);
+ SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
}
}
- if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); }
- if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); }
- if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); }
- if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); }
- if(event & MAP_PA_ROUGH) {
- CLAMP(ptex->rough1,0.0,1.0);
- CLAMP(ptex->rough2,0.0,1.0);
- CLAMP(ptex->roughe,0.0,1.0);
- }
- if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); }
+
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_CLUMP, ptex->clump);
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_KINK, ptex->kink);
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_ROUGH, ptex->rough1);
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
}
-void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *pa, ParticleTexture *ptex, int event)
+void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra)
{
+ ParticleSettings *part = sim->psys->part;
+ MTex **mtexp = part->mtex;
MTex *mtex;
int m;
- float value, rgba[4], co[3], texco[3];
+ float value, rgba[4], co[3], texvec[3];
int setvars=0;
- if(ma) for(m=0; m<MAX_MTEX; m++){
- mtex=ma->mtex[m];
- if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){
+ /* initialize ptex */
+ ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
+ ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink =
+ ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f;
+
+ ptex->time = (float)(pa - sim->psys->particles)/(float)sim->psys->totpart;
+
+ for(m=0; m<MAX_MTEX; m++, mtexp++){
+ mtex = *mtexp;
+ if(mtex && mtex->mapto){
float def=mtex->def_var;
short blend=mtex->blendtype;
+ short texco = mtex->texco;
- if((mtex->texco & TEXCO_UV) && ELEM(sim->psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if(!get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) {
- /* failed to get uv's, let's try orco's */
- psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0);
- }
- }
- else {
- psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0);
+ if(texco == TEXCO_UV && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID))
+ texco = TEXCO_GLOB;
+
+ switch(texco) {
+ case TEXCO_GLOB:
+ copy_v3_v3(texvec, pa->state.co);
+ break;
+ case TEXCO_OBJECT:
+ copy_v3_v3(texvec, pa->state.co);
+ if(mtex->object)
+ mul_m4_v3(mtex->object->imat, texvec);
+ break;
+ case TEXCO_UV:
+ if(get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texvec))
+ break;
+ /* no break, failed to get uv's, so let's try orco's */
+ case TEXCO_ORCO:
+ psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texvec, 0);
+ break;
+ case TEXCO_PARTICLE:
+ /* texture coordinates in range [-1,1] */
+ texvec[0] = 2.f * (cfra - pa->time)/(pa->dietime-pa->time) - 1.f;
+ texvec[1] = 0.f;
+ texvec[2] = 0.f;
+ break;
}
- externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3);
+ externtex(mtex, texvec, &value, rgba, rgba+1, rgba+2, rgba+3, 0);
- if((event & mtex->pmapto) & MAP_PA_TIME){
+ if((event & mtex->mapto) & PAMAP_TIME) {
/* the first time has to set the base value for time regardless of blend mode */
if((setvars&MAP_PA_TIME)==0){
int flip= (mtex->timefac < 0.0f);
@@ -3758,32 +3826,26 @@ void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *p
else
ptex->time= texture_value_blend(def,ptex->time,value,mtex->timefac,blend);
}
- if((event & mtex->pmapto) & MAP_PA_LIFE)
- ptex->life= texture_value_blend(def,ptex->life,value,mtex->lifefac,blend);
- if((event & mtex->pmapto) & MAP_PA_DENS)
- ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend);
- if((event & mtex->pmapto) & MAP_PA_SIZE)
- ptex->size= texture_value_blend(def,ptex->size,value,mtex->sizefac,blend);
- if((event & mtex->pmapto) & MAP_PA_IVEL)
- ptex->ivel= texture_value_blend(def,ptex->ivel,value,mtex->ivelfac,blend);
- if((event & mtex->pmapto) & MAP_PA_PVEL)
- texture_rgb_blend(ptex->pvel,rgba,ptex->pvel,value,mtex->pvelfac,blend);
- if((event & mtex->pmapto) & MAP_PA_LENGTH)
- ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend);
- if((event & mtex->pmapto) & MAP_PA_CLUMP)
- ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend);
- if((event & mtex->pmapto) & MAP_PA_KINK)
- ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend);
- }
- }
- if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); }
- if(event & MAP_PA_LIFE) { CLAMP(ptex->life,0.0,1.0); }
- if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); }
- if(event & MAP_PA_SIZE) { CLAMP(ptex->size,0.0,1.0); }
- if(event & MAP_PA_IVEL) { CLAMP(ptex->ivel,0.0,1.0); }
- if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); }
- if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); }
- if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); }
+ SET_PARTICLE_TEXTURE(PAMAP_LIFE, ptex->life, mtex->lifefac)
+ SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac)
+ SET_PARTICLE_TEXTURE(PAMAP_SIZE, ptex->size, mtex->sizefac)
+ SET_PARTICLE_TEXTURE(PAMAP_IVEL, ptex->ivel, mtex->ivelfac)
+ SET_PARTICLE_TEXTURE(PAMAP_FIELD, ptex->field, mtex->fieldfac)
+ SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac)
+ SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac)
+ SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac)
+ }
+ }
+
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_TIME, ptex->time)
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LIFE, ptex->life)
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist)
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_SIZE, ptex->size)
+ CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_IVEL, ptex->ivel)
+ CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_FIELD, ptex->field)
+ CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_GRAVITY, ptex->gravity)
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DAMP, ptex->damp)
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length)
}
/************************************************/
/* Particle State */
@@ -3821,33 +3883,13 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra,
return (cfra-time)/life;
}
-float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time)
+float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float UNUSED(cfra), float *UNUSED(pa_time))
{
ParticleSettings *part = psys->part;
float size; // time XXX
- if(part->childtype==PART_CHILD_FACES){
+ if(part->childtype==PART_CHILD_FACES)
size=part->size;
-
-#if 0 // XXX old animation system
- if((part->flag&PART_ABS_TIME)==0 && part->ipo){
- IpoCurve *icu;
-
- if(pa_time)
- time=*pa_time;
- else
- time=psys_get_child_time(psys,cpa,cfra,NULL,NULL);
-
- /* correction for lifetime */
- calc_ipo(part->ipo, 100*time);
-
- for(icu = part->ipo->curve.first; icu; icu=icu->next) {
- if(icu->adrcode == PART_SIZE)
- size = icu->curval;
- }
- }
-#endif // XXX old animation system
- }
else
size=psys->particles[cpa->parent].size;
@@ -3863,19 +3905,7 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
ParticleSystem *psys = ctx->sim.psys;
int i = cpa - psys->child;
- ptex->length= 1.0f - part->randlength * PSYS_FRAND(i + 26);
- ptex->clump=1.0;
- ptex->kink=1.0;
- ptex->rough1= 1.0;
- ptex->rough2= 1.0;
- ptex->roughe= 1.0;
- ptex->exist= 1.0;
- ptex->effector= 1.0;
-
- ptex->length*= part->clength_thres < PSYS_FRAND(i + 27) ? part->clength : 1.0f;
-
- get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex,
- MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH);
+ get_cpa_texture(ctx->dm, psys, part, psys->particles + cpa->pa[0], i, cpa_num, cpa_fuv, orco, ptex, PAMAP_DENS|PAMAP_CHILD, psys->cfra);
if(ptex->exist < PSYS_FRAND(i + 24))
@@ -3902,26 +3932,42 @@ static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *pte
int i = cpa - sim->psys->child;
int guided = 0;
+ float kink_freq = part->kink_freq;
+ float rough1 = part->rough1;
+ float rough2 = part->rough2;
+ float rough_end = part->rough_end;
+
+ if(ptex) {
+ kink_freq *= ptex->kink;
+ rough1 *= ptex->rough1;
+ rough2 *= ptex->rough2;
+ rough_end *= ptex->roughe;
+ }
+
if(part->flag & PART_CHILD_EFFECT)
/* state is safe to cast, since only co and vel are used */
guided = do_guides(sim->psys->effectors, (ParticleKey*)state, cpa->parent, t);
if(guided==0){
- if(part->kink)
- do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape,
- part->kink_amp, part->kink, part->kink_axis, sim->ob->obmat);
-
- do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump);
+ float clump = do_clump(state, par, t, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f);
+
+ if(kink_freq != 0.f) {
+ float kink_amp = part->kink_amp * (1.f - part->kink_amp_clump * clump);
+
+ do_kink(state, par, par_rot, t, kink_freq, part->kink_shape,
+ kink_amp, part->kink_flat, part->kink, part->kink_axis,
+ sim->ob->obmat, sim->psys->part->childtype == PART_CHILD_FACES);
+ }
}
- if(part->rough1 != 0.0 && ptex->rough1 != 0.0)
- do_rough(orco, mat, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state);
+ if(rough1 > 0.f)
+ do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
- if(part->rough2 != 0.0 && ptex->rough2 != 0.0)
- do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state);
+ if(rough2 > 0.f)
+ do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, rough2, part->rough2_size, part->rough2_thres, state);
- if(part->rough_end != 0.0 && ptex->roughe != 0.0)
- do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state);
+ if(rough_end > 0.f)
+ do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, rough_end, part->rough_end_shape, state);
}
/* get's hair (or keyed) particles state at the "path time" specified in state->time */
void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, int vel)
@@ -3937,10 +3983,9 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
ParticleThreadContext ctx; /* fake thread context for child modifiers */
ParticleInterpolationData pind;
- float t, frs_sec = sim->scene->r.frs_sec;
+ float t;
float co[3], orco[3];
float hairmat[4][4];
- int totparent = 0;
int totpart = psys->totpart;
int totchild = psys->totchild;
short between = 0, edit = 0;
@@ -3950,11 +3995,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
float *cpa_fuv; int cpa_num; short cpa_from;
- //if(psys_in_edit_mode(scene, psys)){
- // if((psys->edit_path->flag & PSYS_EP_SHOW_CHILD)==0)
- // totchild=0;
- // edit=1;
- //}
+ /* initialize keys to zero */
+ memset(keys, 0, 4*sizeof(ParticleKey));
t=state->time;
CLAMP(t, 0.0, 1.0);
@@ -3969,7 +4011,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
* account when subdividing for instance */
pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm;
init_particle_interpolation(sim->ob, psys, pa, &pind);
- do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state);
+ do_particle_interpolation(psys, p, pa, t, &pind, state);
if(!keyed && !cached) {
if((pa->flag & PARS_REKEY)==0) {
@@ -3996,11 +4038,6 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
- totparent=(int)(totchild*part->parents*0.3);
-
- if(G.rendering && part->child_nbr && part->ren_child_nbr)
- totparent*=(float)part->child_nbr/(float)part->ren_child_nbr;
-
/* part->parents could still be 0 so we can't test with totparent */
between=1;
}
@@ -4031,7 +4068,10 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
pa = psys->particles + cpa->parent;
- psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
+ if(part->type == PART_HAIR)
+ psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
+ else
+ unit_m4(hairmat);
pa=0;
}
@@ -4047,9 +4087,16 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
cpa_num=pa->num;
cpa_fuv=pa->fuv;
- psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0);
+
- psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
+ if(part->type == PART_HAIR) {
+ psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0);
+ psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
+ }
+ else {
+ copy_v3_v3(orco, cpa->fuv);
+ unit_m4(hairmat);
+ }
}
/* correct child ipo timing */
@@ -4090,7 +4137,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
}
else{
/* offset the child from the parent position */
- offset_child(cpa, keys, state, part->childflat, part->childrad);
+ offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad);
}
par = keys;
@@ -4169,11 +4216,11 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
if(pa) {
if(!always)
- if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
- || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))
+ if((cfra < pa->time && (part->flag & PART_UNBORN)==0)
+ || (cfra > pa->dietime && (part->flag & PART_DIED)==0))
return 0;
- state->time = MIN2(state->time, pa->dietime);
+ cfra = MIN2(cfra, pa->dietime);
}
if(sim->psys->flag & PSYS_KEYED){
@@ -4183,41 +4230,42 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
}
else{
if(cpa){
+ float mat[4][4];
ParticleKey *key1;
float t = (cfra - pa->time) / pa->lifetime;
key1=&pa->state;
- offset_child(cpa, key1, state, part->childflat, part->childrad);
-
+ offset_child(cpa, key1, key1->rot, state, part->childflat, part->childrad);
+
CLAMP(t,0.0,1.0);
- if(part->kink) /* TODO: part->kink_freq*pa_kink */
- do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,sim->ob->obmat);
-
- /* TODO: pa_clump vgroup */
- do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0);
+
+ unit_m4(mat);
+ do_child_modifiers(sim, NULL, key1, key1->rot, cpa, cpa->fuv, mat, state, t);
if(psys->lattice)
calc_latt_deform(sim->psys->lattice, state->co,1.0f);
}
else{
- if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)
- || pa->prev_state.time <= 0.0f)
+ if(pa->state.time==cfra || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED))
copy_particle_key(state, &pa->state, 1);
- else if(pa->prev_state.time==state->time)
+ else if(pa->prev_state.time==cfra)
copy_particle_key(state, &pa->prev_state, 1);
else {
+ float dfra, frs_sec = sim->scene->r.frs_sec;
/* let's interpolate to try to be as accurate as possible */
- if(pa->state.time + 2.0f > state->time && pa->prev_state.time - 2.0f < state->time) {
- ParticleKey keys[4];
- float dfra, keytime, frs_sec = sim->scene->r.frs_sec;
+ if(pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) {
+ if(pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) {
+ /* prev_state is wrong so let's not use it, this can happen at frames 1, 0 or particle birth */
+ dfra = state->time - pa->state.time;
- if(pa->prev_state.time >= pa->state.time) {
- /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */
copy_particle_key(state, &pa->state, 1);
- VECADDFAC(state->co, state->co, state->vel, (state->time-pa->state.time)/frs_sec);
+ madd_v3_v3v3fl(state->co, state->co, state->vel, dfra/frs_sec);
}
else {
+ ParticleKey keys[4];
+ float keytime;
+
copy_particle_key(keys+1, &pa->prev_state, 1);
copy_particle_key(keys+2, &pa->state, 1);
@@ -4232,12 +4280,21 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
psys_interpolate_particle(-1, keys, keytime, state, 1);
/* convert back to real velocity */
- mul_v3_fl(state->vel, 1.0f / (dfra * timestep));
+ mul_v3_fl(state->vel, 1.f / (dfra * timestep));
interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime);
interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime);
}
}
+ else if(pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) {
+ /* linear interpolation using only pa->state */
+
+ dfra = state->time - pa->state.time;
+
+ copy_particle_key(state, &pa->state, 1);
+
+ madd_v3_v3v3fl(state->co, state->co, state->vel, dfra/frs_sec);
+ }
else {
/* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */
copy_particle_key(state, &pa->state, 0);
@@ -4252,7 +4309,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
}
}
-void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
+void psys_get_dupli_texture(Object *UNUSED(ob), ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
{
MFace *mface;
MTFace *mtface;
@@ -4285,7 +4342,7 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo
if(num == DMCACHE_NOTFOUND)
num= pa->num;
- if (num >= psmd->dm->getNumFaces(psmd->dm)) {
+ if (num >= psmd->dm->getNumTessFaces(psmd->dm)) {
/* happens when simplify is enabled
* gives invalid coords but would crash otherwise */
num= DMCACHE_NOTFOUND;
@@ -4357,7 +4414,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa
normalize_v3(side);
cross_v3_v3v3(nor, vec, side);
- unit_m4(mat);
+ unit_m4(mat);
VECCOPY(mat[0], vec);
VECCOPY(mat[1], side);
VECCOPY(mat[2], nor);
@@ -4450,9 +4507,12 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
VECADDFAC(center, center, yvec, bb->offset[1]);
}
-
void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) {
- ParticleSimulationData sim = {scene, ob, psys, psys_get_modifier(ob, psys)};
+ ParticleSimulationData sim= {0};
+ sim.scene= scene;
+ sim.ob= ob;
+ sim.psys= psys;
+ sim.psmd= psys_get_modifier(ob, psys);
psys->lattice = psys_get_lattice(&sim);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 955de554e00..b4900553814 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -29,6 +29,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#include <stddef.h>
#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
#include <stdlib.h>
@@ -53,6 +54,7 @@
#include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed!
#include "DNA_listBase.h"
+#include "BLI_edgehash.h"
#include "BLI_rand.h"
#include "BLI_jitter.h"
#include "BLI_math.h"
@@ -61,7 +63,10 @@
#include "BLI_kdopbvh.h"
#include "BLI_listbase.h"
#include "BLI_threads.h"
+#include "BLI_storage.h" /* For _LARGEFILE64_SOURCE; zlib needs this on some systems */
+#include "BLI_utildefines.h"
+#include "BKE_main.h"
#include "BKE_animsys.h"
#include "BKE_boids.h"
#include "BKE_cdderivedmesh.h"
@@ -70,7 +75,7 @@
#include "BKE_effect.h"
#include "BKE_particle.h"
#include "BKE_global.h"
-#include "BKE_utildefines.h"
+
#include "BKE_DerivedMesh.h"
#include "BKE_object.h"
#include "BKE_material.h"
@@ -115,7 +120,8 @@ static int particles_are_dynamic(ParticleSystem *psys) {
else
return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
}
-int psys_get_current_display_percentage(ParticleSystem *psys)
+
+static int psys_get_current_display_percentage(ParticleSystem *psys)
{
ParticleSettings *part=psys->part;
@@ -124,8 +130,18 @@ int psys_get_current_display_percentage(ParticleSystem *psys)
|| (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
return 100;
- return psys->part->disp;
- }
+ return psys->part->disp;
+}
+
+static int tot_particles(ParticleSystem *psys, PTCacheID *pid)
+{
+ if(pid && psys->pointcache->flag & PTCACHE_EXTERNAL)
+ return pid->cache->totpoint;
+ else if(psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT)
+ return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res - psys->totunexist;
+ else
+ return psys->part->totpart - psys->totunexist;
+}
void psys_reset(ParticleSystem *psys, int mode)
{
@@ -133,9 +149,12 @@ void psys_reset(ParticleSystem *psys, int mode)
if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) {
if(mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) {
- psys_free_particles(psys);
+ /* don't free if not absolutely necessary */
+ if(psys->totpart != tot_particles(psys, NULL)) {
+ psys_free_particles(psys);
+ psys->totpart= 0;
+ }
- psys->totpart= 0;
psys->totkeyed= 0;
psys->flag &= ~(PSYS_HAIR_DONE|PSYS_KEYED);
@@ -155,7 +174,7 @@ void psys_reset(ParticleSystem *psys, int mode)
/* reset children */
if(psys->child) {
MEM_freeN(psys->child);
- psys->child= 0;
+ psys->child= NULL;
}
psys->totchild= 0;
@@ -165,6 +184,13 @@ void psys_reset(ParticleSystem *psys, int mode)
/* reset point cache */
BKE_ptcache_invalidate(psys->pointcache);
+
+ if(psys->fluid_springs) {
+ MEM_freeN(psys->fluid_springs);
+ psys->fluid_springs = NULL;
+ }
+
+ psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
}
static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
@@ -194,9 +220,22 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
psys->free_edit = NULL;
}
- newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles");
- if(psys->part->phystype == PART_PHYS_BOIDS)
- newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles");
+ if(totpart) {
+ newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles");
+ if(newpars == NULL)
+ return;
+
+ if(psys->part->phystype == PART_PHYS_BOIDS) {
+ newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles");
+
+ if(newboids == NULL) {
+ /* allocation error! */
+ if(newpars)
+ MEM_freeN(newpars);
+ return;
+ }
+ }
+ }
if(psys->particles) {
totsaved=MIN2(psys->totpart,totpart);
@@ -239,7 +278,7 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
if(psys->child) {
MEM_freeN(psys->child);
- psys->child=0;
+ psys->child=NULL;
psys->totchild=0;
}
}
@@ -274,7 +313,7 @@ static void alloc_child_particles(ParticleSystem *psys, int tot)
}
MEM_freeN(psys->child);
- psys->child=0;
+ psys->child=NULL;
psys->totchild=0;
}
@@ -332,12 +371,17 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
/* cache the verts/faces! */
LOOP_PARTICLES {
+ if(pa->num < 0) {
+ pa->num_dmcache = -1;
+ continue;
+ }
+
if(psys->part->from == PART_FROM_VERT) {
if(nodearray[pa->num])
pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link);
}
else { /* FROM_FACE/FROM_VOLUME */
- /* Note that somtimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this,
+ /* Note that sometimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this,
* but for now passing NULL is OK. every face will be searched for the particle so its slower - Campbell */
pa->num_dmcache= psys_particle_dm_face_lookup(ob, dm, pa->num, pa->fuv, pa->num < totelem ? nodearray[pa->num] : NULL);
}
@@ -358,7 +402,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
{
- ParticleData *pa=0;
+ ParticleData *pa=NULL;
float min[3], max[3], delta[3], d;
MVert *mv, *mvert = dm->getVertDataArray(dm,0);
int totvert=dm->getNumVerts(dm), from=psys->part->from;
@@ -367,8 +411,8 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
mv=mvert;
/* find bounding box of dm */
- VECCOPY(min,mv->co);
- VECCOPY(max,mv->co);
+ copy_v3_v3(min, mv->co);
+ copy_v3_v3(max, mv->co);
mv++;
for(i=1; i<totvert; i++, mv++){
@@ -384,30 +428,35 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
VECSUB(delta,max,min);
/* determine major axis */
- axis = (delta[0]>=delta[1])?0:((delta[1]>=delta[2])?1:2);
-
+ axis = (delta[0]>=delta[1]) ? 0 : ((delta[1]>=delta[2]) ? 1 : 2);
+
d = delta[axis]/(float)res;
- size[axis]=res;
- size[(axis+1)%3]=(int)ceil(delta[(axis+1)%3]/d);
- size[(axis+2)%3]=(int)ceil(delta[(axis+2)%3]/d);
+ size[axis] = res;
+ size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d);
+ size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d);
/* float errors grrr.. */
size[(axis+1)%3] = MIN2(size[(axis+1)%3],res);
size[(axis+2)%3] = MIN2(size[(axis+2)%3],res);
- min[0]+=d/2.0f;
- min[1]+=d/2.0f;
- min[2]+=d/2.0f;
+ size[0] = MAX2(size[0], 1);
+ size[1] = MAX2(size[1], 1);
+ size[2] = MAX2(size[2], 1);
+
+ /* no full offset for flat/thin objects */
+ min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f;
+ min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f;
+ min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f;
for(i=0,p=0,pa=psys->particles; i<res; i++){
for(j=0; j<res; j++){
for(k=0; k<res; k++,p++,pa++){
- pa->fuv[0]=min[0]+(float)i*d;
- pa->fuv[1]=min[1]+(float)j*d;
- pa->fuv[2]=min[2]+(float)k*d;
+ pa->fuv[0] = min[0] + (float)i*d;
+ pa->fuv[1] = min[1] + (float)j*d;
+ pa->fuv[2] = min[2] + (float)k*d;
pa->flag |= PARS_UNEXIST;
- pa->hair_index=0; /* abused in volume calculation */
+ pa->hair_index = 0; /* abused in volume calculation */
}
}
}
@@ -418,9 +467,9 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
pa=psys->particles;
- min[0]-=d/2.0f;
- min[1]-=d/2.0f;
- min[2]-=d/2.0f;
+ min[0] -= d/2.0f;
+ min[1] -= d/2.0f;
+ min[2] -= d/2.0f;
for(i=0,mv=mvert; i<totvert; i++,mv++){
sub_v3_v3v3(vec,mv->co,min);
@@ -435,13 +484,13 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
else if(ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)){
float co1[3], co2[3];
- MFace *mface=0;
+ MFace *mface= NULL, *mface_array;
float v1[3], v2[3], v3[3], v4[4], lambda;
int a, a1, a2, a0mul, a1mul, a2mul, totface;
int amax= from==PART_FROM_FACE ? 3 : 1;
totface=dm->getNumTessFaces(dm);
- mface=dm->getTessFaceDataArray(dm,CD_MFACE);
+ mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
for(a=0; a<amax; a++){
if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; }
@@ -450,22 +499,22 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
for(a1=0; a1<size[(a+1)%3]; a1++){
for(a2=0; a2<size[(a+2)%3]; a2++){
- mface=dm->getTessFaceDataArray(dm,CD_MFACE);
-
- pa=psys->particles + a1*a1mul + a2*a2mul;
- VECCOPY(co1,pa->fuv);
- co1[a]-=d/2.0f;
- VECCOPY(co2,co1);
- co2[a]+=delta[a] + 0.001f*d;
- co1[a]-=0.001f*d;
+ mface= mface_array;
+
+ pa = psys->particles + a1*a1mul + a2*a2mul;
+ copy_v3_v3(co1, pa->fuv);
+ co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f;
+ copy_v3_v3(co2, co1);
+ co2[a] += delta[a] + 0.001f*d;
+ co1[a] -= 0.001f*d;
/* lets intersect the faces */
for(i=0; i<totface; i++,mface++){
- VECCOPY(v1,mvert[mface->v1].co);
- VECCOPY(v2,mvert[mface->v2].co);
- VECCOPY(v3,mvert[mface->v3].co);
+ copy_v3_v3(v1, mvert[mface->v1].co);
+ copy_v3_v3(v2, mvert[mface->v2].co);
+ copy_v3_v3(v3, mvert[mface->v3].co);
- if(isect_axial_line_tri_v3(a,co1, co2, v2, v3, v1, &lambda)){
+ if(isect_axial_line_tri_v3(a, co1, co2, v2, v3, v1, &lambda)){
if(from==PART_FROM_FACE)
(pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
else /* store number of intersections */
@@ -473,9 +522,9 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
}
if(mface->v4){
- VECCOPY(v4,mvert[mface->v4].co);
+ copy_v3_v3(v4, mvert[mface->v4].co);
- if(isect_axial_line_tri_v3(a,co1, co2, v4, v1, v3, &lambda)){
+ if(isect_axial_line_tri_v3(a, co1, co2, v4, v1, v3, &lambda)){
if(from==PART_FROM_FACE)
(pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
else
@@ -500,8 +549,24 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
}
}
+ if(psys->part->flag & PART_GRID_HEXAGONAL) {
+ for(i=0,p=0,pa=psys->particles; i<res; i++){
+ for(j=0; j<res; j++){
+ for(k=0; k<res; k++,p++,pa++){
+ if(j%2)
+ pa->fuv[0] += d/2.f;
+
+ if(k%2) {
+ pa->fuv[0] += d/2.f;
+ pa->fuv[1] += d/2.f;
+ }
+ }
+ }
+ }
+ }
+
if(psys->part->flag & PART_GRID_INVERT){
- for(i=0,pa=psys->particles; i<size[0]; i++){
+ for(i=0; i<size[0]; i++){
for(j=0; j<size[1]; j++){
pa=psys->particles + res*(i*res + j);
for(k=0; k<size[2]; k++, pa++){
@@ -510,6 +575,18 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
}
}
}
+
+ if(psys->part->grid_rand > 0.f) {
+ float rfac = d * psys->part->grid_rand;
+ for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++){
+ if(pa->flag & PARS_UNEXIST)
+ continue;
+
+ pa->fuv[0] += rfac * (PSYS_FRAND(p + 31) - 0.5f);
+ pa->fuv[1] += rfac * (PSYS_FRAND(p + 32) - 0.5f);
+ pa->fuv[2] += rfac * (PSYS_FRAND(p + 33) - 0.5f);
+ }
+ }
}
/* modified copy from rayshade.c */
@@ -603,15 +680,21 @@ static void psys_uv_to_w(float u, float v, int quad, float *w)
}
}
+/* Find the index in "sum" array before "value" is crossed. */
static int binary_search_distribution(float *sum, int n, float value)
{
int mid, low=0, high=n;
+ if(value == 0.f)
+ return 0;
+
while(low <= high) {
mid= (low + high)/2;
- if(sum[mid] <= value && value <= sum[mid+1])
+
+ if(sum[mid] < value && value <= sum[mid+1])
return mid;
- else if(sum[mid] > value)
+
+ if(sum[mid] >= value)
high= mid - 1;
else if(sum[mid] < value)
low= mid + 1;
@@ -635,7 +718,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
DerivedMesh *dm= ctx->dm;
ParticleData *tpa;
/* ParticleSettings *part= ctx->sim.psys->part; */
- float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3], ornor1[3];
+ float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3];
float cur_d, min_d, randu, randv;
int from= ctx->from;
int cfrom= ctx->cfrom;
@@ -772,20 +855,17 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
if(ctx->tree){
KDTreeNearest ptn[10];
int w,maxw;//, do_seams;
- float maxd,mind,dd,totw=0.0;
+ float maxd,mind,/*dd,*/totw=0.0;
int parent[10];
float pweight[10];
- /*do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams);*/
-
- psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0,orco1,ornor1);
+ psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL);
transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1);
- //maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn);
- maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,ornor1,ptn);
+ maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,NULL,ptn);
maxd=ptn[maxw-1].dist;
mind=ptn[0].dist;
- dd=maxd-mind;
+ /*dd=maxd-mind;*/ /*UNUSED*/
/* the weights here could be done better */
for(w=0; w<maxw; w++){
@@ -796,63 +876,6 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
parent[w]=-1;
pweight[w]=0.0f;
}
- //if(do_seams){
- // ParticleSeam *seam=ctx->seams;
- // float temp[3],temp2[3],tan[3];
- // float inp,cur_len,min_len=10000.0f;
- // int min_seam=0, near_vert=0;
- // /* find closest seam */
- // for(i=0; i<ctx->totseam; i++, seam++){
- // sub_v3_v3v3(temp,co1,seam->v0);
- // inp=dot_v3v3(temp,seam->dir)/seam->length2;
- // if(inp<0.0f){
- // cur_len=len_v3v3(co1,seam->v0);
- // }
- // else if(inp>1.0f){
- // cur_len=len_v3v3(co1,seam->v1);
- // }
- // else{
- // copy_v3_v3(temp2,seam->dir);
- // mul_v3_fl(temp2,inp);
- // cur_len=len_v3v3(temp,temp2);
- // }
- // if(cur_len<min_len){
- // min_len=cur_len;
- // min_seam=i;
- // if(inp<0.0f) near_vert=-1;
- // else if(inp>1.0f) near_vert=1;
- // else near_vert=0;
- // }
- // }
- // seam=ctx->seams+min_seam;
- //
- // copy_v3_v3(temp,seam->v0);
- //
- // if(near_vert){
- // if(near_vert==-1)
- // sub_v3_v3v3(tan,co1,seam->v0);
- // else{
- // sub_v3_v3v3(tan,co1,seam->v1);
- // copy_v3_v3(temp,seam->v1);
- // }
-
- // normalize_v3(tan);
- // }
- // else{
- // copy_v3_v3(tan,seam->tan);
- // sub_v3_v3v3(temp2,co1,temp);
- // if(dot_v3v3(tan,temp2)<0.0f)
- // negate_v3(tan);
- // }
- // for(w=0; w<maxw; w++){
- // sub_v3_v3v3(temp2,ptn[w].co,temp);
- // if(dot_v3v3(tan,temp2)<0.0f){
- // parent[w]=-1;
- // pweight[w]=0.0f;
- // }
- // }
-
- //}
for(w=0,i=0; w<maxw && i<4; w++){
if(parent[w]>=0){
@@ -963,7 +986,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
DerivedMesh *dm= NULL;
float *jit= NULL;
int i, seed, p=0, totthread= threads[0].tot;
- int no_distr=0, cfrom=0;
+ int /*no_distr=0,*/ cfrom=0;
int tot=0, totpart, *index=0, children=0, totseam=0;
//int *vertpart=0;
int jitlevel= 1, distr;
@@ -988,6 +1011,8 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
if(from==PART_FROM_CHILD){
distr=PART_DISTR_RAND;
+ BLI_srandom(31415926 + psys->seed + psys->child_seed);
+
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
dm= finaldm;
children=1;
@@ -1004,50 +1029,6 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
totpart=get_psys_tot_child(scene, psys);
cfrom=from=PART_FROM_FACE;
-
- //if(part->flag&PART_CHILD_SEAMS){
- // MEdge *ed, *medge=dm->getEdgeDataArray(dm,CD_MEDGE);
- // MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
- // int totedge=dm->getNumEdges(dm);
-
- // for(p=0, ed=medge; p<totedge; p++,ed++)
- // if(ed->flag&ME_SEAM)
- // totseam++;
-
- // if(totseam){
- // ParticleSeam *cur_seam=seams=MEM_callocN(totseam*sizeof(ParticleSeam),"Child Distribution Seams");
- // float temp[3],temp2[3];
-
- // for(p=0, ed=medge; p<totedge; p++,ed++){
- // if(ed->flag&ME_SEAM){
- // copy_v3_v3(cur_seam->v0,(mvert+ed->v1)->co);
- // copy_v3_v3(cur_seam->v1,(mvert+ed->v2)->co);
-
- // sub_v3_v3v3(cur_seam->dir,cur_seam->v1,cur_seam->v0);
-
- // cur_seam->length2=len_v3(cur_seam->dir);
- // cur_seam->length2*=cur_seam->length2;
-
- // temp[0]=(float)((mvert+ed->v1)->no[0]);
- // temp[1]=(float)((mvert+ed->v1)->no[1]);
- // temp[2]=(float)((mvert+ed->v1)->no[2]);
- // temp2[0]=(float)((mvert+ed->v2)->no[0]);
- // temp2[1]=(float)((mvert+ed->v2)->no[1]);
- // temp2[2]=(float)((mvert+ed->v2)->no[2]);
-
- // add_v3_v3v3(cur_seam->nor,temp,temp2);
- // normalize_v3(cur_seam->nor);
-
- // cross_v3_v3v3(cur_seam->tan,cur_seam->dir,cur_seam->nor);
-
- // normalize_v3(cur_seam->tan);
-
- // cur_seam++;
- // }
- // }
- // }
- //
- //}
}
else{
/* no need to figure out distribution */
@@ -1092,7 +1073,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
distr=part->distr;
- pa=psys->particles;
+
if(from==PART_FROM_VERT){
MVert *mv= dm->getVertDataArray(dm, CD_MVERT);
float (*orcodata)[3]= dm->getVertDataArray(dm, CD_ORCO);
@@ -1137,7 +1118,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
}
if(tot==0){
- no_distr=1;
+ /*no_distr=1;*/ /*UNUSED*/
if(children){
if(G.f & G_DEBUG)
fprintf(stderr,"Particle child distribution error: Nothing to emit from!\n");
@@ -1284,7 +1265,8 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
float pos;
for(p=0; p<totpart; p++) {
- pos= BLI_frand();
+ /* In theory sys[tot] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
+ pos= BLI_frand() * sum[tot];
index[p]= binary_search_distribution(sum, tot, pos);
index[p]= MIN2(tot-1, index[p]);
jitoff[index[p]]= pos;
@@ -1434,7 +1416,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
}
/* ready for future use, to emit particles without geometry */
-static void distribute_particles_on_shape(ParticleSimulationData *sim, int from)
+static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
{
ParticleSystem *psys = sim->psys;
PARTICLE_P;
@@ -1554,113 +1536,77 @@ void psys_threads_free(ParticleThread *threads)
/* set particle parameters that don't change during particle's life */
void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p)
{
- ParticleSettings *part = sim->psys->part;
+ ParticleSystem *psys = sim->psys;
+ ParticleSettings *part = psys->part;
ParticleTexture ptex;
- Material *ma=0;
- //IpoCurve *icu=0; // XXX old animation system
- int totpart;
- totpart=sim->psys->totpart;
+ pa->flag &= ~PARS_UNEXIST;
- ptex.life=ptex.size=ptex.exist=ptex.length=1.0;
- ptex.time=(float)p/(float)totpart;
-
- BLI_srandom(sim->psys->seed + p + 125);
-
- if(part->from!=PART_FROM_PARTICLE && part->type!=PART_FLUID){
- ma=give_current_material(sim->ob,part->omat);
+ if(part->from != PART_FROM_PARTICLE && part->type != PART_FLUID) {
+ psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f);
+
+ if(ptex.exist < PSYS_FRAND(p+125))
+ pa->flag |= PARS_UNEXIST;
- /* TODO: needs some work to make most blendtypes generally usefull */
- psys_get_texture(sim,ma,pa,&ptex,MAP_PA_INIT);
+ pa->time = (part->type == PART_HAIR) ? 0.f : part->sta + (part->end - part->sta)*ptex.time;
}
- if(part->type==PART_HAIR)
- pa->time= 0.0f;
- //else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0)
- // pa->time= 300000.0f; /* max frame */
- else{
- //icu=find_ipocurve(psys->part->ipo,PART_EMIT_TIME);
- //if(icu){
- // calc_icu(icu,100*ptex.time);
- // ptex.time=icu->curval;
- //}
-
- pa->time= part->sta + (part->end - part->sta)*ptex.time;
- }
-
- if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){
- if(ptex.exist < BLI_frand())
- pa->flag |= PARS_UNEXIST;
- else
- pa->flag &= ~PARS_UNEXIST;
- }
-
- pa->hair_index=0;
+ pa->hair_index = 0;
/* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */
/* usage other than straight after distribute has to handle this index by itself - jahka*/
//pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we dont have a derived mesh face */
}
static void initialize_all_particles(ParticleSimulationData *sim)
{
- //IpoCurve *icu=0; // XXX old animation system
ParticleSystem *psys = sim->psys;
PARTICLE_P;
- LOOP_PARTICLES
- initialize_particle(sim, pa, p);
-
- if(psys->part->type != PART_FLUID) {
-#if 0 // XXX old animation system
- icu=find_ipocurve(psys->part->ipo,PART_EMIT_FREQ);
- if(icu){
- float time=psys->part->sta, end=psys->part->end;
- float v1, v2, a=0.0f, t1,t2, d;
-
- p=0;
- pa=psys->particles;
-
-
- calc_icu(icu,time);
- v1=icu->curval;
- if(v1<0.0f) v1=0.0f;
-
- calc_icu(icu,time+1.0f);
- v2=icu->curval;
- if(v2<0.0f) v2=0.0f;
-
- for(p=0, pa=psys->particles; p<totpart && time<end; p++, pa++){
- while(a+0.5f*(v1+v2) < (float)(p+1) && time<end){
- a+=0.5f*(v1+v2);
- v1=v2;
- time++;
- calc_icu(icu,time+1.0f);
- v2=icu->curval;
- }
- if(time<end){
- if(v1==v2){
- pa->time=time+((float)(p+1)-a)/v1;
- }
- else{
- d=(float)sqrt(v1*v1-2.0f*(v2-v1)*(a-(float)(p+1)));
- t1=(-v1+d)/(v2-v1);
- t2=(-v1-d)/(v2-v1);
-
- /* the root between 0-1 is the correct one */
- if(t1>0.0f && t1<=1.0f)
- pa->time=time+t1;
- else
- pa->time=time+t2;
- }
- }
+ psys->totunexist = 0;
+
+ LOOP_PARTICLES {
+ if((pa->flag & PARS_UNEXIST)==0)
+ initialize_particle(sim, pa, p);
+
+ if(pa->flag & PARS_UNEXIST)
+ psys->totunexist++;
+ }
+
+ /* Free unexisting particles. */
+ if(psys->totpart && psys->totunexist == psys->totpart) {
+ if(psys->particles->boid)
+ MEM_freeN(psys->particles->boid);
+
+ MEM_freeN(psys->particles);
+ psys->particles = NULL;
+ psys->totpart = psys->totunexist = 0;
+ }
+
+ if(psys->totunexist) {
+ int newtotpart = psys->totpart - psys->totunexist;
+ ParticleData *npa, *newpars;
+
+ npa = newpars = MEM_callocN(newtotpart * sizeof(ParticleData), "particles");
+
+ for(p=0, pa=psys->particles; p<newtotpart; p++, pa++, npa++) {
+ while(pa->flag & PARS_UNEXIST)
+ pa++;
+
+ memcpy(npa, pa, sizeof(ParticleData));
+ }
+
+ if(psys->particles->boid)
+ MEM_freeN(psys->particles->boid);
+ MEM_freeN(psys->particles);
+ psys->particles = newpars;
+ psys->totpart -= psys->totunexist;
+
+ if(psys->particles->boid) {
+ BoidParticle *newboids = MEM_callocN(psys->totpart * sizeof(BoidParticle), "boid particles");
+
+ LOOP_PARTICLES
+ pa->boid = newboids++;
- pa->dietime = pa->time+pa->lifetime;
- pa->flag &= ~PARS_UNEXIST;
- }
- for(; p<totpart; p++, pa++){
- pa->flag |= PARS_UNEXIST;
- }
}
-#endif // XXX old animation system
}
}
/* sets particle to the emitter surface with initial velocity & rotation */
@@ -1670,39 +1616,19 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
ParticleSystem *psys = sim->psys;
ParticleSettings *part;
ParticleTexture ptex;
- ParticleKey state;
- //IpoCurve *icu=0; // XXX old animation system
float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4];
float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0};
float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
- float q_phase[4], r_phase;
+ float q_phase[4];
int p = pa - psys->particles;
part=psys->part;
- ptex.ivel=1.0;
- ptex.life=1.0;
-
- /* we need to get every random even if they're not used so that they don't effect eachother */
- r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f);
- r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f);
- r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f);
-
- r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f);
- r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f);
- r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f);
-
- r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f);
- r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f);
- r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f);
- r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f);
- normalize_qt(r_rot);
-
- r_phase = PSYS_FRAND(p + 20);
-
+#if 0 /* deprecated code */
if(part->from==PART_FROM_PARTICLE){
- ParticleSimulationData tsim = {sim->scene, psys->target_ob ? psys->target_ob : ob, NULL, NULL};
float speed;
-
+ ParticleSimulationData tsim= {0};
+ tsim.scene= sim->scene;
+ tsim.ob= psys->target_ob ? psys->target_ob : ob;
tsim.psys = BLI_findlink(&tsim.ob->particlesystem, sim->psys->target_psys-1);
state.time = pa->time;
@@ -1724,79 +1650,93 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
VECCOPY(pa->fuv, loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */
}
else{
- /* get precise emitter matrix if particle is born */
- if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) {
- /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
- BKE_animsys_evaluate_animdata(&sim->ob->id, sim->ob->adt, pa->time, ADT_RECALC_ANIM);
- where_is_object_time(sim->scene, sim->ob, pa->time);
- }
+#endif
+ /* get precise emitter matrix if particle is born */
+ if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) {
+ /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
+ BKE_animsys_evaluate_animdata(&sim->ob->id, sim->ob->adt, pa->time, ADT_RECALC_ANIM);
+ where_is_object_time(sim->scene, sim->ob, pa->time);
+ }
- /* get birth location from object */
- if(part->tanfac!=0.0)
- psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0);
- else
- psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0);
+ /* get birth location from object */
+ if(part->tanfac != 0.f)
+ psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0);
+ else
+ psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0);
- /* get possible textural influence */
- psys_get_texture(sim, give_current_material(sim->ob,part->omat), pa, &ptex, MAP_PA_IVEL|MAP_PA_LIFE);
+ /* get possible textural influence */
+ psys_get_texture(sim, pa, &ptex, PAMAP_IVEL|PAMAP_LIFE, cfra);
- //if(vg_vel && pa->num != -1)
- // ptex.ivel*=psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_vel);
-
- /* particles live in global space so */
- /* let's convert: */
- /* -location */
- mul_m4_v3(ob->obmat,loc);
+ /* particles live in global space so */
+ /* let's convert: */
+ /* -location */
+ mul_m4_v3(ob->obmat, loc);
- /* -normal */
- mul_mat3_m4_v3(ob->obmat,nor);
- normalize_v3(nor);
-
- /* -tangent */
- if(part->tanfac!=0.0){
- //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f;
- float phase=0.0f;
- mul_v3_fl(vtan,-(float)cos(M_PI*(part->tanphase+phase)));
- fac=-(float)sin(M_PI*(part->tanphase+phase));
- VECADDFAC(vtan,vtan,utan,fac);
-
- mul_mat3_m4_v3(ob->obmat,vtan);
-
- VECCOPY(utan,nor);
- mul_v3_fl(utan,dot_v3v3(vtan,nor));
- VECSUB(vtan,vtan,utan);
+ /* -normal */
+ mul_mat3_m4_v3(ob->obmat, nor);
+ normalize_v3(nor);
+
+ /* -tangent */
+ if(part->tanfac!=0.0){
+ //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f;
+ float phase=0.0f;
+ mul_v3_fl(vtan,-(float)cos(M_PI*(part->tanphase+phase)));
+ fac=-(float)sin(M_PI*(part->tanphase+phase));
+ VECADDFAC(vtan,vtan,utan,fac);
+
+ mul_mat3_m4_v3(ob->obmat,vtan);
+
+ VECCOPY(utan,nor);
+ mul_v3_fl(utan,dot_v3v3(vtan,nor));
+ VECSUB(vtan,vtan,utan);
- normalize_v3(vtan);
- }
+ normalize_v3(vtan);
+ }
- /* -velocity */
- if(part->randfac!=0.0){
- mul_mat3_m4_v3(ob->obmat,r_vel);
- normalize_v3(r_vel);
- }
+ /* -velocity */
+ if(part->randfac!=0.0){
+ r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f);
+ r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f);
+ r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f);
- /* -angular velocity */
- if(part->avemode==PART_AVE_RAND){
- mul_mat3_m4_v3(ob->obmat,r_ave);
- normalize_v3(r_ave);
- }
+ mul_mat3_m4_v3(ob->obmat, r_vel);
+ normalize_v3(r_vel);
+ }
+
+ /* -angular velocity */
+ if(part->avemode==PART_AVE_RAND){
+ r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f);
+ r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f);
+ r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f);
+
+ mul_mat3_m4_v3(ob->obmat,r_ave);
+ normalize_v3(r_ave);
+ }
- /* -rotation */
- if(part->randrotfac != 0.0f){
- mat4_to_quat(rot,ob->obmat);
- mul_qt_qtqt(r_rot,r_rot,rot);
- }
+ /* -rotation */
+ if(part->randrotfac != 0.0f){
+ r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f);
+ r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f);
+ r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f);
+ r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f);
+ normalize_qt(r_rot);
+
+ mat4_to_quat(rot,ob->obmat);
+ mul_qt_qtqt(r_rot,r_rot,rot);
+ }
+#if 0
}
+#endif
if(part->phystype==PART_PHYS_BOIDS && pa->boid) {
BoidParticle *bpa = pa->boid;
float dvec[3], q[4], mat[3][3];
- VECCOPY(pa->state.co,loc);
+ copy_v3_v3(pa->state.co,loc);
/* boids don't get any initial velocity */
- pa->state.vel[0]=pa->state.vel[1]=pa->state.vel[2]=0.0f;
+ zero_v3(pa->state.vel);
/* boids store direction in ave */
if(fabs(nor[2])==1.0f) {
@@ -1835,66 +1775,56 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
/* -velocity from: */
/* *reactions */
- if(dtime>0.0f){
- VECSUB(vel,pa->state.vel,pa->prev_state.vel);
+ if(dtime > 0.f){
+ sub_v3_v3v3(vel, pa->state.vel, pa->prev_state.vel);
}
/* *emitter velocity */
- if(dtime!=0.0 && part->obfac!=0.0){
- VECSUB(vel,loc,pa->state.co);
- mul_v3_fl(vel,part->obfac/dtime);
+ if(dtime != 0.f && part->obfac != 0.f){
+ sub_v3_v3v3(vel, loc, pa->state.co);
+ mul_v3_fl(vel, part->obfac/dtime);
}
/* *emitter normal */
- if(part->normfac!=0.0)
- VECADDFAC(vel,vel,nor,part->normfac);
+ if(part->normfac != 0.f)
+ madd_v3_v3fl(vel, nor, part->normfac);
/* *emitter tangent */
- if(sim->psmd && part->tanfac!=0.0)
- VECADDFAC(vel,vel,vtan,part->tanfac);
- //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f));
+ if(sim->psmd && part->tanfac != 0.f)
+ madd_v3_v3fl(vel, vtan, part->tanfac);
/* *emitter object orientation */
- if(part->ob_vel[0]!=0.0) {
+ if(part->ob_vel[0] != 0.f) {
normalize_v3_v3(vec, ob->obmat[0]);
- VECADDFAC(vel, vel, vec, part->ob_vel[0]);
+ madd_v3_v3fl(vel, vec, part->ob_vel[0]);
}
- if(part->ob_vel[1]!=0.0) {
+ if(part->ob_vel[1] != 0.f) {
normalize_v3_v3(vec, ob->obmat[1]);
- VECADDFAC(vel, vel, vec, part->ob_vel[1]);
+ madd_v3_v3fl(vel, vec, part->ob_vel[1]);
}
- if(part->ob_vel[2]!=0.0) {
+ if(part->ob_vel[2] != 0.f) {
normalize_v3_v3(vec, ob->obmat[2]);
- VECADDFAC(vel, vel, vec, part->ob_vel[2]);
+ madd_v3_v3fl(vel, vec, part->ob_vel[2]);
}
/* *texture */
/* TODO */
/* *random */
- if(part->randfac!=0.0)
- VECADDFAC(vel,vel,r_vel,part->randfac);
+ if(part->randfac != 0.f)
+ madd_v3_v3fl(vel, r_vel, part->randfac);
/* *particle */
- if(part->partfac!=0.0)
- VECADDFAC(vel,vel,p_vel,part->partfac);
-
- //icu=find_ipocurve(psys->part->ipo,PART_EMIT_VEL);
- //if(icu){
- // calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta)));
- // ptex.ivel*=icu->curval;
- //}
-
- mul_v3_fl(vel,ptex.ivel);
+ if(part->partfac != 0.f)
+ madd_v3_v3fl(vel, p_vel, part->partfac);
- VECCOPY(pa->state.vel,vel);
+ mul_v3_v3fl(pa->state.vel, vel, ptex.ivel);
/* -location from emitter */
- VECCOPY(pa->state.co,loc);
+ copy_v3_v3(pa->state.co,loc);
/* -rotation */
- pa->state.rot[0]=1.0;
- pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0.0;
+ unit_qt(pa->state.rot);
if(part->rotmode){
/* create vector into which rotation is aligned */
@@ -1930,7 +1860,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
/* rotation phase */
phasefac = part->phasefac;
if(part->randphasefac != 0.0f)
- phasefac += part->randphasefac * r_phase;
+ phasefac += part->randphasefac * PSYS_FRAND(p + 20);
axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI);
/* combine base rotation & phase */
@@ -1939,34 +1869,27 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
/* -angular velocity */
- pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0;
+ zero_v3(pa->state.ave);
if(part->avemode){
switch(part->avemode){
case PART_AVE_SPIN:
- VECCOPY(pa->state.ave,vel);
+ copy_v3_v3(pa->state.ave, vel);
break;
case PART_AVE_RAND:
- VECCOPY(pa->state.ave,r_ave);
+ copy_v3_v3(pa->state.ave, r_ave);
break;
}
normalize_v3(pa->state.ave);
mul_v3_fl(pa->state.ave,part->avefac);
-
- //icu=find_ipocurve(psys->part->ipo,PART_EMIT_AVE);
- //if(icu){
- // calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta)));
- // mul_v3_fl(pa->state.ave,icu->curval);
- //}
}
}
-
if(part->type == PART_HAIR){
pa->lifetime = 100.0f;
}
else{
- pa->lifetime = part->lifetime*ptex.life;
+ pa->lifetime = part->lifetime * ptex.life;
if(part->randlife != 0.0)
pa->lifetime *= 1.0f - part->randlife * PSYS_FRAND(p + 21);
@@ -1993,15 +1916,9 @@ static void reset_all_particles(ParticleSimulationData *sim, float dtime, float
{
ParticleData *pa;
int p, totpart=sim->psys->totpart;
- //float *vg_vel=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_VEL);
- //float *vg_tan=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_TAN);
- //float *vg_rot=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_ROT);
for(p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++)
reset_particle(sim, pa, dtime, cfra);
-
- //if(vg_vel)
- // MEM_freeN(vg_vel);
}
/************************************************/
/* Particle targets */
@@ -2052,12 +1969,14 @@ void psys_count_keyed_targets(ParticleSimulationData *sim)
static void set_keyed_keys(ParticleSimulationData *sim)
{
ParticleSystem *psys = sim->psys;
- ParticleSimulationData ksim = {sim->scene, NULL, NULL, NULL};
+ ParticleSimulationData ksim= {0};
ParticleTarget *pt;
PARTICLE_P;
ParticleKey *key;
int totpart = psys->totpart, k, totkeys = psys->totkeyed;
+ ksim.scene= sim->scene;
+
/* no proper targets so let's clear and bail out */
if(psys->totkeyed==0) {
free_keyed_keys(psys);
@@ -2228,7 +2147,9 @@ void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys)
if(cache->flag & PTCACHE_DISK_CACHE && cache->mem_cache.first == NULL) {
PTCacheID pid;
BKE_ptcache_id_from_particles(&pid, ob, psys);
+ cache->flag &= ~PTCACHE_DISK_CACHE;
BKE_ptcache_disk_to_mem(&pid);
+ cache->flag |= PTCACHE_DISK_CACHE;
}
}
static void psys_clear_temp_pointcache(ParticleSystem *psys)
@@ -2280,136 +2201,249 @@ static void psys_update_effectors(ParticleSimulationData *sim)
precalc_guides(sim, sim->psys->effectors);
}
-/*************************************************
+/*********************************************************************************************************
SPH fluid physics
- In theory, there could be unlimited implementation
- of SPH simulators
-**************************************************/
-void particle_fluidsim(ParticleSystem *psys, ParticleData *pa, ParticleSettings *part, ParticleSimulationData *sim, float dfra, float cfra, float mass){
-/****************************************************************************************************************
-* This code uses in some parts adapted algorithms from the pseduo code as outlined in the Research paper
-* Titled: Particle-based Viscoelastic Fluid Simulation.
-* Authors: Simon Clavet, Philippe Beaudoin and Pierre Poulin
-*
-* Website: http://www.iro.umontreal.ca/labs/infographie/papers/Clavet-2005-PVFS/
-* Presented at Siggraph, (2005)
-*
-*****************************************************************************************************************/
- KDTree *tree = psys->tree;
- KDTreeNearest *ptn = NULL;
-
- SPHFluidSettings *fluid = part->fluid;
- ParticleData *second_particle;
+ In theory, there could be unlimited implementation of SPH simulators
- float start[3], end[3], v[3];
- float temp[3];
- float q, radius, D;
- float p, pnear, pressure_near, pressure;
- float dtime = dfra * psys_get_timestep(sim);
- float omega = fluid->viscosity_omega;
- float beta = fluid->viscosity_omega;
- float massfactor = 1.0f/mass;
- int n, neighbours;
+ This code uses in some parts adapted algorithms from the pseudo code as outlined in the Research paper:
-
- radius = fluid->radius;
+ Titled: Particle-based Viscoelastic Fluid Simulation.
+ Authors: Simon Clavet, Philippe Beaudoin and Pierre Poulin
+ Website: http://www.iro.umontreal.ca/labs/infographie/papers/Clavet-2005-PVFS/
- VECCOPY(start, pa->prev_state.co);
- VECCOPY(end, pa->state.co);
+ Presented at Siggraph, (2005)
- VECCOPY(v, pa->state.vel);
+***********************************************************************************************************/
+#define PSYS_FLUID_SPRINGS_INITIAL_SIZE 256
+static ParticleSpring *add_fluid_spring(ParticleSystem *psys, ParticleSpring *spring)
+{
+ /* Are more refs required? */
+ if(psys->alloc_fluidsprings == 0 || psys->fluid_springs == NULL) {
+ psys->alloc_fluidsprings = PSYS_FLUID_SPRINGS_INITIAL_SIZE;
+ psys->fluid_springs = (ParticleSpring*)MEM_callocN(psys->alloc_fluidsprings * sizeof(ParticleSpring), "Particle Fluid Springs");
+ }
+ else if(psys->tot_fluidsprings == psys->alloc_fluidsprings) {
+ /* Double the number of refs allocated */
+ psys->alloc_fluidsprings *= 2;
+ psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
+ }
- neighbours = BLI_kdtree_range_search(tree, radius, start, NULL, &ptn);
+ memcpy(psys->fluid_springs + psys->tot_fluidsprings, spring, sizeof(ParticleSpring));
+ psys->tot_fluidsprings++;
- /* use ptn[n].co to store relative direction */
- for(n=1; n<neighbours; n++) {
- sub_v3_v3(ptn[n].co, start);
- normalize_v3(ptn[n].co);
- }
-
- /* Viscosity - Algorithm 5 */
- if (omega > 0.f || beta > 0.f) {
- float u, I;
+ return psys->fluid_springs + psys->tot_fluidsprings - 1;
+}
- for(n=1; n<neighbours; n++) {
- second_particle = psys->particles + ptn[n].index;
- q = ptn[n].dist/radius;
-
- sub_v3_v3v3(temp, v, second_particle->prev_state.vel);
-
- u = dot_v3v3(ptn[n].co, temp);
+static void delete_fluid_spring(ParticleSystem *psys, int j)
+{
+ if (j != psys->tot_fluidsprings - 1)
+ psys->fluid_springs[j] = psys->fluid_springs[psys->tot_fluidsprings - 1];
+
+ psys->tot_fluidsprings--;
- if (u > 0){
- I = dtime * ((1-q) * (omega * u + beta * u*u)) * 0.5f;
- madd_v3_v3fl(v, ptn[n].co, -I * massfactor);
- }
- }
+ if (psys->tot_fluidsprings < psys->alloc_fluidsprings/2 && psys->alloc_fluidsprings > PSYS_FLUID_SPRINGS_INITIAL_SIZE){
+ psys->alloc_fluidsprings /= 2;
+ psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
}
+}
+
+static EdgeHash *build_fluid_springhash(ParticleSystem *psys)
+{
+ EdgeHash *springhash = NULL;
+ ParticleSpring *spring;
+ int i = 0;
- /* Hooke's spring force */
- if (fluid->spring_k > 0.f) {
- float D, L = fluid->rest_length;
- for(n=1; n<neighbours; n++) {
- /* L is a factor of radius */
- D = dtime * 10.f * fluid->spring_k * (1.f - L) * (L - ptn[n].dist/radius);
- madd_v3_v3fl(v, ptn[n].co, -D * massfactor);
+ springhash = BLI_edgehash_new();
+
+ for(i=0, spring=psys->fluid_springs; i<psys->tot_fluidsprings; i++, spring++)
+ BLI_edgehash_insert(springhash, spring->particle_index[0], spring->particle_index[1], SET_INT_IN_POINTER(i+1));
+
+ return springhash;
+}
+static void particle_fluidsim(ParticleSystem *psys, int own_psys, ParticleData *pa, float dtime, float mass, float *gravity, EdgeHash *springhash)
+{
+ SPHFluidSettings *fluid = psys->part->fluid;
+ KDTreeNearest *ptn = NULL;
+ ParticleData *npa;
+ ParticleSpring *spring = NULL;
+
+ float temp[3];
+ float q, q1, u, I, D, rij, d, Lij;
+ float pressure_near, pressure;
+ float p=0, pnear=0;
+
+ float omega = fluid->viscosity_omega;
+ float beta = fluid->viscosity_beta;
+ float massfactor = 1.0f/mass;
+ float spring_k = fluid->spring_k;
+ float h = fluid->radius;
+ float L = fluid->rest_length * fluid->radius;
+
+ int n, neighbours = BLI_kdtree_range_search(psys->tree, h, pa->prev_state.co, NULL, &ptn);
+ int spring_index = 0, index = own_psys ? pa - psys->particles : -1;
+
+ /* pressure and near pressure */
+ for(n=own_psys?1:0; n<neighbours; n++) {
+ /* disregard particles at the exact same location */
+ if(ptn[n].dist < FLT_EPSILON)
+ continue;
+
+ sub_v3_v3(ptn[n].co, pa->prev_state.co);
+ mul_v3_fl(ptn[n].co, 1.f/ptn[n].dist);
+ q = ptn[n].dist/h;
+
+ if(q < 1.f) {
+ q1 = 1.f - q;
+
+ p += q1*q1;
+ pnear += q1*q1*q1;
}
}
- /* Update particle position */
- VECADDFAC(end, start, v, dtime);
- /* Double Density Relaxation - Algorithm 2 */
- p = 0;
- pnear = 0;
- for(n=1; n<neighbours; n++) {
- q = ptn[n].dist/radius;
- p += ((1-q)*(1-q));
- pnear += ((1-q)*(1-q)*(1-q));
- }
- p *= part->mass;
- pnear *= part->mass;
+ p *= mass;
+ pnear *= mass;
pressure = fluid->stiffness_k * (p - fluid->rest_density);
pressure_near = fluid->stiffness_knear * pnear;
- for(n=1; n<neighbours; n++) {
- q = ptn[n].dist/radius;
+ /* main calculations */
+ for(n=own_psys?1:0; n<neighbours; n++) {
+ /* disregard particles at the exact same location */
+ if(ptn[n].dist < FLT_EPSILON)
+ continue;
+
+ npa = psys->particles + ptn[n].index;
+
+ rij = ptn[n].dist;
+ q = rij/h;
+ q1 = 1.f-q;
+
+ /* Double Density Relaxation - Algorithm 2 (can't be thread safe!)*/
+ D = dtime * dtime * (pressure + pressure_near*q1)*q1 * 0.5f;
+ madd_v3_v3fl(pa->state.co, ptn[n].co, -D * massfactor);
+ if(own_psys)
+ madd_v3_v3fl(npa->state.co, ptn[n].co, D * massfactor);
+
+ if(index < ptn[n].index) {
+ /* Viscosity - Algorithm 5 */
+ if(omega > 0.f || beta > 0.f) {
+ sub_v3_v3v3(temp, pa->state.vel, npa->state.vel);
+ u = dot_v3v3(ptn[n].co, temp);
+
+ if (u > 0){
+ I = dtime * (q1 * (omega * u + beta * u*u)) * 0.5f;
+ madd_v3_v3fl(pa->state.vel, ptn[n].co, -I * massfactor);
+
+ if(own_psys)
+ madd_v3_v3fl(npa->state.vel, ptn[n].co, I * massfactor);
+ }
+ }
+
+ if(spring_k > 0.f) {
+ /* Viscoelastic spring force - Algorithm 4*/
+ if (fluid->flag & SPH_VISCOELASTIC_SPRINGS && springhash){
+ spring_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(springhash, index, ptn[n].index));
+
+ if(spring_index) {
+ spring = psys->fluid_springs + spring_index - 1;
+ }
+ else {
+ ParticleSpring temp_spring;
+ temp_spring.particle_index[0] = index;
+ temp_spring.particle_index[1] = ptn[n].index;
+ temp_spring.rest_length = (fluid->flag & SPH_CURRENT_REST_LENGTH) ? rij : L;
+ temp_spring.delete_flag = 0;
+
+ spring = add_fluid_spring(psys, &temp_spring);
+ }
- D = dtime * dtime * (pressure*(1-q) + pressure_near*(1-q)*(1-q))* 0.5f;
- madd_v3_v3fl(end, ptn[n].co, -D * massfactor);
- }
+ Lij = spring->rest_length;
+ d = fluid->yield_ratio * Lij;
+
+ if (rij > Lij + d) // Stretch, 25 is just a multiplier for plasticity_constant value to counter default dtime of 1/25
+ spring->rest_length += dtime * 25.f * fluid->plasticity_constant * (rij - Lij - d);
+ else if(rij < Lij - d) // Compress
+ spring->rest_length -= dtime * 25.f * fluid->plasticity_constant * (Lij - d - rij);
+ }
+ else { /* PART_SPRING_HOOKES - Hooke's spring force */
+ /* L is a factor of radius */
+ D = 0.5 * dtime * dtime * 10.f * fluid->spring_k * (1.f - L/h) * (L - rij);
+
+ madd_v3_v3fl(pa->state.co, ptn[n].co, -D * massfactor);
+ if(own_psys)
+ madd_v3_v3fl(npa->state.co, ptn[n].co, D * massfactor);
+ }
+ }
+ }
+ }
/* Artificial buoyancy force in negative gravity direction */
- if (fluid->buoyancy >= 0.f && psys_uses_gravity(sim)) {
+ if (fluid->buoyancy >= 0.f && gravity) {
float B = -dtime * dtime * fluid->buoyancy * (p - fluid->rest_density) * 0.5f;
- madd_v3_v3fl(end, sim->scene->physics_settings.gravity, -B * massfactor);
+ madd_v3_v3fl(pa->state.co, gravity, -B * massfactor);
}
- /* apply final result and recalculate velocity */
- VECCOPY(pa->state.co, end);
- sub_v3_v3v3(pa->state.vel, end, start);
- mul_v3_fl(pa->state.vel, 1.f/dtime);
-
- if(ptn){ MEM_freeN(ptn); ptn=NULL;}
+ if(ptn)
+ MEM_freeN(ptn);
}
-static void apply_particle_fluidsim(ParticleSystem *psys, ParticleData *pa, ParticleSettings *part, ParticleSimulationData *sim, float dfra, float cfra){
+static void apply_particle_fluidsim(Object *ob, ParticleSystem *psys, ParticleData *pa, float dtime, float *gravity, EdgeHash *springhash){
ParticleTarget *pt;
-// float dtime = dfra*psys_get_timestep(sim);
- float particle_mass = part->mass;
- particle_fluidsim(psys, pa, part, sim, dfra, cfra, particle_mass);
+ particle_fluidsim(psys, 1, pa, dtime, psys->part->mass, gravity, springhash);
/*----check other SPH systems (Multifluids) , each fluid has its own parameters---*/
- for(pt=sim->psys->targets.first; pt; pt=pt->next) {
- ParticleSystem *epsys = psys_get_target_system(sim->ob, pt);
+ for(pt=psys->targets.first; pt; pt=pt->next) {
+ ParticleSystem *epsys = psys_get_target_system(ob, pt);
if(epsys)
- particle_fluidsim(epsys, pa, epsys->part, sim, dfra, cfra, particle_mass);
+ particle_fluidsim(epsys, 0, pa, dtime, psys->part->mass, gravity, NULL);
}
/*----------------------------------------------------------------*/
}
+static void apply_fluid_springs(ParticleSystem *psys, float timestep){
+ SPHFluidSettings *fluid = psys->part->fluid;
+ ParticleData *pa1, *pa2;
+ ParticleSpring *spring = psys->fluid_springs;
+
+ float h = fluid->radius;
+ float massfactor = 1.0f/psys->part->mass;
+ float D, Rij[3], rij, Lij;
+ int i;
+
+ if((fluid->flag & SPH_VISCOELASTIC_SPRINGS)==0 || fluid->spring_k == 0.f)
+ return;
+
+ /* Loop through the springs */
+ for(i=0; i<psys->tot_fluidsprings; i++, spring++) {
+ Lij = spring->rest_length;
+
+ if (Lij > h) {
+ spring->delete_flag = 1;
+ }
+ else {
+ pa1 = psys->particles + spring->particle_index[0];
+ pa2 = psys->particles + spring->particle_index[1];
+
+ sub_v3_v3v3(Rij, pa2->prev_state.co, pa1->prev_state.co);
+ rij = normalize_v3(Rij);
+
+ /* Calculate displacement and apply value */
+ D = 0.5f * timestep * timestep * 10.f * fluid->spring_k * (1.f - Lij/h) * (Lij - rij);
+
+ madd_v3_v3fl(pa1->state.co, Rij, -D * pa1->state.time * pa1->state.time * massfactor);
+ madd_v3_v3fl(pa2->state.co, Rij, D * pa2->state.time * pa2->state.time * massfactor);
+ }
+ }
+
+ /* Loop through springs backwaqrds - for efficient delete function */
+ for (i=psys->tot_fluidsprings-1; i >= 0; i--) {
+ if(psys->fluid_springs[i].delete_flag)
+ delete_fluid_spring(psys, i);
+ }
+}
+
/************************************************/
/* Newtonian physics */
/************************************************/
@@ -2422,8 +2456,11 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
ParticleKey states[5], tkey;
float timestep = psys_get_timestep(sim);
float force[3],impulse[3],dx[4][3],dv[4][3],oldpos[3];
- float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=sim->psys->cfra;
+ float dtime=dfra*timestep, time, pa_mass=part->mass, fac /*, fra=sim->psys->cfra*/;
int i, steps=1;
+ ParticleTexture ptex;
+
+ psys_get_texture(sim, pa, &ptex, PAMAP_PHYSICS, cfra);
/* maintain angular velocity */
VECCOPY(pa->state.ave,pa->prev_state.ave);
@@ -2457,6 +2494,9 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
if(part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)
pdDoEffectors(sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse);
+ mul_v3_fl(force, ptex.field);
+ mul_v3_fl(impulse, ptex.field);
+
/* calculate air-particle interaction */
if(part->dragfac!=0.0f){
fac=-part->dragfac*pa->size*pa->size*len_v3(states[i].vel);
@@ -2477,10 +2517,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
if(psys_uses_gravity(sim)
/* normal gravity is too strong for hair so it's disabled by default */
&& (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)) {
- float gravity[3];
- VECCOPY(gravity, sim->scene->physics_settings.gravity);
- mul_v3_fl(gravity, part->effector_weights->global_gravity);
- VECADD(force,force,gravity);
+ madd_v3_v3fl(force, sim->scene->physics_settings.gravity, part->effector_weights->global_gravity * ptex.gravity);
}
/* calculate next state */
@@ -2495,7 +2532,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
if(i==0){
VECADDFAC(states[1].co,states->co,states->vel,dtime*0.5f);
VECADDFAC(states[1].vel,states->vel,force,dtime*0.5f);
- fra=sim->psys->cfra+0.5f*dfra;
+ /*fra=sim->psys->cfra+0.5f*dfra;*/
}
else{
VECADDFAC(pa->state.co,states->co,states[1].vel,dtime);
@@ -2512,7 +2549,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
VECADDFAC(states[1].co,states->co,dx[0],0.5f);
VECADDFAC(states[1].vel,states->vel,dv[0],0.5f);
- fra=sim->psys->cfra+0.5f*dfra;
+ /*fra=sim->psys->cfra+0.5f*dfra;*/
break;
case 1:
VECADDFAC(dx[1],states->vel,dv[0],0.5f);
@@ -2531,7 +2568,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
VECADD(states[3].co,states->co,dx[2]);
VECADD(states[3].vel,states->vel,dv[2]);
- fra=cfra;
+ /*fra=cfra;*/
break;
case 3:
VECADD(dx[3],states->vel,dv[2]);
@@ -2561,8 +2598,8 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
}
/* damp affects final velocity */
- if(part->dampfac!=0.0)
- mul_v3_fl(pa->state.vel,1.0f-part->dampfac);
+ if(part->dampfac != 0.f)
+ mul_v3_fl(pa->state.vel, 1.f - part->dampfac * ptex.damp);
VECCOPY(pa->state.ave, states->ave);
@@ -2772,23 +2809,26 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B
MVert *x = col->md->x;
MVert *v = col->md->current_v;
float vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], t;
+ float x0[3], x1[3], x2[3], x3[3];
+ float *t0=x0, *t1=x1, *t2=x2, *t3=(face->v4 ? x3 : NULL);
- float *t0, *t1, *t2, *t3;
- t0 = x[ face->v1 ].co;
- t1 = x[ face->v2 ].co;
- t2 = x[ face->v3 ].co;
- t3 = face->v4 ? x[ face->v4].co : NULL;
+ /* move collision face to start of timestep */
+ madd_v3_v3v3fl(t0, x[face->v1].co, v[face->v1].co, col->cfra);
+ madd_v3_v3v3fl(t1, x[face->v2].co, v[face->v2].co, col->cfra);
+ madd_v3_v3v3fl(t2, x[face->v3].co, v[face->v3].co, col->cfra);
+ if(t3)
+ madd_v3_v3v3fl(t3, x[face->v4].co, v[face->v4].co, col->cfra);
/* calculate average velocity of face */
- VECCOPY(vel, v[ face->v1 ].co);
- VECADD(vel, vel, v[ face->v2 ].co);
- VECADD(vel, vel, v[ face->v3 ].co);
- mul_v3_fl(vel, 0.33334f);
+ copy_v3_v3(vel, v[ face->v1 ].co);
+ add_v3_v3(vel, v[ face->v2 ].co);
+ add_v3_v3(vel, v[ face->v3 ].co);
+ mul_v3_fl(vel, 0.33334f*col->dfra);
/* substract face velocity, in other words convert to
a coordinate system where only the particle moves */
- VECADDFAC(co1, col->co1, vel, -col->t);
- VECSUB(co2, col->co2, vel);
+ madd_v3_v3v3fl(co1, col->co1, vel, -col->f);
+ sub_v3_v3v3(co2, col->co2, vel);
do
{
@@ -2836,11 +2876,18 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B
} while(t2);
}
-/* particle - mesh collision code */
-/* in addition to basic point to surface collisions handles friction & damping,*/
-/* angular momentum <-> linear momentum and swept sphere - mesh collisions */
-/* 1. check for all possible deflectors for closest intersection on particle path */
-/* 2. if deflection was found kill the particle or calculate new coordinates */
+/* Particle - Mesh collision code
+ * Features:
+ * - point and swept sphere to mesh surface collisions
+ * - moving colliders (but not yet rotating or deforming colliders)
+ * - friction & damping
+ * - angular momentum <-> linear momentum
+ * - high accuracy by re-applying particle acceleration after collision
+ * - behaves relatively well even if limit of 10 collisions per simulation step is exceeded
+ * Main parts:
+ * 1. check for all possible deflectors for closest intersection on particle path
+ * 2. if deflection was found calculate new coordinates or kill the particle
+ */
static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, float cfra){
Object *ground_ob = NULL;
ParticleSettings *part = sim->psys->part;
@@ -2848,20 +2895,22 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
ParticleCollision col;
ColliderCache *coll;
BVHTreeRayHit hit;
- float ray_dir[3], zerovec[3]={0.0,0.0,0.0};
+ float ray_dir[3], acc[3];
float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f), boid_z = 0.0f;
- float timestep = psys_get_timestep(sim);
+ float timestep = psys_get_timestep(sim) * dfra;
+ float inv_timestep = 1.0f/timestep;
int deflections=0, max_deflections=10;
- VECCOPY(col.co1, pa->prev_state.co);
- VECCOPY(col.co2, pa->state.co);
-
- VECCOPY(col.ve1, pa->prev_state.vel);
- VECCOPY(col.ve2, pa->state.vel);
- mul_v3_fl(col.ve1, timestep * dfra);
- mul_v3_fl(col.ve2, timestep * dfra);
-
- col.t = 0.0f;
+ /* get acceleration (from gravity, forcefields etc. to be re-applied after collision) */
+ sub_v3_v3v3(acc, pa->state.vel, pa->prev_state.vel);
+ mul_v3_fl(acc, inv_timestep);
+
+ /* set values for first iteration */
+ copy_v3_v3(col.co1, pa->prev_state.co);
+ copy_v3_v3(col.co2, pa->state.co);
+ copy_v3_v3(col.ve1, pa->prev_state.vel);
+ copy_v3_v3(col.ve2, pa->state.vel);
+ col.f = 0.0f;
/* override for boids */
if(part->phystype == PART_PHYS_BOIDS) {
@@ -2875,10 +2924,13 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
if(sim->colliders) while(deflections < max_deflections){
/* 1. */
- VECSUB(ray_dir, col.co2, col.co1);
+ sub_v3_v3v3(ray_dir, col.co2, col.co1);
hit.index = -1;
hit.dist = col.ray_len = len_v3(ray_dir);
+ col.cfra = fmod(cfra-dfra, 1.0f);
+ col.dfra = dfra;
+
/* even if particle is stationary we want to check for moving colliders */
/* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */
if(hit.dist == 0.0f)
@@ -2903,45 +2955,49 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
/* 2. */
if(hit.index>=0) {
PartDeflect *pd = col.hit_ob->pd;
- int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0;
- float co[3]; /* point of collision */
- float vec[3]; /* movement through collision */
- float acc[3]; /* acceleration */
-
- float x = hit.dist/col.ray_len; /* location of collision between this iteration */
- float le = len_v3(col.ve1)/col.ray_len;
- float ac = len_v3(col.ve2)/col.ray_len - le; /* (taking acceleration into account) */
- float t = (-le + sqrt(le*le + 2*ac*x))/ac; /* time of collision between this iteration */
- float dt = col.t + x * (1.0f - col.t); /* time of collision between frame change*/
- float it = 1.0 - t;
+ float co[3]; /* point of collision */
+ float x = hit.dist/col.ray_len; /* location factor of collision between this iteration */
+ float f = col.f + x * (1.0f - col.f); /* time factor of collision between timestep */
+ float dt1 = (f - col.f) * timestep; /* time since previous collision (in seconds) */
+ float dt2 = (1.0f - f) * timestep; /* time left after collision (in seconds) */
+ int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */
+
+ deflections++;
interp_v3_v3v3(co, col.co1, col.co2, x);
- VECSUB(vec, col.co2, col.co1);
-
- VECSUB(acc, col.ve2, col.ve1);
- mul_v3_fl(col.vel, 1.0f-col.t);
+ /* make sure we don't hit the current face again */
+ /* TODO: could/should this be proportional to pa->size? */
+ madd_v3_v3fl(co, col.nor, (through ? -0.0001f : 0.0001f));
/* particle dies in collision */
if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) {
pa->alive = PARS_DYING;
- pa->dietime = pa->state.time + (cfra - pa->state.time) * dt;
-
- /* we have to add this for dying particles too so that reactors work correctly */
- VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f));
+ pa->dietime = sim->psys->cfra + (cfra - sim->psys->cfra) * f;
- VECCOPY(pa->state.co, co);
- interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, dt);
- interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, dt);
- interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, dt);
+ copy_v3_v3(pa->state.co, co);
+ interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, f);
+ interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, f);
+ interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, f);
/* particle is dead so we don't need to calculate further */
- deflections=max_deflections;
+ return;
}
+ /* figure out velocity and other data after collision */
else {
- float nor_vec[3], tan_vec[3], tan_vel[3];
+ float v0[3]; /* velocity directly before collision to be modified into velocity directly after collision */
+ float v0_nor[3];/* normal component of v0 */
+ float v0_tan[3];/* tangential component of v0 */
+ float vc_tan[3];/* tangential component of collision surface velocity */
+ float check[3];
+ float v0_dot, vc_dot, check_dot;
float damp, frict;
- float inp, inp_v;
+
+ /* get exact velocity right before collision */
+ madd_v3_v3v3fl(v0, col.ve1, acc, dt1);
+
+ /* convert collider velocity from 1/framestep to 1/s */
+ mul_v3_fl(col.vel, inv_timestep);
/* get damping & friction factors */
damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f);
@@ -2951,119 +3007,118 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
CLAMP(frict,0.0,1.0);
/* treat normal & tangent components separately */
- inp = dot_v3v3(col.nor, vec);
- inp_v = dot_v3v3(col.nor, col.vel);
-
- VECADDFAC(tan_vec, vec, col.nor, -inp);
- VECADDFAC(tan_vel, col.vel, col.nor, -inp_v);
- if((part->flag & PART_ROT_DYN)==0)
- interp_v3_v3v3(tan_vec, tan_vec, tan_vel, frict);
-
- VECCOPY(nor_vec, col.nor);
- inp *= 1.0f - damp;
+ v0_dot = dot_v3v3(col.nor, v0);
+ madd_v3_v3v3fl(v0_tan, v0, col.nor, -v0_dot);
- if(through)
- inp_v *= damp;
+ vc_dot = dot_v3v3(col.nor, col.vel);
+ madd_v3_v3v3fl(vc_tan, col.vel, col.nor, -vc_dot);
- /* special case for object hitting the particle from behind */
- if(through==0 && ((inp_v>0 && inp>0 && inp_v>inp) || (inp_v<0 && inp<0 && inp_v<inp)))
- mul_v3_fl(nor_vec, inp_v);
- else
- mul_v3_fl(nor_vec, inp_v + (through ? 1.0f : -1.0f) * inp);
-
- /* angular <-> linear velocity - slightly more physical and looks even nicer than before */
- if(part->flag & PART_ROT_DYN) {
- float surface_vel[3], rot_vel[3], friction[3], dave[3], dvel[3];
-
- /* apparent velocity along collision surface */
- VECSUB(surface_vel, tan_vec, tan_vel);
+ /* handle friction effects (tangential and angular velocity) */
+ if(frict > 0.0f) {
+ /* angular <-> linear velocity */
+ if(part->flag & PART_ROT_DYN) {
+ float vr_tan[3], v1_tan[3], ave[3];
+
+ /* linear velocity of particle surface */
+ cross_v3_v3v3(vr_tan, col.nor, pa->state.ave);
+ mul_v3_fl(vr_tan, pa->size);
- /* direction of rolling friction */
- cross_v3_v3v3(rot_vel, pa->state.ave, col.nor);
- /* convert to current dt */
- mul_v3_fl(rot_vel, (timestep*dfra) * (1.0f - col.t));
- mul_v3_fl(rot_vel, pa->size);
+ /* change to coordinates that move with the collision plane */
+ sub_v3_v3v3(v1_tan, v0_tan, vc_tan);
+
+ /* The resulting velocity is a weighted average of particle cm & surface
+ * velocity. This weight (related to particle's moment of inertia) could
+ * be made a parameter for angular <-> linear conversion.
+ */
+ madd_v3_v3fl(v1_tan, vr_tan, -0.4);
+ mul_v3_fl(v1_tan, 1.0f/1.4f); /* 1/(1+0.4) */
- /* apply sliding friction */
- VECSUB(surface_vel, surface_vel, rot_vel);
- VECCOPY(friction, surface_vel);
+ /* rolling friction is around 0.01 of sliding friction (could be made a parameter) */
+ mul_v3_fl(v1_tan, 1.0f - 0.01f * frict);
- mul_v3_fl(surface_vel, 1.0 - frict);
- mul_v3_fl(friction, frict);
+ /* surface_velocity is opposite to cm velocity */
+ mul_v3_v3fl(vr_tan, v1_tan, -1.0f);
- /* sliding changes angular velocity */
- cross_v3_v3v3(dave, col.nor, friction);
- mul_v3_fl(dave, 1.0f/MAX2(pa->size, 0.001));
+ /* get back to global coordinates */
+ add_v3_v3(v1_tan, vc_tan);
- /* we assume rolling friction is around 0.01 of sliding friction */
- mul_v3_fl(rot_vel, 1.0 - frict*0.01);
+ /* convert to angular velocity*/
+ cross_v3_v3v3(ave, vr_tan, col.nor);
+ mul_v3_fl(ave, 1.0f/MAX2(pa->size, 0.001));
- /* change in angular velocity has to be added to the linear velocity too */
- cross_v3_v3v3(dvel, dave, col.nor);
- mul_v3_fl(dvel, pa->size);
- VECADD(rot_vel, rot_vel, dvel);
+ /* only friction will cause change in linear & angular velocity */
+ interp_v3_v3v3(pa->state.ave, pa->state.ave, ave, frict);
+ interp_v3_v3v3(v0_tan, v0_tan, v1_tan, frict);
+ }
+ else {
+ /* just basic friction (unphysical due to the friction model used in Blender) */
+ interp_v3_v3v3(v0_tan, v0_tan, vc_tan, frict);
+ }
+ }
- VECADD(surface_vel, surface_vel, rot_vel);
- VECADD(tan_vec, surface_vel, tan_vel);
+ /* stickness was possibly added before, so cancel that before calculating new normal velocity */
+ /* otherwise particles go flying out of the surface because of high reversed sticky velocity */
+ if(v0_dot < 0.0f) {
+ v0_dot += pd->pdef_stickness;
+ if(v0_dot > 0.0f)
+ v0_dot = 0.0f;
+ }
- /* convert back to normal time */
- mul_v3_fl(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001));
+ /* damping and flipping of velocity around normal */
+ v0_dot *= 1.0f - damp;
+ vc_dot *= through ? damp : 1.0f;
- mul_v3_fl(pa->state.ave, 1.0 - frict*0.01);
- VECADD(pa->state.ave, pa->state.ave, dave);
- }
+ /* special case for object hitting the particle from behind */
+ if(through==0 && ((vc_dot>0.0f && v0_dot>0.0f && vc_dot>v0_dot) || (vc_dot<0.0f && v0_dot<0.0f && vc_dot<v0_dot)))
+ mul_v3_v3fl(v0_nor, col.nor, vc_dot);
+ else
+ mul_v3_v3fl(v0_nor, col.nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot);
/* combine components together again */
- VECADD(vec, nor_vec, tan_vec);
-
- /* make sure we don't hit the current face again */
- VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f));
+ add_v3_v3v3(v0, v0_nor, v0_tan);
+ /* keep boids above ground */
if(part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) {
BoidParticle *bpa = pa->boid;
if(bpa->data.mode == eBoidMode_OnLand || co[2] <= boid_z) {
co[2] = boid_z;
- vec[2] = 0.0f;
+ v0[2] = 0.0f;
}
}
-
- /* set coordinates for next iteration */
- /* apply acceleration to final position, but make sure particle stays above surface */
- madd_v3_v3v3fl(acc, vec, acc, it);
- ac = dot_v3v3(acc, col.nor);
- if((!through && ac < 0.0f) || (through && ac > 0.0f))
- madd_v3_v3fl(acc, col.nor, -ac);
-
- VECCOPY(col.co1, co);
- VECADDFAC(col.co2, co, acc, it);
-
- VECCOPY(col.ve1, vec);
- VECCOPY(col.ve2, acc);
-
- if(len_v3(vec) < 0.001 && len_v3v3(pa->state.co, pa->prev_state.co) < 0.001) {
- /* kill speed to stop slipping */
- VECCOPY(pa->state.vel,zerovec);
- VECCOPY(pa->state.co, co);
- if(part->flag & PART_ROT_DYN) {
- VECCOPY(pa->state.ave,zerovec);
- }
- }
- else {
- VECCOPY(pa->state.co, col.co2);
- mul_v3_v3fl(pa->state.vel, acc, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001));
-
+ if(deflections < max_deflections) {
+ /* re-apply acceleration to final velocity and location */
+ madd_v3_v3v3fl(pa->state.vel, v0, acc, dt2);
+ madd_v3_v3v3fl(pa->state.co, co, v0, dt2);
+ madd_v3_v3fl(pa->state.co, acc, 0.5f*dt2*dt2);
+
+ /* make sure particle stays on the right side of the surface */
+ sub_v3_v3v3(check, pa->state.co, co);
+ /* (collision surface has moved during the time too) */
+ madd_v3_v3fl(check, col.vel, -dt2);
+
+ check_dot = dot_v3v3(check, col.nor);
+ if((!through && check_dot < 0.0f) || (through && check_dot > 0.0f))
+ madd_v3_v3fl(pa->state.co, col.nor, (through ? -0.0001f : 0.0001f) - check_dot);
+
/* Stickness to surface */
- normalize_v3(nor_vec);
madd_v3_v3fl(pa->state.vel, col.nor, -pd->pdef_stickness);
- }
- col.t = dt;
- }
- deflections++;
+ /* set coordinates for next iteration */
+ copy_v3_v3(col.co1, co);
+ copy_v3_v3(col.co2, pa->state.co);
- //reaction_state.time = cfra - (1.0f - dt) * dfra;
- //push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state);
+ copy_v3_v3(col.ve1, v0);
+ copy_v3_v3(col.ve2, pa->state.vel);
+
+ col.f = f;
+ }
+ else {
+ /* final chance to prevent failure, so stick to the surface and hope for the best */
+ madd_v3_v3v3fl(pa->state.co, co, col.vel, dt2);
+ copy_v3_v3(pa->state.vel, v0);
+ }
+ }
}
else
return;
@@ -3244,7 +3299,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
psys->clmd->point_cache = psys->pointcache;
psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
- psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, 0, 0);
+ psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm);
psys->clmd->sim_parms->effector_weights = NULL;
}
@@ -3269,11 +3324,11 @@ static void hair_step(ParticleSimulationData *sim, float cfra)
psys_calc_dmcache(sim->ob, sim->psmd->dm, psys);
if(psys->clmd)
- cloth_free_modifier(sim->ob, psys->clmd);
+ cloth_free_modifier(psys->clmd);
}
- /* dynamics with cloth simulation */
- if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS)
+ /* dynamics with cloth simulation, psys->particles can be NULL with 0 particles [#25519] */
+ if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS && psys->particles)
do_hair_dynamics(sim);
/* following lines were removed r29079 but cause bug [#22811], see report for details */
@@ -3283,20 +3338,17 @@ static void hair_step(ParticleSimulationData *sim, float cfra)
psys->flag |= PSYS_HAIR_UPDATED;
}
-static void save_hair(ParticleSimulationData *sim, float cfra){
+static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)){
Object *ob = sim->ob;
ParticleSystem *psys = sim->psys;
HairKey *key, *root;
PARTICLE_P;
- int totpart;
invert_m4_m4(ob->imat, ob->obmat);
psys->lattice= psys_get_lattice(sim);
if(psys->totpart==0) return;
-
- totpart=psys->totpart;
/* save new keys for elements if needed */
LOOP_PARTICLES {
@@ -3338,12 +3390,11 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
ParticleSystem *psys = sim->psys;
ParticleSettings *part=psys->part;
BoidBrainData bbd;
+ ParticleTexture ptex;
PARTICLE_P;
float timestep;
- /* current time */
- float ctime;
/* frame & time changes */
- float dfra, dtime, pa_dtime, pa_dfra=0.0;
+ float dfra, dtime;
float birthtime, dietime;
/* where have we gone in time since last time */
@@ -3351,11 +3402,11 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
timestep = psys_get_timestep(sim);
dtime= dfra*timestep;
- ctime= cfra*timestep;
if(dfra<0.0){
LOOP_EXISTING_PARTICLES {
- pa->size = part->size;
+ psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
+ pa->size = part->size*ptex.size;
if(part->randsize > 0.0)
pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1);
@@ -3369,65 +3420,67 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
psys_update_effectors(sim);
if(part->type != PART_HAIR)
- sim->colliders = get_collider_cache(sim->scene, NULL, NULL);
+ sim->colliders = get_collider_cache(sim->scene, sim->ob, NULL);
- if(part->phystype==PART_PHYS_BOIDS){
- ParticleTarget *pt = psys->targets.first;
- bbd.sim = sim;
- bbd.part = part;
- bbd.cfra = cfra;
- bbd.dfra = dfra;
- bbd.timestep = timestep;
+ /* initialize physics type specific stuff */
+ switch(part->phystype) {
+ case PART_PHYS_BOIDS:
+ {
+ ParticleTarget *pt = psys->targets.first;
+ bbd.sim = sim;
+ bbd.part = part;
+ bbd.cfra = cfra;
+ bbd.dfra = dfra;
+ bbd.timestep = timestep;
- psys_update_particle_tree(psys, cfra);
+ psys_update_particle_tree(psys, cfra);
- boids_precalc_rules(part, cfra);
+ boids_precalc_rules(part, cfra);
- for(; pt; pt=pt->next) {
- if(pt->ob)
- psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra);
+ for(; pt; pt=pt->next) {
+ if(pt->ob)
+ psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra);
+ }
+ break;
}
- }
- else if(part->phystype==PART_PHYS_FLUID){
- ParticleTarget *pt = psys->targets.first;
- psys_update_particle_tree(psys, cfra);
-
- for(; pt; pt=pt->next) { /* Updating others systems particle tree for fluid-fluid interaction */
- if(pt->ob) psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra);
+ case PART_PHYS_FLUID:
+ {
+ ParticleTarget *pt = psys->targets.first;
+ psys_update_particle_tree(psys, cfra);
+
+ for(; pt; pt=pt->next) { /* Updating others systems particle tree for fluid-fluid interaction */
+ if(pt->ob)
+ psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra);
+ }
+ break;
}
}
-
- /* main loop: calculate physics for all particles */
+ /* initialize all particles for dynamics */
LOOP_SHOWN_PARTICLES {
copy_particle_key(&pa->prev_state,&pa->state,1);
- pa->size = part->size;
+ psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
+
+ pa->size = part->size*ptex.size;
if(part->randsize > 0.0)
pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1);
- ///* reactions can change birth time so they need to be checked first */
- //if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0)
- // react_to_events(psys,p);
-
birthtime = pa->time;
dietime = birthtime + pa->lifetime;
- pa_dfra = dfra;
- pa_dtime = dtime;
-
+ /* store this, so we can do multiple loops over particles */
+ pa->state.time = dfra;
if(dietime <= cfra && psys->cfra < dietime){
/* particle dies some time between this and last step */
- pa_dfra = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra);
- pa_dtime = pa_dfra * timestep;
+ pa->state.time = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra);
pa->alive = PARS_DYING;
}
else if(birthtime <= cfra && birthtime >= psys->cfra){
/* particle is born some time between this and last step*/
- reset_particle(sim, pa, dtime, cfra);
+ reset_particle(sim, pa, dfra*timestep, cfra);
pa->alive = PARS_ALIVE;
- pa_dfra = cfra - birthtime;
- pa_dtime = pa_dfra*timestep;
+ pa->state.time = cfra - birthtime;
}
else if(dietime < cfra){
/* nothing to be done when particle is dead */
@@ -3440,63 +3493,100 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
else if(part->phystype == PART_PHYS_NO)
reset_particle(sim, pa, dtime, cfra);
- if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){
- switch(part->phystype){
- case PART_PHYS_NEWTON:
- /* do global forces & effectors */
- apply_particle_forces(sim, p, pa_dfra, cfra);
-
+ if(ELEM(pa->alive, PARS_ALIVE, PARS_DYING)==0 || (pa->flag & (PARS_UNEXIST|PARS_NO_DISP)))
+ pa->state.time = -1.f;
+ }
+
+ switch(part->phystype) {
+ case PART_PHYS_NEWTON:
+ {
+ LOOP_DYNAMIC_PARTICLES {
+ /* do global forces & effectors */
+ apply_particle_forces(sim, p, pa->state.time, cfra);
+
+ /* deflection */
+ if(sim->colliders)
+ deflect_particle(sim, p, pa->state.time, cfra);
+
+ /* rotations */
+ rotate_particle(part, pa, pa->state.time, timestep);
+ }
+ break;
+ }
+ case PART_PHYS_BOIDS:
+ {
+ LOOP_DYNAMIC_PARTICLES {
+ bbd.goal_ob = NULL;
+
+ boid_brain(&bbd, p, pa);
+
+ if(pa->alive != PARS_DYING) {
+ boid_body(&bbd, pa);
+
/* deflection */
if(sim->colliders)
- deflect_particle(sim, p, pa_dfra, cfra);
-
- /* rotations */
- rotate_particle(part, pa, pa_dfra, timestep);
- break;
- case PART_PHYS_BOIDS:
- {
- bbd.goal_ob = NULL;
- boid_brain(&bbd, p, pa);
- if(pa->alive != PARS_DYING) {
- boid_body(&bbd, pa);
-
- /* deflection */
- if(sim->colliders)
- deflect_particle(sim, p, pa_dfra, cfra);
- }
- break;
+ deflect_particle(sim, p, pa->state.time, cfra);
}
- case PART_PHYS_FLUID:
- {
- /* do global forces & effectors */
- apply_particle_forces(sim, p, pa_dfra, cfra);
+ }
+ break;
+ }
+ case PART_PHYS_FLUID:
+ {
+ EdgeHash *springhash = build_fluid_springhash(psys);
+ float *gravity = NULL;
- /* do fluid sim */
- apply_particle_fluidsim(psys, pa, part, sim, pa_dfra, cfra);
+ if(psys_uses_gravity(sim))
+ gravity = sim->scene->physics_settings.gravity;
- /* deflection */
- if(sim->colliders)
- deflect_particle(sim, p, pa_dfra, cfra);
-
- /* rotations, SPH particles are not physical particles, just interpolation particles, thus rotation has not a direct sense for them */
- rotate_particle(part, pa, pa_dfra, timestep);
- break;
- }
+ /* do global forces & effectors */
+ LOOP_DYNAMIC_PARTICLES {
+ apply_particle_forces(sim, p, pa->state.time, cfra);
+ /* in fluids forces only effect velocity */
+ copy_v3_v3(pa->state.co, pa->prev_state.co);
+ }
+
+ /* actual fluids calculations (not threadsafe!) */
+ LOOP_DYNAMIC_PARTICLES {
+ apply_particle_fluidsim(sim->ob, psys, pa, pa->state.time*timestep, gravity, springhash);
}
- if(pa->alive == PARS_DYING){
- //push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state);
+ /* Apply springs to particles */
+ apply_fluid_springs(psys, timestep);
+
+ /* apply velocity, collisions and rotation */
+ LOOP_DYNAMIC_PARTICLES {
+ /* velocity holds forces and viscosity, so apply them before collisions */
+ madd_v3_v3fl(pa->state.co, pa->state.vel, pa->state.time*timestep);
+
+ /* calculate new velocity based on new-old location */
+ sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
+ mul_v3_fl(pa->state.vel, 1.f/(pa->state.time*timestep));
- pa->alive=PARS_DEAD;
- pa->state.time=pa->dietime;
+ if(sim->colliders)
+ deflect_particle(sim, p, pa->state.time, cfra);
+
+ /* SPH particles are not physical particles, just interpolation particles, thus rotation has not a direct sense for them */
+ rotate_particle(part, pa, pa->state.time, timestep);
}
- else
- pa->state.time=cfra;
- //push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state);
+ if(springhash) {
+ BLI_edgehash_free(springhash, NULL);
+ springhash = NULL;
+ }
+ break;
}
}
+ /* finalize particle state and time after dynamics */
+ LOOP_DYNAMIC_PARTICLES {
+ if(pa->alive == PARS_DYING){
+ pa->alive=PARS_DEAD;
+ pa->state.time=pa->dietime;
+ }
+ else
+ pa->state.time=cfra;
+ }
+
free_collider_cache(&sim->colliders);
}
static void update_children(ParticleSimulationData *sim)
@@ -3504,8 +3594,12 @@ static void update_children(ParticleSimulationData *sim)
if((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0)
/* don't generate children while growing hair - waste of time */
psys_free_children(sim->psys);
- else if(sim->psys->part->childtype && sim->psys->totchild != get_psys_tot_child(sim->scene, sim->psys))
- distribute_particles(sim, PART_FROM_CHILD);
+ else if(sim->psys->part->childtype) {
+ if(sim->psys->totchild != get_psys_tot_child(sim->scene, sim->psys))
+ distribute_particles(sim, PART_FROM_CHILD);
+ else
+ ; /* Children are up to date, nothing to do. */
+ }
else
psys_free_children(sim->psys);
}
@@ -3514,8 +3608,9 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
{
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
+ ParticleTexture ptex;
PARTICLE_P;
- float disp, birthtime, dietime;
+ float disp, dietime;
BLI_srandom(psys->seed);
@@ -3524,13 +3619,13 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
disp= (float)psys_get_current_display_percentage(psys)/100.0f;
LOOP_PARTICLES {
- pa->size = part->size;
+ psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
+ pa->size = part->size*ptex.size;
if(part->randsize > 0.0)
pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1);
psys->lattice= psys_get_lattice(sim);
- birthtime = pa->time;
dietime = pa->dietime;
/* update alive status and push events */
@@ -3556,7 +3651,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
}
}
-static void particles_fluid_step(ParticleSimulationData *sim, int cfra)
+static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra))
{
ParticleSystem *psys = sim->psys;
if(psys->particles){
@@ -3573,26 +3668,23 @@ static void particles_fluid_step(ParticleSimulationData *sim, int cfra)
if( fluidmd && fluidmd->fss) {
FluidsimSettings *fss= fluidmd->fss;
ParticleSettings *part = psys->part;
- ParticleData *pa=0;
- char *suffix = "fluidsurface_particles_####";
- char *suffix2 = ".gz";
+ ParticleData *pa=NULL;
char filename[256];
char debugStrBuffer[256];
int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
- int p, j, numFileParts, totpart;
+ int p, j, totpart;
int readMask, activeParts = 0, fileParts = 0;
gzFile gzf;
// XXX if(ob==G.obedit) // off...
// return;
-
+
// ok, start loading
- strcpy(filename, fss->surfdataPath);
- strcat(filename, suffix);
- BLI_path_abs(filename, G.sce);
+ BLI_snprintf(filename, sizeof(filename), "%sfluidsurface_particles_####.gz", fss->surfdataPath);
+
+ BLI_path_abs(filename, G.main->name);
BLI_path_frame(filename, curFrame, 0); // fixed #frame-no
- strcat(filename, suffix2);
-
+
gzf = gzopen(filename, "rb");
if (!gzf) {
snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename);
@@ -3601,16 +3693,14 @@ static void particles_fluid_step(ParticleSimulationData *sim, int cfra)
}
gzread(gzf, &totpart, sizeof(totpart));
- numFileParts = totpart;
totpart = (G.rendering)?totpart:(part->disp*totpart)/100;
part->totpart= totpart;
part->sta=part->end = 1.0f;
part->lifetime = sim->scene->r.efra + 1;
- /* initialize particles */
+ /* allocate particles */
realloc_particles(sim, part->totpart);
- initialize_all_particles(sim);
// set up reading mask
readMask = fss->typeFlags;
@@ -3642,6 +3732,9 @@ static void particles_fluid_step(ParticleSimulationData *sim, int cfra)
pa->state.rot[0] = 1.0;
pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0;
+ pa->time = 1.f;
+ pa->dietime = sim->scene->r.efra + 1;
+ pa->lifetime = sim->scene->r.efra;
pa->alive = PARS_ALIVE;
//if(a<25) fprintf(stderr,"FSPARTICLE debug set %s , a%d = %f,%f,%f , life=%f \n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime );
} else {
@@ -3664,19 +3757,11 @@ static void particles_fluid_step(ParticleSimulationData *sim, int cfra)
#endif // DISABLE_ELBEEM
}
-static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float cfra)
+static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra))
{
ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
int oldtotpart = psys->totpart;
- int totpart = oldtotpart;
-
- if(pid && psys->pointcache->flag & PTCACHE_EXTERNAL)
- totpart = pid->cache->totpoint;
- else if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT)
- totpart = part->grid_res*part->grid_res*part->grid_res;
- else
- totpart = psys->part->totpart;
+ int totpart = tot_particles(psys, pid);
if(totpart != oldtotpart)
realloc_particles(sim, totpart);
@@ -3694,94 +3779,84 @@ static void system_step(ParticleSimulationData *sim, float cfra)
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
PointCache *cache = psys->pointcache;
- PTCacheID pid, *use_cache = NULL;
+ PTCacheID ptcacheid, *pid = NULL;
PARTICLE_P;
- int oldtotpart;
- float disp; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */
- int init= 0, emit= 0; //, only_children_changed= 0;
- int framenr, framedelta, startframe = 0, endframe = 100;
-
- framenr= (int)sim->scene->r.cfra;
- framedelta= framenr - cache->simframe;
+ float disp, cache_cfra = cfra; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */
+ int startframe = 0, endframe = 100, oldtotpart = 0;
/* cache shouldn't be used for hair or "continue physics" */
if(part->type != PART_HAIR && BKE_ptcache_get_continue_physics() == 0) {
- BKE_ptcache_id_from_particles(&pid, sim->ob, psys);
- use_cache = &pid;
- }
-
- if(use_cache) {
- psys_clear_temp_pointcache(sim->psys);
+ psys_clear_temp_pointcache(psys);
/* set suitable cache range automatically */
if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0)
- psys_get_pointcache_start_end(sim->scene, sim->psys, &cache->startframe, &cache->endframe);
-
- BKE_ptcache_id_time(&pid, sim->scene, 0.0f, &startframe, &endframe, NULL);
+ psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe);
- /* simulation is only active during a specific period */
- if(framenr < startframe) {
- psys_reset(psys, PSYS_RESET_CACHE_MISS);
- return;
- }
- else if(framenr > endframe) {
- framenr= endframe;
- }
+ pid = &ptcacheid;
+ BKE_ptcache_id_from_particles(pid, sim->ob, psys);
- if(framenr == startframe) {
- BKE_ptcache_id_reset(sim->scene, use_cache, PTCACHE_RESET_OUTDATED);
- BKE_ptcache_validate(cache, framenr);
+ BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL);
+
+ /* clear everythin on start frame */
+ if((int)cfra == startframe) {
+ BKE_ptcache_id_reset(sim->scene, pid, PTCACHE_RESET_OUTDATED);
+ BKE_ptcache_validate(cache, startframe);
cache->flag &= ~PTCACHE_REDO_NEEDED;
}
+
+ CLAMP(cache_cfra, startframe, endframe);
}
-/* 1. emit particles */
-
- /* verify if we need to reallocate */
+/* 1. emit particles and redo particles if needed */
oldtotpart = psys->totpart;
-
- emit = emit_particles(sim, use_cache, cfra);
- if(use_cache && emit > 0)
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, cfra);
- init = emit*emit + (psys->recalc & PSYS_RECALC_RESET);
-
- if(init) {
+ if(emit_particles(sim, pid, cfra) || psys->recalc & PSYS_RECALC_RESET) {
distribute_particles(sim, part->from);
initialize_all_particles(sim);
+ /* reset only just created particles (on startframe all particles are recreated) */
reset_all_particles(sim, 0.0, cfra, oldtotpart);
+ if (psys->fluid_springs) {
+ MEM_freeN(psys->fluid_springs);
+ psys->fluid_springs = NULL;
+ }
+
+ psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
+
/* flag for possible explode modifiers after this system */
sim->psmd->flag |= eParticleSystemFlag_Pars;
+
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
}
/* 2. try to read from the cache */
- if(use_cache) {
- int cache_result = BKE_ptcache_read_cache(use_cache, cfra, sim->scene->r.frs_sec);
+ if(pid) {
+ int cache_result = BKE_ptcache_read(pid, cache_cfra);
if(ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
cached_step(sim, cfra);
update_children(sim);
psys_update_path_cache(sim, cfra);
- BKE_ptcache_validate(cache, framenr);
+ BKE_ptcache_validate(cache, (int)cache_cfra);
if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_write_cache(use_cache, framenr);
+ BKE_ptcache_write(pid, (int)cache_cfra);
return;
}
+ /* Cache is supposed to be baked, but no data was found so bail out */
+ else if(cache->flag & PTCACHE_BAKED) {
+ psys_reset(psys, PSYS_RESET_CACHE_MISS);
+ return;
+ }
else if(cache_result == PTCACHE_READ_OLD) {
psys->cfra = (float)cache->simframe;
cached_step(sim, psys->cfra);
}
- else if(cfra != startframe && ( /*sim->ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED))) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */
- psys_reset(psys, PSYS_RESET_CACHE_MISS);
- return;
- }
/* if on second frame, write cache for first frame */
if(psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
- BKE_ptcache_write_cache(use_cache, startframe);
+ BKE_ptcache_write(pid, startframe);
}
else
BKE_ptcache_invalidate(cache);
@@ -3804,7 +3879,7 @@ static void system_step(ParticleSimulationData *sim, float cfra)
/* handle negative frame start at the first frame by doing
* all the steps before the first frame */
- if(framenr == startframe && part->sta < startframe)
+ if((int)cfra == startframe && part->sta < startframe)
totframesback = (startframe - (int)part->sta);
for(dframe=-totframesback; dframe<=0; dframe++) {
@@ -3819,14 +3894,13 @@ static void system_step(ParticleSimulationData *sim, float cfra)
}
/* 4. only write cache starting from second frame */
- if(use_cache) {
- BKE_ptcache_validate(cache, framenr);
- if(framenr != startframe)
- BKE_ptcache_write_cache(use_cache, framenr);
+ if(pid) {
+ BKE_ptcache_validate(cache, (int)cache_cfra);
+ if((int)cache_cfra != startframe)
+ BKE_ptcache_write(pid, (int)cache_cfra);
}
- if(init)
- update_children(sim);
+ update_children(sim);
/* cleanup */
if(psys->lattice){
@@ -3904,6 +3978,8 @@ static void fluid_default_settings(ParticleSettings *part){
fluid->radius = 0.5f;
fluid->spring_k = 0.f;
+ fluid->plasticity_constant = 0.1f;
+ fluid->yield_ratio = 0.1f;
fluid->rest_length = 0.5f;
fluid->viscosity_omega = 2.f;
fluid->viscosity_beta = 0.f;
@@ -3913,7 +3989,7 @@ static void fluid_default_settings(ParticleSettings *part){
fluid->buoyancy = 0.f;
}
-static void psys_changed_physics(ParticleSimulationData *sim)
+static void psys_prepare_physics(ParticleSimulationData *sim)
{
ParticleSettings *part = sim->psys->part;
@@ -3952,7 +4028,7 @@ static void psys_changed_physics(ParticleSimulationData *sim)
static int hair_needs_recalc(ParticleSystem *psys)
{
if(!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) &&
- ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) {
+ ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET || (psys->part->flag & PART_HAIR_REGROW && !psys->edit))) {
return 1;
}
@@ -3963,7 +4039,7 @@ static int hair_needs_recalc(ParticleSystem *psys)
* then advances in to actual particle calculations depending on particle type */
void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
{
- ParticleSimulationData sim = {scene, ob, psys, NULL, NULL};
+ ParticleSimulationData sim= {0};
ParticleSettings *part = psys->part;
float cfra;
@@ -3974,6 +4050,10 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
return;
cfra= BKE_curframe(scene);
+
+ sim.scene= scene;
+ sim.ob= ob;
+ sim.psys= psys;
sim.psmd= psys_get_modifier(ob, psys);
/* system was already updated from modifier stack */
@@ -3992,19 +4072,34 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
if(psys->recalc & PSYS_RECALC_TYPE)
psys_changed_type(&sim);
- else if(psys->recalc & PSYS_RECALC_PHYS)
- psys_changed_physics(&sim);
+
+ if(psys->recalc & PSYS_RECALC_RESET)
+ psys->totunexist = 0;
+
+ /* setup necessary physics type dependent additional data if it doesn't yet exist */
+ psys_prepare_physics(&sim);
switch(part->type) {
case PART_HAIR:
{
+ /* nothing to do so bail out early */
+ if(psys->totpart == 0 && part->totpart == 0) {
+ psys_free_path_cache(psys, NULL);
+ free_hair(ob, psys, 0);
+ }
/* (re-)create hair */
- if(hair_needs_recalc(psys)) {
+ else if(hair_needs_recalc(psys)) {
float hcfra=0.0f;
int i, recalc = psys->recalc;
free_hair(ob, psys, 0);
+ if(psys->edit && psys->free_edit) {
+ psys->free_edit(psys->edit);
+ psys->edit = NULL;
+ psys->free_edit = NULL;
+ }
+
/* first step is negative so particles get killed and reset */
psys->cfra= 1.0f;
@@ -4020,6 +4115,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
psys->flag |= PSYS_HAIR_DONE;
psys->recalc = recalc;
}
+ else if(psys->flag & PSYS_EDITED)
+ psys->flag |= PSYS_HAIR_DONE;
if(psys->flag & PSYS_HAIR_DONE)
hair_step(&sim, cfra);
@@ -4037,12 +4134,13 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
case PART_PHYS_KEYED:
{
PARTICLE_P;
+ float disp = (float)psys_get_current_display_percentage(psys)/100.0f;
/* Particles without dynamics haven't been reset yet because they don't use pointcache */
if(psys->recalc & PSYS_RECALC_RESET)
psys_reset(psys, PSYS_RESET_ALL);
- if(emit_particles(&sim, NULL, cfra)) {
+ if(emit_particles(&sim, NULL, cfra) || (psys->recalc & PSYS_RECALC_RESET)) {
free_keyed_keys(psys);
distribute_particles(&sim, part->from);
initialize_all_particles(&sim);
@@ -4054,6 +4152,11 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1);
reset_particle(&sim, pa, 0.0, cfra);
+
+ if(PSYS_FRAND(p) > disp)
+ pa->flag |= PARS_NO_DISP;
+ else
+ pa->flag &= ~PARS_NO_DISP;
}
if(part->phystype == PART_PHYS_KEYED) {
@@ -4077,7 +4180,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
psys->cfra = cfra;
psys->recalc = 0;
- /* save matrix for duplicators */
- invert_m4_m4(psys->imat, ob->obmat);
+ /* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
+ if(psys->renderdata==0)
+ invert_m4_m4(psys->imat, ob->obmat);
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index a35e40d7cf7..6ea14606660 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1,4 +1,5 @@
-/**
+/*
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -19,7 +20,7 @@
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
-* Contributor(s): Campbell Barton <ideasman42@gmail.com>
+ * Contributor(s): Campbell Barton <ideasman42@gmail.com>
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -44,6 +45,7 @@
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "PIL_time.h"
@@ -63,6 +65,7 @@
#include "BKE_smoke.h"
#include "BKE_softbody.h"
#include "BKE_utildefines.h"
+
#include "BIK_api.h"
/* both in intern */
@@ -95,44 +98,55 @@
/* could be made into a pointcache option */
#define DURIAN_POINTCACHE_LIB_OK 1
-int ptcache_data_size[] = {
- sizeof(int), // BPHYS_DATA_INDEX
- 3 * sizeof(float), // BPHYS_DATA_LOCATION:
- 3 * sizeof(float), // BPHYS_DATA_VELOCITY:
- 4 * sizeof(float), // BPHYS_DATA_ROTATION:
- 3 * sizeof(float), // BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */
- sizeof(float), // BPHYS_DATA_SIZE:
- 3 * sizeof(float), // BPHYS_DATA_TIMES:
- sizeof(BoidData) // case BPHYS_DATA_BOIDS:
+static int ptcache_data_size[] = {
+ sizeof(unsigned int), // BPHYS_DATA_INDEX
+ 3 * sizeof(float), // BPHYS_DATA_LOCATION
+ 3 * sizeof(float), // BPHYS_DATA_VELOCITY
+ 4 * sizeof(float), // BPHYS_DATA_ROTATION
+ 3 * sizeof(float), // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST
+ sizeof(float), // BPHYS_DATA_SIZE
+ 3 * sizeof(float), // BPHYS_DATA_TIMES
+ sizeof(BoidData) // case BPHYS_DATA_BOIDS
+};
+
+static int ptcache_extra_datasize[] = {
+ 0,
+ sizeof(ParticleSpring)
};
+/* forward declerations */
+static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len);
+static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode);
+static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
+static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
+
/* Common functions */
-static int ptcache_read_basic_header(PTCacheFile *pf)
+static int ptcache_basic_header_read(PTCacheFile *pf)
{
int error=0;
/* Custom functions should read these basic elements too! */
- if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp))
+ if(!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
error = 1;
- if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp))
+ if(!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
error = 1;
return !error;
}
-static int ptcache_write_basic_header(PTCacheFile *pf)
+static int ptcache_basic_header_write(PTCacheFile *pf)
{
/* Custom functions should write these basic elements too! */
- if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp))
+ if(!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
return 0;
- if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp))
+ if(!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
return 0;
return 1;
}
/* Softbody functions */
-static int ptcache_write_softbody(int index, void *soft_v, void **data, int cfra)
+static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
{
SoftBody *soft= soft_v;
BodyPoint *bp = soft->bpoint + index;
@@ -142,7 +156,7 @@ static int ptcache_write_softbody(int index, void *soft_v, void **data, int cfra
return 1;
}
-static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data)
+static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data)
{
SoftBody *soft= soft_v;
BodyPoint *bp = soft->bpoint + index;
@@ -156,7 +170,7 @@ static void ptcache_read_softbody(int index, void *soft_v, void **data, float fr
PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
}
}
-static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
+static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
{
SoftBody *soft= soft_v;
BodyPoint *bp = soft->bpoint + index;
@@ -188,24 +202,44 @@ static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, f
VECCOPY(bp->pos, keys->co);
VECCOPY(bp->vec, keys->vel);
}
-static int ptcache_totpoint_softbody(void *soft_v, int cfra)
+static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
{
SoftBody *soft= soft_v;
return soft->totpoint;
}
/* Particle functions */
-static int ptcache_write_particle(int index, void *psys_v, void **data, int cfra)
+void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
+{
+ PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
+ PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel);
+
+ /* no rotation info, so make something nice up */
+ if(data[BPHYS_DATA_ROTATION]==NULL) {
+ vec_to_quat( key->rot, key->vel, OB_NEGX, OB_POSZ);
+ }
+ else {
+ PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot);
+ }
+
+ PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave);
+ key->time = time;
+}
+static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra)
{
ParticleSystem *psys= psys_v;
ParticleData *pa = psys->particles + index;
BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
- float times[3] = {pa->time, pa->dietime, pa->lifetime};
+ float times[3];
int step = psys->pointcache->step;
/* No need to store unborn or died particles outside cache step bounds */
if(data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step))
return 0;
-
+
+ times[0]= pa->time;
+ times[1]= pa->dietime;
+ times[2]= pa->lifetime;
+
PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
@@ -220,19 +254,12 @@ static int ptcache_write_particle(int index, void *psys_v, void **data, int cfra
/* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */
return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time);
}
-void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
-{
- PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
- PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel);
- PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot);
- PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave);
- key->time = time;
-}
-static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data)
+static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data)
{
ParticleSystem *psys= psys_v;
ParticleData *pa;
BoidParticle *boid;
+ float timestep = 0.04f*psys->part->timetweak;
if(index >= psys->totpart)
return;
@@ -254,6 +281,8 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr
/* set frames cached before birth to birth time */
if(cfra < pa->time)
pa->state.time = pa->time;
+ else if(cfra > pa->dietime)
+ pa->state.time = pa->dietime;
if(data[BPHYS_DATA_SIZE])
PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
@@ -273,11 +302,11 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr
if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
if(cfra > pa->prev_state.time) {
sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
- mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec);
+ mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep);
}
else {
sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
- mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec);
+ mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep);
}
}
@@ -286,12 +315,12 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr
vec_to_quat( pa->state.rot,pa->state.vel, OB_NEGX, OB_POSZ);
}
}
-static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
+static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
{
ParticleSystem *psys= psys_v;
ParticleData *pa;
ParticleKey keys[4];
- float dfra;
+ float dfra, timestep = 0.04f*psys->part->timetweak;
if(index >= psys->totpart)
return;
@@ -319,11 +348,11 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f
if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
if(keys[1].time > keys[2].time) {
sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co);
- mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec);
+ mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep);
}
else {
sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co);
- mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec);
+ mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep);
}
}
@@ -337,163 +366,81 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f
dfra = cfra2 - cfra1;
- mul_v3_fl(keys[1].vel, dfra / frs_sec);
- mul_v3_fl(keys[2].vel, dfra / frs_sec);
+ mul_v3_fl(keys[1].vel, dfra * timestep);
+ mul_v3_fl(keys[2].vel, dfra * timestep);
psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
- mul_v3_fl(pa->state.vel, frs_sec / dfra);
+ mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep));
pa->state.time = cfra;
}
-static int ptcache_totpoint_particle(void *psys_v, int cfra)
+static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
{
ParticleSystem *psys = psys_v;
return psys->totpart;
}
-static int ptcache_totwrite_particle(void *psys_v, int cfra)
+static int ptcache_particle_totwrite(void *psys_v, int cfra)
{
ParticleSystem *psys = psys_v;
ParticleData *pa= psys->particles;
int p, step = psys->pointcache->step;
int totwrite = 0;
+ if(cfra == 0)
+ return psys->totpart;
+
for(p=0; p<psys->totpart; p++,pa++)
totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step);
return totwrite;
}
-//static int ptcache_write_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v)
-//{
-// ParticleSystem *psys= psys_v;
-// ParticleData *pa = psys->particles;
-// BoidParticle *boid = NULL;
-// float times[3];
-// int i = 0;
-//
-// if(!pf && !pm)
-// return 0;
-//
-// for(i=0; i<psys->totpart; i++, pa++) {
-//
-// if(data[BPHYS_DATA_INDEX]) {
-// int step = psys->pointcache->step;
-// /* No need to store unborn or died particles */
-// if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time)
-// continue;
-// }
-//
-// times[0] = pa->time;
-// times[1] = pa->dietime;
-// times[2] = pa->lifetime;
-//
-// PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
-// PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
-// PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
-// PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot);
-// PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
-// PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size);
-// PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times);
-//
-// boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
-// if(boid)
-// PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
-//
-// if(pf && !ptcache_file_write_data(pf))
-// return 0;
-//
-// if(pm)
-// BKE_ptcache_mem_incr_pointers(pm);
-// }
-//
-// return 1;
-//}
-//static void ptcache_read_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v, void **data, float frs_sec, float cfra, float *old_data)
-//{
-// ParticleSystem *psys= psys_v;
-// ParticleData *pa = psys->particles + index;
-// BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
-//
-// if(cfra > pa->state.time)
-// memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
-//
-// if(old_data){
-// /* old format cache */
-// memcpy(&pa->state, old_data, sizeof(ParticleKey));
-// return;
-// }
-//
-// BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
-//
-// if(data[BPHYS_DATA_SIZE])
-// PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
-//
-// if(data[BPHYS_DATA_TIMES]) {
-// float times[3];
-// PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, &times);
-// pa->time = times[0];
-// pa->dietime = times[1];
-// pa->lifetime = times[2];
-// }
-//
-// if(boid)
-// PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
-//
-// /* determine velocity from previous location */
-// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
-// if(cfra > pa->prev_state.time) {
-// sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
-// mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec);
-// }
-// else {
-// sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
-// mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec);
-// }
-// }
-//
-// /* determine rotation from velocity */
-// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
-// vec_to_quat( pa->state.rot,pa->state.vel, OB_POSX, OB_POSZ);
-// }
-//}
-//static void ptcache_interpolate_particle_stream(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
-//{
-// ParticleSystem *psys= psys_v;
-// ParticleData *pa = psys->particles + index;
-// ParticleKey keys[4];
-// float dfra;
-//
-// cfra = MIN2(cfra, pa->dietime);
-// cfra1 = MIN2(cfra1, pa->dietime);
-// cfra2 = MIN2(cfra2, pa->dietime);
-//
-// if(cfra1 == cfra2)
-// return;
-//
-// memcpy(keys+1, &pa->state, sizeof(ParticleKey));
-// if(old_data)
-// memcpy(keys+2, old_data, sizeof(ParticleKey));
-// else
-// BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
-//
-// dfra = cfra2 - cfra1;
-//
-// mul_v3_fl(keys[1].vel, dfra / frs_sec);
-// mul_v3_fl(keys[2].vel, dfra / frs_sec);
-//
-// psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
-// interp_qt_qtqt(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
-//
-// mul_v3_fl(pa->state.vel, frs_sec / dfra);
-//
-// pa->state.time = cfra;
-//}
-//
+static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
+{
+ ParticleSystem *psys = psys_v;
+ PTCacheExtra *extra = NULL;
+
+ if(psys->part->phystype == PART_PHYS_FLUID &&
+ psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS &&
+ psys->tot_fluidsprings && psys->fluid_springs) {
+
+ extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data");
+
+ extra->type = BPHYS_EXTRA_FLUID_SPRINGS;
+ extra->totdata = psys->tot_fluidsprings;
+
+ extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data");
+ memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]);
+
+ BLI_addtail(&pm->extradata, extra);
+ }
+}
+
+static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra))
+{
+ ParticleSystem *psys = psys_v;
+ PTCacheExtra *extra = pm->extradata.first;
+
+ for(; extra; extra=extra->next) {
+ switch(extra->type) {
+ case BPHYS_EXTRA_FLUID_SPRINGS:
+ {
+ if(psys->fluid_springs)
+ MEM_freeN(psys->fluid_springs);
+
+ psys->fluid_springs = MEM_dupallocN(extra->data);
+ psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata;
+ break;
+ }
+ }
+ }
+}
+
/* Cloth functions */
-static int ptcache_write_cloth(int index, void *cloth_v, void **data, int cfra)
+static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra))
{
ClothModifierData *clmd= cloth_v;
Cloth *cloth= clmd->clothObject;
@@ -505,7 +452,7 @@ static int ptcache_write_cloth(int index, void *cloth_v, void **data, int cfra)
return 1;
}
-static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data)
+static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data)
{
ClothModifierData *clmd= cloth_v;
Cloth *cloth= clmd->clothObject;
@@ -522,7 +469,7 @@ static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_
PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst);
}
}
-static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
+static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
{
ClothModifierData *clmd= cloth_v;
Cloth *cloth= clmd->clothObject;
@@ -558,84 +505,14 @@ static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, flo
/* should vert->xconst be interpolated somehow too? - jahka */
}
-static int ptcache_totpoint_cloth(void *cloth_v, int cfra)
+static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
{
ClothModifierData *clmd= cloth_v;
return clmd->clothObject ? clmd->clothObject->numverts : 0;
}
-/* Creating ID's */
-void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
-{
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->ob= ob;
- pid->calldata= sb;
- pid->type= PTCACHE_TYPE_SOFTBODY;
- pid->cache= sb->pointcache;
- pid->cache_ptr= &sb->pointcache;
- pid->ptcaches= &sb->ptcaches;
- pid->totpoint= pid->totwrite= ptcache_totpoint_softbody;
-
- pid->write_elem= ptcache_write_softbody;
- pid->write_stream = NULL;
- pid->read_stream = NULL;
- pid->read_elem= ptcache_read_softbody;
- pid->interpolate_elem= ptcache_interpolate_softbody;
-
- pid->write_header= ptcache_write_basic_header;
- pid->read_header= ptcache_read_basic_header;
-
- pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
- pid->info_types= 0;
-
- pid->stack_index = pid->cache->index;
-}
-
-void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
-{
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->ob= ob;
- pid->calldata= psys;
- pid->type= PTCACHE_TYPE_PARTICLES;
- pid->stack_index= psys->pointcache->index;
- pid->cache= psys->pointcache;
- pid->cache_ptr= &psys->pointcache;
- pid->ptcaches= &psys->ptcaches;
-
- if(psys->part->type != PART_HAIR)
- pid->flag |= PTCACHE_VEL_PER_SEC;
-
- pid->write_elem= ptcache_write_particle;
- pid->write_stream = NULL;
- pid->read_stream = NULL;
- pid->read_elem= ptcache_read_particle;
- pid->interpolate_elem= ptcache_interpolate_particle;
-
- pid->totpoint= ptcache_totpoint_particle;
- pid->totwrite= ptcache_totwrite_particle;
-
- pid->write_header= ptcache_write_basic_header;
- pid->read_header= ptcache_read_basic_header;
-
- pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX);
-
- if(psys->part->phystype == PART_PHYS_BOIDS)
- pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
-
- if(psys->part->rotmode!=PART_ROT_VEL
- || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f)
- pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
-
- if(psys->part->flag & PART_ROT_DYN)
- pid->data_types|= (1<<BPHYS_DATA_ROTATION);
-
- pid->info_types= (1<<BPHYS_DATA_TIMES);
-}
-
/* Smoke functions */
-static int ptcache_totpoint_smoke(void *smoke_v, int cfra)
+static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
{
SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
SmokeDomainSettings *sds = smd->domain;
@@ -646,79 +523,11 @@ static int ptcache_totpoint_smoke(void *smoke_v, int cfra)
else
return 0;
}
-
-/* Smoke functions */
-static int ptcache_totpoint_smoke_turbulence(void *smoke_v, int cfra)
-{
- SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
-
- if(sds->wt) {
- return sds->res_wt[0]*sds->res_wt[1]*sds->res_wt[2];
- }
- else
- return 0;
-}
-
-// forward decleration
-static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size);
-
-static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
-{
- int r = 0;
- unsigned char compressed = 0;
- unsigned int out_len= 0;
- unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
- size_t sizeOfIt = 5;
-
-#ifdef WITH_LZO
- out_len= LZO_OUT_LEN(in_len);
- if(mode == 1) {
- LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
-
- r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
- if (!(r == LZO_E_OK) || (out_len >= in_len))
- compressed = 0;
- else
- compressed = 1;
- }
-#endif
-#ifdef WITH_LZMA
- if(mode == 2) {
-
- r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1....
- props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
-
- if(!(r == SZ_OK) || (out_len >= in_len))
- compressed = 0;
- else
- compressed = 2;
- }
-#endif
-
- ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
- if(compressed) {
- ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int));
- ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
- }
- else
- ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
-
- if(compressed == 2)
- {
- ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
- ptcache_file_write(pf, props, sizeOfIt, sizeof(unsigned char));
- }
-
- MEM_freeN(props);
-
- return r;
-}
-
-static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v)
+static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
{
SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
SmokeDomainSettings *sds = smd->domain;
+ int ret = 0;
if(sds->fluid) {
size_t res = sds->res[0]*sds->res[1]*sds->res[2];
@@ -732,33 +541,26 @@ static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v)
smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
- ptcache_compress_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)dens, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)densold, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)heat, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)heatold, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)vx, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)vy, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)vz, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)vxold, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)vyold, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)vzold, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)vxold, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)vyold, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)vzold, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
ptcache_file_write(pf, &dt, 1, sizeof(float));
ptcache_file_write(pf, &dx, 1, sizeof(float));
MEM_freeN(out);
- return 1;
+ ret = 1;
}
- return 0;
-}
-static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v)
-{
- SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
-
if(sds->wt) {
int res_big_array[3];
int res_big;
@@ -780,71 +582,22 @@ static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v)
smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
- ptcache_compress_write(pf, (unsigned char *)dens, in_len_big, out, mode);
- ptcache_compress_write(pf, (unsigned char *)densold, in_len_big, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len_big, out, mode);
MEM_freeN(out);
out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
- ptcache_compress_write(pf, (unsigned char *)tcu, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)tcv, in_len, out, mode);
- ptcache_compress_write(pf, (unsigned char *)tcw, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode);
MEM_freeN(out);
- return 1;
+ ret = 1;
}
- return 0;
-}
-// forward decleration
-static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size);
-
-static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
-{
- int r = 0;
- unsigned char compressed = 0;
- unsigned int in_len;
-#ifdef WITH_LZO
- unsigned int out_len = len;
- size_t sizeOfIt = 5;
-#endif
- unsigned char *in;
- unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
-
- ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
- if(compressed) {
- ptcache_file_read(pf, &in_len, 1, sizeof(unsigned int));
- if(in_len==0) {
- /* do nothing */
- }
- else {
- in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
- ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
-#ifdef WITH_LZO
- if(compressed == 1)
- r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
-#endif
-#ifdef WITH_LZMA
- if(compressed == 2)
- {
- size_t leni = in_len, leno = out_len;
- ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int));
- ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
- r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
- }
-#endif
- MEM_freeN(in);
- }
- }
- else {
- ptcache_file_read(pf, result, len, sizeof(unsigned char));
- }
-
- MEM_freeN(props);
-
- return r;
+ return ret;
}
-
-static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v)
+static void ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
{
SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
SmokeDomainSettings *sds = smd->domain;
@@ -857,116 +610,126 @@ static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v)
smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
- ptcache_compress_read(pf, (unsigned char *)sds->shadow, out_len);
- ptcache_compress_read(pf, (unsigned char*)dens, out_len);
- ptcache_compress_read(pf, (unsigned char*)densold, out_len);
- ptcache_compress_read(pf, (unsigned char*)heat, out_len);
- ptcache_compress_read(pf, (unsigned char*)heatold, out_len);
- ptcache_compress_read(pf, (unsigned char*)vx, out_len);
- ptcache_compress_read(pf, (unsigned char*)vy, out_len);
- ptcache_compress_read(pf, (unsigned char*)vz, out_len);
- ptcache_compress_read(pf, (unsigned char*)vxold, out_len);
- ptcache_compress_read(pf, (unsigned char*)vyold, out_len);
- ptcache_compress_read(pf, (unsigned char*)vzold, out_len);
- ptcache_compress_read(pf, (unsigned char*)obstacles, (unsigned int)res);
+ ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)vxold, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)vyold, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)vzold, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res);
ptcache_file_read(pf, &dt, 1, sizeof(float));
ptcache_file_read(pf, &dx, 1, sizeof(float));
- }
-}
-static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v)
-{
- SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
-
- if(sds->fluid) {
- int res = sds->res[0]*sds->res[1]*sds->res[2];
- int res_big, res_big_array[3];
- float *dens, *densold, *tcu, *tcv, *tcw;
- unsigned int out_len = sizeof(float)*(unsigned int)res;
- unsigned int out_len_big;
+ if(pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
+ int res = sds->res[0]*sds->res[1]*sds->res[2];
+ int res_big, res_big_array[3];
+ float *dens, *densold, *tcu, *tcv, *tcw;
+ unsigned int out_len = sizeof(float)*(unsigned int)res;
+ unsigned int out_len_big;
- smoke_turbulence_get_res(sds->wt, res_big_array);
- res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
- out_len_big = sizeof(float) * (unsigned int)res_big;
+ smoke_turbulence_get_res(sds->wt, res_big_array);
+ res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
+ out_len_big = sizeof(float) * (unsigned int)res_big;
- smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
+ smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
- ptcache_compress_read(pf, (unsigned char*)dens, out_len_big);
- ptcache_compress_read(pf, (unsigned char*)densold, out_len_big);
+ ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big);
+ ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len_big);
- ptcache_compress_read(pf, (unsigned char*)tcu, out_len);
- ptcache_compress_read(pf, (unsigned char*)tcv, out_len);
- ptcache_compress_read(pf, (unsigned char*)tcw, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len);
+ }
}
}
-void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
+/* Creating ID's */
+void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
{
- SmokeDomainSettings *sds = smd->domain;
-
memset(pid, 0, sizeof(PTCacheID));
pid->ob= ob;
- pid->calldata= smd;
-
- pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
- pid->stack_index= sds->point_cache[0]->index;
-
- pid->cache= sds->point_cache[0];
- pid->cache_ptr= &(sds->point_cache[0]);
- pid->ptcaches= &(sds->ptcaches[0]);
+ pid->calldata= sb;
+ pid->type= PTCACHE_TYPE_SOFTBODY;
+ pid->cache= sb->pointcache;
+ pid->cache_ptr= &sb->pointcache;
+ pid->ptcaches= &sb->ptcaches;
+ pid->totpoint= pid->totwrite= ptcache_softbody_totpoint;
- pid->totpoint= pid->totwrite= ptcache_totpoint_smoke;
+ pid->write_point = ptcache_softbody_write;
+ pid->read_point = ptcache_softbody_read;
+ pid->interpolate_point = ptcache_softbody_interpolate;
- pid->write_elem= NULL;
- pid->read_elem= NULL;
+ pid->write_stream = NULL;
+ pid->read_stream = NULL;
- pid->read_stream = ptcache_read_smoke;
- pid->write_stream = ptcache_write_smoke;
-
- pid->interpolate_elem= NULL;
+ pid->write_extra_data = NULL;
+ pid->read_extra_data = NULL;
+ pid->interpolate_extra_data = NULL;
- pid->write_header= ptcache_write_basic_header;
- pid->read_header= ptcache_read_basic_header;
+ pid->write_header = ptcache_basic_header_write;
+ pid->read_header = ptcache_basic_header_read;
- pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values to make pointcache happy
+ pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
pid->info_types= 0;
-}
-void BKE_ptcache_id_from_smoke_turbulence(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
+ pid->stack_index = pid->cache->index;
+}
+void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
{
- SmokeDomainSettings *sds = smd->domain;
-
memset(pid, 0, sizeof(PTCacheID));
pid->ob= ob;
- pid->calldata= smd;
-
- pid->type= PTCACHE_TYPE_SMOKE_HIGHRES;
- pid->stack_index= sds->point_cache[1]->index;
+ pid->calldata= psys;
+ pid->type= PTCACHE_TYPE_PARTICLES;
+ pid->stack_index= psys->pointcache->index;
+ pid->cache= psys->pointcache;
+ pid->cache_ptr= &psys->pointcache;
+ pid->ptcaches= &psys->ptcaches;
- pid->cache= sds->point_cache[1];
- pid->cache_ptr= &sds->point_cache[1];
- pid->ptcaches= &sds->ptcaches[1];
+ if(psys->part->type != PART_HAIR)
+ pid->flag |= PTCACHE_VEL_PER_SEC;
- pid->totpoint= pid->totwrite= ptcache_totpoint_smoke_turbulence;
+ pid->totpoint = ptcache_particle_totpoint;
+ pid->totwrite = ptcache_particle_totwrite;
- pid->write_elem= NULL;
- pid->read_elem= NULL;
+ pid->write_point = ptcache_particle_write;
+ pid->read_point = ptcache_particle_read;
+ pid->interpolate_point = ptcache_particle_interpolate;
- pid->read_stream = ptcache_read_smoke_turbulence;
- pid->write_stream = ptcache_write_smoke_turbulence;
-
- pid->interpolate_elem= NULL;
+ pid->write_stream = NULL;
+ pid->read_stream = NULL;
- pid->write_header= ptcache_write_basic_header;
- pid->read_header= ptcache_read_basic_header;
+ pid->write_extra_data = NULL;
+ pid->read_extra_data = NULL;
+ pid->interpolate_extra_data = NULL;
- pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy
- pid->info_types= 0;
-}
+ pid->write_header = ptcache_basic_header_write;
+ pid->read_header = ptcache_basic_header_read;
+
+ pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX);
+
+ if(psys->part->phystype == PART_PHYS_BOIDS)
+ pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
+ else if(psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) {
+ pid->write_extra_data = ptcache_particle_extra_write;
+ pid->read_extra_data = ptcache_particle_extra_read;
+ }
+ if(psys->part->rotmode!=PART_ROT_VEL
+ || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f)
+ pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
+
+ if(psys->part->flag & PART_ROT_DYN)
+ pid->data_types|= (1<<BPHYS_DATA_ROTATION);
+
+ pid->info_types= (1<<BPHYS_DATA_TIMES);
+}
void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
{
memset(pid, 0, sizeof(PTCacheID));
@@ -978,21 +741,65 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->cache= clmd->point_cache;
pid->cache_ptr= &clmd->point_cache;
pid->ptcaches= &clmd->ptcaches;
- pid->totpoint= pid->totwrite= ptcache_totpoint_cloth;
+ pid->totpoint= pid->totwrite= ptcache_cloth_totpoint;
+
+ pid->write_point = ptcache_cloth_write;
+ pid->read_point = ptcache_cloth_read;
+ pid->interpolate_point = ptcache_cloth_interpolate;
+
+ pid->write_stream = NULL;
+ pid->read_stream = NULL;
- pid->write_elem= ptcache_write_cloth;
- pid->write_stream = NULL;
- pid->read_stream = NULL;
- pid->read_elem= ptcache_read_cloth;
- pid->interpolate_elem= ptcache_interpolate_cloth;
+ pid->write_extra_data = NULL;
+ pid->read_extra_data = NULL;
+ pid->interpolate_extra_data = NULL;
- pid->write_header= ptcache_write_basic_header;
- pid->read_header= ptcache_read_basic_header;
+ pid->write_header = ptcache_basic_header_write;
+ pid->read_header = ptcache_basic_header_read;
pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
pid->info_types= 0;
}
+void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
+{
+ SmokeDomainSettings *sds = smd->domain;
+
+ memset(pid, 0, sizeof(PTCacheID));
+
+ pid->ob= ob;
+ pid->calldata= smd;
+
+ pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
+ pid->stack_index= sds->point_cache[0]->index;
+
+ pid->cache= sds->point_cache[0];
+ pid->cache_ptr= &(sds->point_cache[0]);
+ pid->ptcaches= &(sds->ptcaches[0]);
+
+ pid->totpoint= pid->totwrite= ptcache_smoke_totpoint;
+ pid->write_point = NULL;
+ pid->read_point = NULL;
+ pid->interpolate_point = NULL;
+
+ pid->read_stream = ptcache_smoke_read;
+ pid->write_stream = ptcache_smoke_write;
+
+ pid->write_extra_data = NULL;
+ pid->read_extra_data = NULL;
+ pid->interpolate_extra_data = NULL;
+
+ pid->write_header = ptcache_basic_header_write;
+ pid->read_header = ptcache_basic_header_read;
+
+ pid->data_types= 0;
+ pid->info_types= 0;
+
+ if(sds->fluid)
+ pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW);
+ if(sds->wt)
+ pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH);
+}
void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
{
PTCacheID *pid;
@@ -1008,11 +815,23 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
}
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
- if(psys->part) {
- pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_particles(pid, ob, psys);
- BLI_addtail(lb, pid);
- }
+ if(psys->part==NULL)
+ continue;
+
+ /* check to make sure point cache is actually used by the particles */
+ if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
+ continue;
+
+ /* hair needs to be included in id-list for cache edit mode to work */
+ /* if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */
+ /* continue; */
+
+ if(psys->part->type == PART_FLUID)
+ continue;
+
+ pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
+ BKE_ptcache_id_from_particles(pid, ob, psys);
+ BLI_addtail(lb, pid);
}
for(md=ob->modifiers.first; md; md=md->next) {
@@ -1028,10 +847,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md);
BLI_addtail(lb, pid);
-
- pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_smoke_turbulence(pid, ob, (SmokeModifierData*)md);
- BLI_addtail(lb, pid);
}
}
}
@@ -1045,7 +860,7 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
if(dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
ListBase lb_dupli_pid;
BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
- addlisttolist(lb, &lb_dupli_pid);
+ BLI_movelisttolist(lb, &lb_dupli_pid);
if(lb_dupli_pid.first)
printf("Adding Dupli\n");
}
@@ -1056,7 +871,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
}
}
-
/* File handling */
/* Takes an Object ID and returns a unique name
@@ -1070,8 +884,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
static int ptcache_path(PTCacheID *pid, char *filename)
{
- Library *lib= (pid)? pid->ob->id.lib: NULL;
- const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.sce;
+ Library *lib= (pid->ob)? pid->ob->id.lib: NULL;
+ const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name;
size_t i;
if(pid->cache->flag & PTCACHE_EXTERNAL) {
@@ -1104,7 +918,7 @@ static int ptcache_path(PTCacheID *pid, char *filename)
return BLI_add_slash(filename); /* new strlen() */
}
-static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
+static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
{
int len=0;
char *idname;
@@ -1169,7 +983,7 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
#endif
if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
- BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
+ ptcache_filename(pid, filename, cfra, 1, 1);
if (mode==PTCACHE_FILE_READ) {
if (!BLI_exists(filename)) {
@@ -1189,48 +1003,155 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
pf->fp= fp;
+ pf->old_format = 0;
+ pf->frame = cfra;
return pf;
}
-
static void ptcache_file_close(PTCacheFile *pf)
{
- fclose(pf->fp);
- MEM_freeN(pf);
+ if(pf) {
+ fclose(pf->fp);
+ MEM_freeN(pf);
+ }
+}
+
+static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
+{
+ int r = 0;
+ unsigned char compressed = 0;
+ size_t in_len;
+#ifdef WITH_LZO
+ size_t out_len = len;
+ size_t sizeOfIt = 5;
+#endif
+ unsigned char *in;
+ unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
+
+ ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
+ if(compressed) {
+ unsigned int size;
+ ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
+ in_len = (size_t)size;
+ if(in_len==0) {
+ /* do nothing */
+ }
+ else {
+ in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
+ ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
+#ifdef WITH_LZO
+ if(compressed == 1)
+ r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
+#endif
+#ifdef WITH_LZMA
+ if(compressed == 2)
+ {
+ size_t leni = in_len, leno = out_len;
+ ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
+ sizeOfIt = (size_t)size;
+ ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
+ r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
+ }
+#endif
+ MEM_freeN(in);
+ }
+ }
+ else {
+ ptcache_file_read(pf, result, len, sizeof(unsigned char));
+ }
+
+ MEM_freeN(props);
+
+ return r;
}
+static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
+{
+ int r = 0;
+ unsigned char compressed = 0;
+ size_t out_len= 0;
+ unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
+ size_t sizeOfIt = 5;
-static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size)
+ (void)mode; /* unused when building w/o compression */
+
+#ifdef WITH_LZO
+ out_len= LZO_OUT_LEN(in_len);
+ if(mode == 1) {
+ LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
+
+ r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
+ if (!(r == LZO_E_OK) || (out_len >= in_len))
+ compressed = 0;
+ else
+ compressed = 1;
+ }
+#endif
+#ifdef WITH_LZMA
+ if(mode == 2) {
+
+ r = LzmaCompress(out, &out_len, in, in_len,//assume sizeof(char)==1....
+ props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
+
+ if(!(r == SZ_OK) || (out_len >= in_len))
+ compressed = 0;
+ else
+ compressed = 2;
+ }
+#endif
+
+ ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
+ if(compressed) {
+ unsigned int size = out_len;
+ ptcache_file_write(pf, &size, 1, sizeof(unsigned int));
+ ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
+ }
+ else
+ ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
+
+ if(compressed == 2)
+ {
+ unsigned int size = sizeOfIt;
+ ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
+ ptcache_file_write(pf, props, size, sizeof(unsigned char));
+ }
+
+ MEM_freeN(props);
+
+ return r;
+}
+static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
{
return (fread(f, size, tot, pf->fp) == tot);
}
-static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size)
+static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
{
return (fwrite(f, size, tot, pf->fp) == tot);
}
-static int ptcache_file_read_data(PTCacheFile *pf)
+static int ptcache_file_data_read(PTCacheFile *pf)
{
int i;
for(i=0; i<BPHYS_TOT_DATA; i++) {
- if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i]))
+ if((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i]))
return 0;
}
return 1;
}
-static int ptcache_file_write_data(PTCacheFile *pf)
+static int ptcache_file_data_write(PTCacheFile *pf)
{
int i;
for(i=0; i<BPHYS_TOT_DATA; i++) {
- if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
+ if((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
return 0;
}
return 1;
}
-static int ptcache_file_read_header_begin(PTCacheFile *pf)
+static int ptcache_file_header_begin_read(PTCacheFile *pf)
{
+ unsigned int typeflag=0;
int error=0;
char bphysics[8];
@@ -1242,8 +1163,11 @@ static int ptcache_file_read_header_begin(PTCacheFile *pf)
if(!error && strncmp(bphysics, "BPHYSICS", 8))
error = 1;
- if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp))
+ if(!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp))
error = 1;
+
+ pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK);
+ pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK);
/* if there was an error set file as it was */
if(error)
@@ -1251,84 +1175,82 @@ static int ptcache_file_read_header_begin(PTCacheFile *pf)
return !error;
}
-
-
-static int ptcache_file_write_header_begin(PTCacheFile *pf)
+static int ptcache_file_header_begin_write(PTCacheFile *pf)
{
- char *bphysics = "BPHYSICS";
+ const char *bphysics = "BPHYSICS";
+ unsigned int typeflag = pf->type + pf->flag;
if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
return 0;
- if(!fwrite(&pf->type, sizeof(int), 1, pf->fp))
+ if(!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp))
return 0;
return 1;
}
-
/* Data pointer handling */
int BKE_ptcache_data_size(int data_type)
{
return ptcache_data_size[data_type];
}
-static void ptcache_file_init_pointers(PTCacheFile *pf)
+static void ptcache_file_pointers_init(PTCacheFile *pf)
{
int data_types = pf->data_types;
- pf->cur[BPHYS_DATA_INDEX] = data_types & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : NULL;
- pf->cur[BPHYS_DATA_LOCATION] = data_types & (1<<BPHYS_DATA_LOCATION) ? &pf->data.loc : NULL;
- pf->cur[BPHYS_DATA_VELOCITY] = data_types & (1<<BPHYS_DATA_VELOCITY) ? &pf->data.vel : NULL;
- pf->cur[BPHYS_DATA_ROTATION] = data_types & (1<<BPHYS_DATA_ROTATION) ? &pf->data.rot : NULL;
- pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ? &pf->data.ave : NULL;
- pf->cur[BPHYS_DATA_SIZE] = data_types & (1<<BPHYS_DATA_SIZE) ? &pf->data.size : NULL;
- pf->cur[BPHYS_DATA_TIMES] = data_types & (1<<BPHYS_DATA_TIMES) ? &pf->data.times : NULL;
- pf->cur[BPHYS_DATA_BOIDS] = data_types & (1<<BPHYS_DATA_BOIDS) ? &pf->data.boids : NULL;
+ pf->cur[BPHYS_DATA_INDEX] = (data_types & (1<<BPHYS_DATA_INDEX)) ? &pf->data.index : NULL;
+ pf->cur[BPHYS_DATA_LOCATION] = (data_types & (1<<BPHYS_DATA_LOCATION)) ? &pf->data.loc : NULL;
+ pf->cur[BPHYS_DATA_VELOCITY] = (data_types & (1<<BPHYS_DATA_VELOCITY)) ? &pf->data.vel : NULL;
+ pf->cur[BPHYS_DATA_ROTATION] = (data_types & (1<<BPHYS_DATA_ROTATION)) ? &pf->data.rot : NULL;
+ pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))? &pf->data.ave : NULL;
+ pf->cur[BPHYS_DATA_SIZE] = (data_types & (1<<BPHYS_DATA_SIZE)) ? &pf->data.size : NULL;
+ pf->cur[BPHYS_DATA_TIMES] = (data_types & (1<<BPHYS_DATA_TIMES)) ? &pf->data.times : NULL;
+ pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1<<BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL;
}
-static void ptcache_file_seek_pointers(int index, PTCacheFile *pf)
+/* Check to see if point number "index" is in pm, uses binary search for index data. */
+int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
{
- int i, size=0;
- int data_types = pf->data_types;
+ if(pm->data[BPHYS_DATA_INDEX]) {
+ unsigned int *data = pm->data[BPHYS_DATA_INDEX];
+ unsigned int mid, low = 0, high = pm->totpoint - 1;
- if(data_types & (1<<BPHYS_DATA_INDEX)) {
- int totpoint;
- /* The simplest solution is to just write to the very end. This may cause
- * some data duplication, but since it's on disk it's not so bad. The correct
- * thing would be to search through the file for the correct index and only
- * write to the end if it's not found, but this could be quite slow.
- */
- fseek(pf->fp, 8 + sizeof(int), SEEK_SET);
- fread(&totpoint, sizeof(int), 1, pf->fp);
-
- totpoint++;
+ if(index < *data || index > *(data+high))
+ return -1;
- fseek(pf->fp, 8 + sizeof(int), SEEK_SET);
- fwrite(&totpoint, sizeof(int), 1, pf->fp);
+ /* check simple case for continuous indexes first */
+ if(index-*data < high && data[index-*data] == index)
+ return index-*data;
+
+ while(low <= high) {
+ mid= (low + high)/2;
+
+ if(data[mid] > index)
+ high = mid - 1;
+ else if(data[mid] < index)
+ low = mid + 1;
+ else
+ return mid;
+ }
- fseek(pf->fp, 0, SEEK_END);
+ return -1;
}
else {
- for(i=0; i<BPHYS_TOT_DATA; i++)
- size += pf->data_types & (1<<i) ? ptcache_data_size[i] : 0;
-
- /* size of default header + data up to index */
- fseek(pf->fp, 8 + 3*sizeof(int) + index * size, SEEK_SET);
+ return (index < pm->totpoint ? index : -1);
}
-
- ptcache_file_init_pointers(pf);
}
-void BKE_ptcache_mem_init_pointers(PTCacheMem *pm)
+
+void BKE_ptcache_mem_pointers_init(PTCacheMem *pm)
{
int data_types = pm->data_types;
int i;
for(i=0; i<BPHYS_TOT_DATA; i++)
- pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL;
+ pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL);
}
-void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm)
+void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm)
{
int i;
@@ -1337,10 +1259,10 @@ void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm)
pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i];
}
}
-int BKE_ptcache_mem_seek_pointers(int point_index, PTCacheMem *pm)
+int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
{
int data_types = pm->data_types;
- int i, index = pm->index_array ? pm->index_array[point_index] - 1 : point_index;
+ int i, index = BKE_ptcache_mem_index_find(pm, point_index);
if(index < 0) {
/* Can't give proper location without reallocation, so don't give any location.
@@ -1356,7 +1278,7 @@ int BKE_ptcache_mem_seek_pointers(int point_index, PTCacheMem *pm)
return 1;
}
-static void ptcache_alloc_data(PTCacheMem *pm)
+static void ptcache_data_alloc(PTCacheMem *pm)
{
int data_types = pm->data_types;
int totpoint = pm->totpoint;
@@ -1367,7 +1289,7 @@ static void ptcache_alloc_data(PTCacheMem *pm)
pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
}
}
-static void ptcache_free_data(PTCacheMem *pm)
+static void ptcache_data_free(PTCacheMem *pm)
{
void **data = pm->data;
int i;
@@ -1376,13 +1298,8 @@ static void ptcache_free_data(PTCacheMem *pm)
if(data[i])
MEM_freeN(data[i]);
}
-
- if(pm->index_array) {
- MEM_freeN(pm->index_array);
- pm->index_array = NULL;
- }
}
-static void ptcache_copy_data(void *from[], void *to[])
+static void ptcache_data_copy(void *from[], void *to[])
{
int i;
for(i=0; i<BPHYS_TOT_DATA; i++) {
@@ -1393,9 +1310,20 @@ static void ptcache_copy_data(void *from[], void *to[])
}
}
+static void ptcache_extra_free(PTCacheMem *pm)
+{
+ PTCacheExtra *extra = pm->extradata.first;
+ if(extra) {
+ for(; extra; extra=extra->next) {
+ if(extra->data)
+ MEM_freeN(extra->data);
+ }
-static int ptcache_pid_old_elemsize(PTCacheID *pid)
+ BLI_freelistN(&pm->extradata);
+ }
+}
+static int ptcache_old_elemsize(PTCacheID *pid)
{
if(pid->type==PTCACHE_TYPE_SOFTBODY)
return 6 * sizeof(float);
@@ -1407,268 +1335,408 @@ static int ptcache_pid_old_elemsize(PTCacheID *pid)
return 0;
}
-/* reads cache from disk or memory */
-/* possible to get old or interpolated result */
-int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec)
+static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
{
- PTCacheFile *pf=NULL, *pf2=NULL;
- PTCacheMem *pm=NULL, *pm2=NULL;
- float old_data1[14], old_data2[14];
- int cfrai = (int)cfra;
- int old_elemsize = ptcache_pid_old_elemsize(pid);
- int i;
+ if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+ int cfra1=frame-1, cfra2=frame+1;
- int cfra1 = 0, cfra2 = 0;
- int totpoint = 0, totpoint2 = 0;
- int *index = &i, *index2 = &i;
- int use_old = 0, old_frame = 0;
+ while(cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1))
+ cfra1--;
- int ret = 0, error = 0;
+ if(cfra1 < pid->cache->startframe)
+ cfra1 = 0;
- /* nothing to read to */
- if(pid->totpoint(pid->calldata, (int)cfra) == 0)
- return 0;
+ while(cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2))
+ cfra2++;
- if(pid->cache->flag & PTCACHE_READ_INFO) {
- pid->cache->flag &= ~PTCACHE_READ_INFO;
- BKE_ptcache_read_cache(pid, 0, frs_sec);
+ if(cfra2 > pid->cache->endframe)
+ cfra2 = 0;
+
+ if(cfra1 && !cfra2) {
+ *fra1 = 0;
+ *fra2 = cfra1;
+ }
+ else {
+ *fra1 = cfra1;
+ *fra2 = cfra2;
+ }
}
+ else if(pid->cache->mem_cache.first) {
+ PTCacheMem *pm = pid->cache->mem_cache.first;
+ PTCacheMem *pm2 = pid->cache->mem_cache.last;
+ while(pm->next && pm->next->frame < frame)
+ pm= pm->next;
- /* first check if we have the actual frame cached */
- if(cfra == (float)cfrai) {
- if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- }
+ if(pm2 && pm2->frame < frame)
+ pm2 = NULL;
else {
- pm = pid->cache->mem_cache.first;
+ while(pm2->prev && pm2->prev->frame > frame)
+ pm2= pm2->prev;
+ }
- for(; pm; pm=pm->next) {
- if(pm->frame == cfrai)
- break;
- }
+ if(pm && !pm2) {
+ *fra1 = 0;
+ *fra2 = pm->frame;
+ }
+ else {
+ *fra1 = pm->frame;
+ *fra2 = pm2->frame;
}
}
+}
- /* no exact cache frame found so try to find cached frames around cfra */
- if(!pm && !pf) {
- if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- pf=NULL;
- while(cfrai > pid->cache->startframe && !pf) {
- cfrai--;
- pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- cfra1 = cfrai;
- }
+static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
+{
+ PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
+ PTCacheMem *pm = NULL;
+ unsigned int i, error = 0;
+
+ if(pf == NULL)
+ return 0;
- old_frame = cfrai;
+ if(!ptcache_file_header_begin_read(pf))
+ error = 1;
+
+ if(!error && (pf->type != pid->type || !pid->read_header(pf)))
+ error = 1;
+
+ if(!error) {
+ pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
- cfrai = (int)cfra;
- while(cfrai < pid->cache->endframe && !pf2) {
- cfrai++;
- pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- cfra2 = cfrai;
+ pm->totpoint = pf->totpoint;
+ pm->data_types = pf->data_types;
+ pm->frame = pf->frame;
+
+ ptcache_data_alloc(pm);
+
+ if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
+ for(i=0; i<BPHYS_TOT_DATA; i++) {
+ unsigned int out_len = pm->totpoint*ptcache_data_size[i];
+ if(pf->data_types & (1<<i))
+ ptcache_file_compressed_read(pf, (unsigned char*)(pm->data[i]), out_len);
}
+ }
+ else {
+ BKE_ptcache_mem_pointers_init(pm);
+ ptcache_file_pointers_init(pf);
- if(pf && !pf2) {
- pf2 = pf;
- pf = NULL;
+ for(i=0; i<pm->totpoint; i++) {
+ if(!ptcache_file_data_read(pf)) {
+ error = 1;
+ break;
+ }
+ ptcache_data_copy(pf->cur, pm->cur);
+ BKE_ptcache_mem_pointers_incr(pm);
}
}
- else if(pid->cache->mem_cache.first){
- pm = pid->cache->mem_cache.first;
+ }
- while(pm->next && pm->next->frame < cfra)
- pm= pm->next;
+ if(!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) {
+ unsigned int extratype = 0;
- if(pm) {
- old_frame = pm->frame;
- cfra1 = pm->frame;
- }
+ while(ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) {
+ PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata");
- pm2 = pid->cache->mem_cache.last;
+ extra->type = extratype;
- if(pm2 && pm2->frame < cfra)
- pm2 = NULL;
- else {
- while(pm2->prev && pm2->prev->frame > cfra)
- pm2= pm2->prev;
+ ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int));
- if(pm2)
- cfra2 = pm2->frame;
- }
+ extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data");
- if(pm && !pm2) {
- pm2 = pm;
- pm = NULL;
- }
+ if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS)
+ ptcache_file_compressed_read(pf, (unsigned char*)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]);
+ else
+ ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
+
+ BLI_addtail(&pm->extradata, extra);
}
}
- if(!pm && !pm2 && !pf && !pf2)
- return 0;
-
- if(pm) {
- BKE_ptcache_mem_init_pointers(pm);
- totpoint = pm->totpoint;
- index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
+ if(error && pm) {
+ ptcache_data_free(pm);
+ ptcache_extra_free(pm);
+ MEM_freeN(pm);
+ pm = NULL;
}
- if(pm2) {
- BKE_ptcache_mem_init_pointers(pm2);
- totpoint2 = pm2->totpoint;
- index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
+
+ ptcache_file_close(pf);
+
+ if (error && G.f & G_DEBUG)
+ printf("Error reading from disk cache\n");
+
+ return pm;
+}
+static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
+{
+ PTCacheFile *pf = NULL;
+ unsigned int i, error = 0;
+
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame);
+
+ pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
+
+ if(pf==NULL) {
+ if (G.f & G_DEBUG)
+ printf("Error opening disk cache file for writing\n");
+ return 0;
}
- if(pf) {
- if(ptcache_file_read_header_begin(pf)) {
- if(pf->type != pid->type) {
- /* todo report error */
- ptcache_file_close(pf);
- pf = NULL;
- }
- else if(pid->read_header(pf)) {
- ptcache_file_init_pointers(pf);
- totpoint = pf->totpoint;
- index = pf->data_types & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : &i;
+
+ pf->data_types = pm->data_types;
+ pf->totpoint = pm->totpoint;
+ pf->type = pid->type;
+ pf->flag = 0;
+
+ if(pm->extradata.first)
+ pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
+
+ if(pid->cache->compression)
+ pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
+
+ if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))
+ error = 1;
+
+ if(!error) {
+ if(pid->cache->compression) {
+ for(i=0; i<BPHYS_TOT_DATA; i++) {
+ if(pm->data[i]) {
+ unsigned int in_len = pm->totpoint*ptcache_data_size[i];
+ unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
+ ptcache_file_compressed_write(pf, (unsigned char*)(pm->data[i]), in_len, out, pid->cache->compression);
+ MEM_freeN(out);
+ }
}
}
else {
- /* fall back to old cache file format */
- use_old = 1;
- totpoint = pid->totpoint(pid->calldata, (int) cfra);
+ BKE_ptcache_mem_pointers_init(pm);
+ ptcache_file_pointers_init(pf);
+
+ for(i=0; i<pm->totpoint; i++) {
+ ptcache_data_copy(pm->cur, pf->cur);
+ if(!ptcache_file_data_write(pf)) {
+ error = 1;
+ break;
+ }
+ BKE_ptcache_mem_pointers_incr(pm);
+ }
}
}
- if(pf2) {
- if(ptcache_file_read_header_begin(pf2)) {
- if(pf2->type != pid->type) {
- /* todo report error */
- ptcache_file_close(pf2);
- pf2 = NULL;
+
+ if(!error && pm->extradata.first) {
+ PTCacheExtra *extra = pm->extradata.first;
+
+ for(; extra; extra=extra->next) {
+ if(extra->data == NULL || extra->totdata == 0)
+ continue;
+
+ ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int));
+ ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int));
+
+ if(pid->cache->compression) {
+ unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
+ unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
+ ptcache_file_compressed_write(pf, (unsigned char*)(extra->data), in_len, out, pid->cache->compression);
+ MEM_freeN(out);
}
- else if(pid->read_header(pf2)) {
- ptcache_file_init_pointers(pf2);
- totpoint2 = pf2->totpoint;
- index2 = pf2->data_types & (1<<BPHYS_DATA_INDEX) ? &pf2->data.index : &i;
+ else {
+ ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
}
}
- else {
- /* fall back to old cache file format */
- use_old = 1;
- totpoint2 = pid->totpoint(pid->calldata, (int) cfra);
- }
}
- /* don't read old cache if already simulated past cached frame */
- if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe)
+ ptcache_file_close(pf);
+
+ if (error && G.f & G_DEBUG)
+ printf("Error writing to disk cache\n");
+
+ return error==0;
+}
+
+static int ptcache_read_stream(PTCacheID *pid, int cfra)
+{
+ PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
+ int error = 0;
+
+ if(pid->read_stream == NULL)
+ return 0;
+
+ if(pf == NULL) {
+ if (G.f & G_DEBUG)
+ printf("Error opening disk cache file for reading\n");
+ return 0;
+ }
+
+ if(!ptcache_file_header_begin_read(pf))
error = 1;
- if(cfra1 && cfra1==cfra2)
+
+ if(!error && (pf->type != pid->type || !pid->read_header(pf)))
error = 1;
- if(!error)
- {
- if(pf && pid->read_stream) {
- if(totpoint != pid->totpoint(pid->calldata, (int) cfra))
- error = 1;
- else
- {
- // we have stream writing here
- pid->read_stream(pf, pid->calldata);
- }
- }
+ if(!error && pf->totpoint != pid->totpoint(pid->calldata, cfra))
+ error = 1;
+
+ if(!error) {
+ ptcache_file_pointers_init(pf);
+
+ // we have stream reading here
+ pid->read_stream(pf, pid->calldata);
+ }
+
+ ptcache_file_close(pf);
+
+ return error == 0;
+}
+static int ptcache_read(PTCacheID *pid, int cfra)
+{
+ PTCacheMem *pm = NULL;
+ int i;
+ int *index = &i;
+
+ /* get a memory cache to read from */
+ if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+ pm = ptcache_disk_frame_to_mem(pid, cfra);
+ }
+ else {
+ pm = pid->cache->mem_cache.first;
+
+ while(pm && pm->frame != cfra)
+ pm = pm->next;
}
- if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
- totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int) cfra));
+ /* read the cache */
+ if(pm) {
+ int totpoint = pm->totpoint;
+
+ if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
+ totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra));
+
+ BKE_ptcache_mem_pointers_init(pm);
- if(!error)
- {
for(i=0; i<totpoint; i++) {
- /* read old cache file format */
- if(use_old) {
- if(pid->read_elem && ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize))
- pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1);
- else if(pid->read_elem)
- { error = 1; break; }
- }
- else {
- if(pid->read_elem && (pm || ptcache_file_read_data(pf)))
- pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL);
- else if(pid->read_elem)
- { error = 1; break; }
- }
+ if(pm->data_types & (1<<BPHYS_DATA_INDEX))
+ index = pm->cur[BPHYS_DATA_INDEX];
- if(pm) {
- BKE_ptcache_mem_incr_pointers(pm);
- index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
- }
+ pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL);
+
+ BKE_ptcache_mem_pointers_incr(pm);
}
- }
- if(!error)
- {
- if(pf2 && pid->read_stream) {
- if(totpoint2 != pid->totpoint(pid->calldata, (int) cfra))
- error = 1;
- else
- {
- // we have stream writing here
- pid->read_stream(pf2, pid->calldata);
- }
+ if(pid->read_extra_data && pm->extradata.first)
+ pid->read_extra_data(pid->calldata, pm, (float)pm->frame);
+
+ /* clean up temporary memory cache */
+ if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+ ptcache_data_free(pm);
+ ptcache_extra_free(pm);
+ MEM_freeN(pm);
}
}
- if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
- totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata, (int) cfra));
+ return 1;
+}
+static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
+{
+ PTCacheMem *pm = NULL;
+ int i;
+ int *index = &i;
- if(!error)
- {
- for(i=0; i<totpoint2; i++) {
- /* read old cache file format */
- if(use_old) {
- if(pid->read_elem && ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) {
- if(!pf && pf2)
- pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2);
- else if(pid->interpolate_elem)
- pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2);
- else
- { error = 1; break; }
- }
- else if(pid->read_elem)
- { error = 1; break; }
- }
- else {
- if(pid->read_elem && (pm2 || ptcache_file_read_data(pf2))) {
- if((!pf && pf2) || (!pm && pm2))
- pid->read_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, (float)cfra2, NULL);
- else if(pid->interpolate_elem)
- pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL);
- else
- { error = 1; break; }
- }
- else if(pid->read_elem)
- { error = 1; break; }
- }
+ /* get a memory cache to read from */
+ if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+ pm = ptcache_disk_frame_to_mem(pid, cfra2);
+ }
+ else {
+ pm = pid->cache->mem_cache.first;
+
+ while(pm && pm->frame != cfra2)
+ pm = pm->next;
+ }
- if(pm2) {
- BKE_ptcache_mem_incr_pointers(pm2);
- index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
- }
+ /* read the cache */
+ if(pm) {
+ int totpoint = pm->totpoint;
+
+ if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
+ totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra));
+
+ BKE_ptcache_mem_pointers_init(pm);
+
+ for(i=0; i<totpoint; i++) {
+ if(pm->data_types & (1<<BPHYS_DATA_INDEX))
+ index = pm->cur[BPHYS_DATA_INDEX];
+
+ pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL);
+ BKE_ptcache_mem_pointers_incr(pm);
+ }
+
+ if(pid->interpolate_extra_data && pm->extradata.first)
+ pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2);
+
+ /* clean up temporary memory cache */
+ if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+ ptcache_data_free(pm);
+ ptcache_extra_free(pm);
+ MEM_freeN(pm);
}
}
- if(pm || pf)
- ret = (pm2 || pf2) ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT;
- else if(pm2 || pf2) {
- ret = PTCACHE_READ_OLD;
- pid->cache->simframe = old_frame;
+ return 1;
+}
+/* reads cache from disk or memory */
+/* possible to get old or interpolated result */
+int BKE_ptcache_read(PTCacheID *pid, float cfra)
+{
+ int cfrai = (int)cfra, cfra1=0, cfra2=0;
+ int ret = 0;
+
+ /* nothing to read to */
+ if(pid->totpoint(pid->calldata, cfrai) == 0)
+ return 0;
+
+ if(pid->cache->flag & PTCACHE_READ_INFO) {
+ pid->cache->flag &= ~PTCACHE_READ_INFO;
+ ptcache_read(pid, 0);
}
- if(pf) {
- ptcache_file_close(pf);
- pf = NULL;
+ /* first check if we have the actual frame cached */
+ if(cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai))
+ cfra1 = cfrai;
+
+ /* no exact cache frame found so try to find cached frames around cfra */
+ if(cfra1 == 0)
+ ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2);
+
+ if(cfra1 == 0 && cfra2 == 0)
+ return 0;
+
+ /* don't read old cache if already simulated past cached frame */
+ if(cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe)
+ return 0;
+ if(cfra1 && cfra1 == cfra2)
+ return 0;
+
+ if(cfra1) {
+ if(pid->read_stream)
+ ptcache_read_stream(pid, cfra1);
+ else if(pid->read_point)
+ ptcache_read(pid, cfra1);
}
- if(pf2) {
- ptcache_file_close(pf2);
- pf = NULL;
+ if(cfra2) {
+ if(pid->read_stream)
+ ptcache_read_stream(pid, cfra2);
+ else if(pid->read_point) {
+ if(cfra1 && cfra2 && pid->interpolate_point)
+ ptcache_interpolate(pid, cfra, cfra1, cfra2);
+ else
+ ptcache_read(pid, cfra2);
+ }
+ }
+
+ if(cfra1)
+ ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT);
+ else if(cfra2) {
+ ret = PTCACHE_READ_OLD;
+ pid->cache->simframe = cfra2;
}
if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
@@ -1681,218 +1749,208 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec)
if(cfra <= pid->cache->last_exact)
pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact));
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact));
}
}
- return (error ? 0 : ret);
+ return ret;
}
-/* TODO for later */
-static void ptcache_make_index_array(PTCacheMem *pm, int totpoint)
+static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
{
- int i, *index;
+ PTCacheFile *pf = NULL;
+ int error = 0;
+
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
+
+ pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
- if(pm->index_array) {
- MEM_freeN(pm->index_array);
- pm->index_array = NULL;
+ if(pf==NULL) {
+ if (G.f & G_DEBUG)
+ printf("Error opening disk cache file for writing\n");
+ return 0;
}
- if(!pm->data[BPHYS_DATA_INDEX])
- return;
+ pf->data_types = pid->data_types;
+ pf->totpoint = totpoint;
+ pf->type = pid->type;
+ pf->flag = 0;
+
+ if(!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)))
+ error = 1;
- pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array");
- index = pm->data[BPHYS_DATA_INDEX];
+ if(!error && pid->write_stream)
+ pid->write_stream(pf, pid->calldata);
- for(i=0; i<pm->totpoint; i++, index++)
- pm->index_array[*index] = i + 1;
+ ptcache_file_close(pf);
+
+ if (error && G.f & G_DEBUG)
+ printf("Error writing to disk cache\n");
+
+ return error == 0;
}
-/* writes cache to disk or memory */
-int BKE_ptcache_write_cache(PTCacheID *pid, int cfra)
+static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
{
PointCache *cache = pid->cache;
- PTCacheFile *pf= NULL, *pf2= NULL;
- int i;
+ PTCacheMem *pm=NULL, *pm2=NULL;
int totpoint = pid->totpoint(pid->calldata, cfra);
- int add = 0, overwrite = 0;
+ int i, error = 0;
- if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
- return 0;
+ pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
- if(cache->flag & PTCACHE_DISK_CACHE) {
- int ofra=0, efra = cache->endframe;
+ pm->totpoint = pid->totwrite(pid->calldata, cfra);
+ pm->data_types = cfra ? pid->data_types : pid->info_types;
- if(cfra==0 && cache->startframe > 0)
- add = 1;
- /* allways start from scratch on the first frame */
- else if(cfra == cache->startframe) {
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- add = 1;
+ ptcache_data_alloc(pm);
+ BKE_ptcache_mem_pointers_init(pm);
+
+ if(overwrite) {
+ if(cache->flag & PTCACHE_DISK_CACHE) {
+ int fra = cfra-1;
+
+ while(fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra))
+ fra--;
+
+ pm2 = ptcache_disk_frame_to_mem(pid, fra);
}
- else {
- /* find last cached frame */
- while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
- efra--;
-
- /* find second last cached frame */
- ofra = efra-1;
- while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
- ofra--;
-
- if(efra >= cache->startframe && cfra > efra) {
- if(ofra >= cache->startframe && efra - ofra < cache->step)
- overwrite = 1;
- else
- add = 1;
+ else
+ pm2 = cache->mem_cache.last;
+ }
+
+ if(pid->write_point) {
+ for(i=0; i<totpoint; i++) {
+ int write = pid->write_point(i, pid->calldata, pm->cur, cfra);
+ if(write) {
+ BKE_ptcache_mem_pointers_incr(pm);
+
+ /* newly born particles have to be copied to previous cached frame */
+ if(overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2))
+ pid->write_point(i, pid->calldata, pm2->cur, cfra);
}
}
+ }
- if(add || overwrite) {
- if(overwrite)
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
-
- pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
- if(!pf)
- return 0;
+ if(pid->write_extra_data)
+ pid->write_extra_data(pid->calldata, pm, cfra);
- pf->type = pid->type;
- pf->totpoint = cfra ? pid->totwrite(pid->calldata, cfra) : totpoint;
- pf->data_types = cfra ? pid->data_types : pid->info_types;
+ pm->frame = cfra;
- if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
- ptcache_file_close(pf);
- return 0;
- }
+ if(cache->flag & PTCACHE_DISK_CACHE) {
+ error += !ptcache_mem_frame_to_disk(pid, pm);
- ptcache_file_init_pointers(pf);
+ if(pm) {
+ ptcache_data_free(pm);
+ ptcache_extra_free(pm);
+ MEM_freeN(pm);
+ }
- if(pf && pid->write_stream) {
- // we have stream writing here
- pid->write_stream(pf, pid->calldata);
- }
- else
- for(i=0; i<totpoint; i++) {
- if(pid->write_elem) {
- int write = pid->write_elem(i, pid->calldata, pf->cur, cfra);
- if(write) {
- if(!ptcache_file_write_data(pf)) {
- ptcache_file_close(pf);
- if(pf2) ptcache_file_close(pf2);
- return 0;
- }
- /* newly born particles have to be copied to previous cached frame */
- else if(overwrite && write == 2) {
- if(!pf2) {
- pf2 = ptcache_file_open(pid, PTCACHE_FILE_UPDATE, ofra);
- if(!pf2) {
- ptcache_file_close(pf);
- return 0;
- }
- pf2->type = pid->type;
- pf2->totpoint = totpoint;
- pf2->data_types = pid->data_types;
- }
- ptcache_file_seek_pointers(i, pf2);
- pid->write_elem(i, pid->calldata, pf2->cur, cfra);
- if(!ptcache_file_write_data(pf2)) {
- ptcache_file_close(pf);
- ptcache_file_close(pf2);
- return 0;
- }
- }
- }
- }
- }
+ if(pm2) {
+ error += !ptcache_mem_frame_to_disk(pid, pm2);
+ ptcache_data_free(pm2);
+ ptcache_extra_free(pm2);
+ MEM_freeN(pm2);
}
}
else {
- PTCacheMem *pm;
- PTCacheMem *pm2;
+ BLI_addtail(&cache->mem_cache, pm);
+ }
- pm2 = cache->mem_cache.first;
-
- /* don't write info file in memory */
- if(cfra==0)
+ return error;
+}
+static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
+{
+ PointCache *cache = pid->cache;
+ int ofra = 0, efra = cache->endframe;
+
+ /* allways start from scratch on the first frame */
+ if(cfra && cfra == cache->startframe) {
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
+ cache->flag &= ~PTCACHE_REDO_NEEDED;
+ return 1;
+ }
+
+ if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+ if(cfra==0 && cache->startframe > 0)
return 1;
- /* allways start from scratch on the first frame */
- if(cfra == cache->startframe) {
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- add = 1;
- }
- else if (cache->mem_cache.last) {
- pm2 = cache->mem_cache.last;
- if(pm2 && cfra > pm2->frame) {
- if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
- overwrite = 1;
- else
- add = 1;
- }
- }
- else
- add = 1;
+ /* find last cached frame */
+ while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
+ efra--;
- if(add || overwrite) {
- if(overwrite)
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame);
+ /* find second last cached frame */
+ ofra = efra-1;
+ while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
+ ofra--;
+ }
+ else {
+ PTCacheMem *pm = cache->mem_cache.last;
+ /* don't write info file in memory */
+ if(cfra == 0)
+ return 0;
- pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
+ if(pm == NULL)
+ return 1;
- pm->totpoint = pid->totwrite(pid->calldata, cfra);
- pm->data_types = cfra ? pid->data_types : pid->info_types;
+ efra = pm->frame;
+ ofra = (pm->prev ? pm->prev->frame : efra - cache->step);
+ }
- ptcache_alloc_data(pm);
- BKE_ptcache_mem_init_pointers(pm);
+ if(efra >= cache->startframe && cfra > efra) {
+ if(ofra >= cache->startframe && efra - ofra < cache->step) {
+ /* overwrite previous frame */
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
+ *overwrite = 1;
+ }
+ return 1;
+ }
- for(i=0; i<totpoint; i++) {
- if(pid->write_elem) {
- int write = pid->write_elem(i, pid->calldata, pm->cur, cfra);
- if(write) {
- BKE_ptcache_mem_incr_pointers(pm);
+ return 0;
+}
+/* writes cache to disk or memory */
+int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
+{
+ PointCache *cache = pid->cache;
+ int totpoint = pid->totpoint(pid->calldata, cfra);
+ int overwrite = 0, error = 0;
- /* newly born particles have to be copied to previous cached frame */
- if(overwrite && write == 2) {
- pm2 = cache->mem_cache.last;
- if(BKE_ptcache_mem_seek_pointers(i, pm2))
- pid->write_elem(i, pid->calldata, pm2->cur, cfra);
- }
- }
- }
- }
- ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra));
+ if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
+ return 0;
- pm->frame = cfra;
- BLI_addtail(&cache->mem_cache, pm);
- }
+ if(ptcache_write_needed(pid, cfra, &overwrite)==0)
+ return 0;
+
+ if(pid->write_stream) {
+ ptcache_write_stream(pid, cfra, totpoint);
+ }
+ else if(pid->write_point) {
+ error += ptcache_write(pid, cfra, overwrite);
}
- if(add || overwrite) {
- if(cfra - cache->last_exact == 1
- || cfra == cache->startframe) {
- cache->last_exact = cfra;
- cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
- }
- else
- cache->flag |= PTCACHE_FRAMES_SKIPPED;
+ /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */
+ if(cfra - cache->last_exact == 1 || cfra == cache->startframe) {
+ cache->last_exact = cfra;
+ cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
}
-
- if(pf) ptcache_file_close(pf);
+ /* Don't mark skipped when writing info file (frame 0) */
+ else if(cfra)
+ cache->flag |= PTCACHE_FRAMES_SKIPPED;
- if(pf2) ptcache_file_close(pf2);
+ /* Update timeline cache display */
+ if(cfra && cache->cached_frames)
+ cache->cached_frames[cfra-cache->startframe] = 1;
BKE_ptcache_update_info(pid);
- return 1;
+ return !error;
}
/* youll need to close yourself after!
* mode - PTCACHE_CLEAR_ALL,
*/
/* Clears & resets */
-void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
+void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
{
- int len; /* store the length of the string */
+ unsigned int len; /* store the length of the string */
+ unsigned int sta, end;
/* mode is same as fopen's modes */
DIR *dir;
@@ -1902,9 +1960,12 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
char path_full[MAX_PTCACHE_FILE];
char ext[MAX_PTCACHE_PATH];
- if(!pid->cache || pid->cache->flag & PTCACHE_BAKED)
+ if(!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED)
return;
+ sta = pid->cache->startframe;
+ end = pid->cache->endframe;
+
#ifndef DURIAN_POINTCACHE_LIB_OK
/* don't allow clearing for linked objects */
if(pid->ob->id.lib)
@@ -1921,7 +1982,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
if(pid->cache->flag & PTCACHE_DISK_CACHE) {
ptcache_path(pid, path);
- len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
+ len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
dir = opendir(path);
if (dir==NULL)
@@ -1934,11 +1995,11 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
if (mode == PTCACHE_CLEAR_ALL) {
pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
- BLI_join_dirfile(path_full, path, de->d_name);
+ BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
BLI_delete(path_full, 0, 0);
} else {
/* read the number of the file */
- int frame, len2 = (int)strlen(de->d_name);
+ unsigned int frame, len2 = (int)strlen(de->d_name);
char num[7];
if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
@@ -1948,8 +2009,10 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) ||
(mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) {
- BLI_join_dirfile(path_full, path, de->d_name);
+ BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
BLI_delete(path_full, 0, 0);
+ if(pid->cache->cached_frames && frame >=sta && frame <= end)
+ pid->cache->cached_frames[frame-sta] = 0;
}
}
}
@@ -1957,25 +2020,34 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
}
}
closedir(dir);
+
+ if(mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames)
+ memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
}
else {
PTCacheMem *pm= pid->cache->mem_cache.first;
PTCacheMem *link= NULL;
- pm= pid->cache->mem_cache.first;
-
if(mode == PTCACHE_CLEAR_ALL) {
/*we want startframe if the cache starts before zero*/
pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
- for(; pm; pm=pm->next)
- ptcache_free_data(pm);
+ for(; pm; pm=pm->next) {
+ ptcache_data_free(pm);
+ ptcache_extra_free(pm);
+ }
BLI_freelistN(&pid->cache->mem_cache);
+
+ if(pid->cache->cached_frames)
+ memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
} else {
while(pm) {
if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
(mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
link = pm;
- ptcache_free_data(pm);
+ if(pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end)
+ pid->cache->cached_frames[pm->frame-sta] = 0;
+ ptcache_data_free(pm);
+ ptcache_extra_free(pm);
pm = pm->next;
BLI_freelinkN(&pid->cache->mem_cache, link);
}
@@ -1989,7 +2061,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
case PTCACHE_CLEAR_FRAME:
if(pid->cache->flag & PTCACHE_DISK_CACHE) {
if(BKE_ptcache_id_exist(pid, cfra)) {
- BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
+ ptcache_filename(pid, filename, cfra, 1, 1); /* no path */
BLI_delete(filename, 0, 0);
}
}
@@ -1998,27 +2070,35 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
for(; pm; pm=pm->next) {
if(pm->frame == cfra) {
- ptcache_free_data(pm);
+ ptcache_data_free(pm);
+ ptcache_extra_free(pm);
BLI_freelinkN(&pid->cache->mem_cache, pm);
break;
}
}
}
+ if(pid->cache->cached_frames && cfra>=sta && cfra<=end)
+ pid->cache->cached_frames[cfra-sta] = 0;
break;
}
BKE_ptcache_update_info(pid);
}
-
-int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
+int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
{
if(!pid->cache)
return 0;
+
+ if(cfra<pid->cache->startframe || cfra > pid->cache->endframe)
+ return 0;
+
+ if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0)
+ return 0;
if(pid->cache->flag & PTCACHE_DISK_CACHE) {
char filename[MAX_PTCACHE_FILE];
- BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
+ ptcache_filename(pid, filename, cfra, 1, 1);
return BLI_exists(filename);
}
@@ -2032,7 +2112,6 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
return 0;
}
}
-
void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
{
Object *ob;
@@ -2073,9 +2152,71 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
*endframe += (int)(offset+0.5f);
}
}
-}
-int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
+ /* verify cached_frames array is up to date */
+ if(cache->cached_frames) {
+ if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) {
+ MEM_freeN(cache->cached_frames);
+ cache->cached_frames = NULL;
+ }
+ }
+
+ if(cache->cached_frames==NULL && cache->endframe > cache->startframe) {
+ unsigned int sta=cache->startframe;
+ unsigned int end=cache->endframe;
+
+ cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array");
+
+ if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+ /* mode is same as fopen's modes */
+ DIR *dir;
+ struct dirent *de;
+ char path[MAX_PTCACHE_PATH];
+ char filename[MAX_PTCACHE_FILE];
+ char ext[MAX_PTCACHE_PATH];
+ unsigned int len; /* store the length of the string */
+
+ ptcache_path(pid, path);
+
+ len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */
+
+ dir = opendir(path);
+ if (dir==NULL)
+ return;
+
+ snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
+
+ while ((de = readdir(dir)) != NULL) {
+ if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
+ if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+ /* read the number of the file */
+ unsigned int frame, len2 = (int)strlen(de->d_name);
+ char num[7];
+
+ if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
+ BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
+ frame = atoi(num);
+
+ if(frame >= sta && frame <= end)
+ cache->cached_frames[frame-sta] = 1;
+ }
+ }
+ }
+ }
+ closedir(dir);
+ }
+ else {
+ PTCacheMem *pm= pid->cache->mem_cache.first;
+
+ while(pm) {
+ if(pm->frame >= sta && pm->frame <= end)
+ cache->cached_frames[pm->frame-sta] = 1;
+ pm = pm->next;
+ }
+ }
+ }
+}
+int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
{
PointCache *cache;
int reset, clear, after;
@@ -2120,7 +2261,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
cache->flag &= ~PTCACHE_REDO_NEEDED;
if(pid->type == PTCACHE_TYPE_CLOTH)
- cloth_free_modifier(pid->ob, pid->calldata);
+ cloth_free_modifier(pid->calldata);
else if(pid->type == PTCACHE_TYPE_SOFTBODY)
sbFreeSimulation(pid->calldata);
else if(pid->type == PTCACHE_TYPE_PARTICLES)
@@ -2137,8 +2278,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
return (reset || clear || after);
}
-
-int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
+int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
{
PTCacheID pid;
ParticleSystem *psys;
@@ -2154,17 +2294,18 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
}
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
- /* Baked cloth hair has to be checked first, because we don't want to reset */
+ /* children or just redo can be calculated without reseting anything */
+ if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
+ skip = 1;
+ /* Baked cloth hair has to be checked too, because we don't want to reset */
/* particles or cloth in that case -jahka */
- if(psys->clmd) {
+ else if(psys->clmd) {
BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED)))
reset |= BKE_ptcache_id_reset(scene, &pid, mode);
else
skip = 1;
}
- else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
- skip = 1;
if(skip == 0 && psys->part) {
BKE_ptcache_id_from_particles(&pid, ob, psys);
@@ -2183,9 +2324,6 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
{
BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md);
reset |= BKE_ptcache_id_reset(scene, &pid, mode);
-
- BKE_ptcache_id_from_smoke_turbulence(&pid, ob, (SmokeModifierData*)md);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
}
}
}
@@ -2219,7 +2357,7 @@ void BKE_ptcache_remove(void)
if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
/* do nothing */
} else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
- BLI_join_dirfile(path_full, path, de->d_name);
+ BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
BLI_delete(path_full, 0, 0);
} else {
rmdir = 0; /* unknown file, dont remove the dir */
@@ -2250,12 +2388,12 @@ void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable)
if(CONTINUE_PHYSICS == 0) {
for(ob=bmain->object.first; ob; ob=ob->id.next)
if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
}
-int BKE_ptcache_get_continue_physics()
+int BKE_ptcache_get_continue_physics(void)
{
return CONTINUE_PHYSICS;
}
@@ -2282,8 +2420,10 @@ void BKE_ptcache_free_mem(ListBase *mem_cache)
PTCacheMem *pm = mem_cache->first;
if(pm) {
- for(; pm; pm=pm->next)
- ptcache_free_data(pm);
+ for(; pm; pm=pm->next) {
+ ptcache_data_free(pm);
+ ptcache_extra_free(pm);
+ }
BLI_freelistN(mem_cache);
}
@@ -2293,6 +2433,8 @@ void BKE_ptcache_free(PointCache *cache)
BKE_ptcache_free_mem(&cache->mem_cache);
if(cache->edit && cache->free_edit)
cache->free_edit(cache->edit);
+ if(cache->cached_frames)
+ MEM_freeN(cache->cached_frames);
MEM_freeN(cache);
}
void BKE_ptcache_free_list(ListBase *ptcaches)
@@ -2315,6 +2457,8 @@ static PointCache *ptcache_copy(PointCache *cache)
/* hmm, should these be copied over instead? */
ncache->mem_cache.first = NULL;
ncache->mem_cache.last = NULL;
+ ncache->cached_frames = NULL;
+ ncache->edit = NULL;
ncache->flag= 0;
ncache->simframe= 0;
@@ -2353,7 +2497,7 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
baker.scene=scene;
baker.quick_step=scene->physics_settings.quick_cache_step;
- BKE_ptcache_make_cache(&baker);
+ BKE_ptcache_bake(&baker);
}
/* Simulation thread, no need for interlocks as data written in both threads
@@ -2366,10 +2510,10 @@ typedef struct {
int *cfra_ptr;
Main *main;
Scene *scene;
-} ptcache_make_cache_data;
+} ptcache_bake_data;
-static void *ptcache_make_cache_thread(void *ptr) {
- ptcache_make_cache_data *data = (ptcache_make_cache_data*)ptr;
+static void *ptcache_bake_thread(void *ptr) {
+ ptcache_bake_data *data = (ptcache_bake_data*)ptr;
for(; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) {
scene_update_for_newframe(data->main, data->scene, data->scene->lay);
@@ -2383,11 +2527,11 @@ static void *ptcache_make_cache_thread(void *ptr) {
}
/* if bake is not given run simulations to current frame */
-void BKE_ptcache_make_cache(PTCacheBaker* baker)
+void BKE_ptcache_bake(PTCacheBaker* baker)
{
Main *bmain = baker->main;
Scene *scene = baker->scene;
- Scene *sce; /* SETLOOPER macro only */
+ Scene *sce_iter; /* SETLOOPER macro only */
Base *base;
ListBase pidlist;
PTCacheID *pid = baker->pid;
@@ -2398,7 +2542,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
int bake = baker->bake;
int render = baker->render;
ListBase threads;
- ptcache_make_cache_data thread_data;
+ ptcache_bake_data thread_data;
int progress, old_progress;
thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA;
@@ -2458,7 +2602,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
cache->flag &= ~PTCACHE_BAKED;
}
}
- else for(SETLOOPER(scene, base)) {
+ else for(SETLOOPER(scene, sce_iter, base)) {
/* cache/bake everything in the scene */
BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
@@ -2499,12 +2643,14 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
thread_data.break_operation = FALSE;
thread_data.thread_ended = FALSE;
old_progress = -1;
+
+ WM_cursor_wait(1);
if(G.background) {
- ptcache_make_cache_thread((void*)&thread_data);
+ ptcache_bake_thread((void*)&thread_data);
}
else {
- BLI_init_threads(&threads, ptcache_make_cache_thread, 1);
+ BLI_init_threads(&threads, ptcache_bake_thread, 1);
BLI_insert_thread(&threads, (void*)&thread_data);
while (thread_data.thread_ended == FALSE) {
@@ -2542,10 +2688,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
cache->flag |= PTCACHE_BAKED;
/* write info file */
if(cache->flag & PTCACHE_DISK_CACHE)
- BKE_ptcache_write_cache(pid, 0);
+ BKE_ptcache_write(pid, 0);
}
}
- else for(SETLOOPER(scene, base)) {
+ else for(SETLOOPER(scene, sce_iter, base)) {
BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
for(pid=pidlist.first; pid; pid=pid->next) {
@@ -2565,7 +2711,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
if(bake) {
cache->flag |= PTCACHE_BAKED;
if(cache->flag & PTCACHE_DISK_CACHE)
- BKE_ptcache_write_cache(pid, 0);
+ BKE_ptcache_write(pid, 0);
}
}
BLI_freelistN(&pidlist);
@@ -2582,126 +2728,59 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
else if (baker->progressend)
baker->progressend(baker->progresscontext);
+ WM_cursor_wait(0);
+
/* TODO: call redraw all windows somehow */
}
/* Helpers */
void BKE_ptcache_disk_to_mem(PTCacheID *pid)
{
PointCache *cache = pid->cache;
- PTCacheFile *pf;
- PTCacheMem *pm;
-
+ PTCacheMem *pm = NULL;
+ int baked = cache->flag & PTCACHE_BAKED;
int cfra, sfra = cache->startframe, efra = cache->endframe;
- int i;
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+ /* Remove possible bake flag to allow clear */
+ cache->flag &= ~PTCACHE_BAKED;
- for(cfra=sfra; cfra <= efra; cfra++) {
- pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
-
- if(pf) {
- if(!ptcache_file_read_header_begin(pf)) {
- printf("Can't yet convert old cache format\n");
- cache->flag |= PTCACHE_DISK_CACHE;
- ptcache_file_close(pf);
- return;
- }
-
- if(pf->type != pid->type || !pid->read_header(pf)) {
- cache->flag |= PTCACHE_DISK_CACHE;
- ptcache_file_close(pf);
- return;
- }
-
- pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
-
- pm->totpoint = pf->totpoint;
- pm->data_types = pf->data_types;
- pm->frame = cfra;
-
- ptcache_alloc_data(pm);
- BKE_ptcache_mem_init_pointers(pm);
- ptcache_file_init_pointers(pf);
+ /* PTCACHE_DISK_CACHE flag was cleared already */
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- for(i=0; i<pm->totpoint; i++) {
- if(!ptcache_file_read_data(pf)) {
- printf("Error reading from disk cache\n");
-
- cache->flag |= PTCACHE_DISK_CACHE;
-
- ptcache_free_data(pm);
- MEM_freeN(pm);
- ptcache_file_close(pf);
-
- return;
- }
- ptcache_copy_data(pf->cur, pm->cur);
- BKE_ptcache_mem_incr_pointers(pm);
- }
+ /* restore possible bake flag */
+ cache->flag |= baked;
- ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra));
+ for(cfra=sfra; cfra <= efra; cfra++) {
+ pm = ptcache_disk_frame_to_mem(pid, cfra);
+ if(pm)
BLI_addtail(&pid->cache->mem_cache, pm);
-
- ptcache_file_close(pf);
- }
}
-
}
void BKE_ptcache_mem_to_disk(PTCacheID *pid)
{
PointCache *cache = pid->cache;
- PTCacheFile *pf;
- PTCacheMem *pm;
- int i;
+ PTCacheMem *pm = cache->mem_cache.first;
+ int baked = cache->flag & PTCACHE_BAKED;
- pm = cache->mem_cache.first;
+ /* Remove possible bake flag to allow clear */
+ cache->flag &= ~PTCACHE_BAKED;
+ /* PTCACHE_DISK_CACHE flag was set already */
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- for(; pm; pm=pm->next) {
- pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
-
- if(pf) {
- pf->data_types = pm->data_types;
- pf->totpoint = pm->totpoint;
- pf->type = pid->type;
+ /* restore possible bake flag */
+ cache->flag |= baked;
- BKE_ptcache_mem_init_pointers(pm);
- ptcache_file_init_pointers(pf);
-
- if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
- if (G.f & G_DEBUG)
- printf("Error writing to disk cache\n");
- cache->flag &= ~PTCACHE_DISK_CACHE;
-
- ptcache_file_close(pf);
- return;
- }
-
- for(i=0; i<pm->totpoint; i++) {
- ptcache_copy_data(pm->cur, pf->cur);
- if(!ptcache_file_write_data(pf)) {
- if (G.f & G_DEBUG)
- printf("Error writing to disk cache\n");
- cache->flag &= ~PTCACHE_DISK_CACHE;
-
- ptcache_file_close(pf);
- return;
- }
- BKE_ptcache_mem_incr_pointers(pm);
- }
-
- ptcache_file_close(pf);
-
- /* write info file */
- if(cache->flag & PTCACHE_BAKED)
- BKE_ptcache_write_cache(pid, 0);
+ for(; pm; pm=pm->next) {
+ if(ptcache_mem_frame_to_disk(pid, pm)==0) {
+ cache->flag &= ~PTCACHE_DISK_CACHE;
+ break;
}
- else
- if (G.f & G_DEBUG)
- printf("Error creating disk cache file\n");
}
+
+ /* write info file */
+ if(cache->flag & PTCACHE_BAKED)
+ BKE_ptcache_write(pid, 0);
}
void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
{
@@ -2715,6 +2794,11 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
return;
}
+ if(cache->cached_frames) {
+ MEM_freeN(cache->cached_frames);
+ cache->cached_frames=NULL;
+ }
+
if(cache->flag & PTCACHE_DISK_CACHE)
BKE_ptcache_mem_to_disk(pid);
else
@@ -2726,15 +2810,75 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
cache->last_exact = last_exact;
+ BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL);
+
BKE_ptcache_update_info(pid);
}
+void BKE_ptcache_disk_cache_rename(PTCacheID *pid, char *from, char *to)
+{
+ char old_name[80];
+ int len; /* store the length of the string */
+ /* mode is same as fopen's modes */
+ DIR *dir;
+ struct dirent *de;
+ char path[MAX_PTCACHE_PATH];
+ char old_filename[MAX_PTCACHE_FILE];
+ char new_path_full[MAX_PTCACHE_FILE];
+ char old_path_full[MAX_PTCACHE_FILE];
+ char ext[MAX_PTCACHE_PATH];
+
+ /* save old name */
+ strcpy(old_name, pid->cache->name);
+
+ /* get "from" filename */
+ strcpy(pid->cache->name, from);
+
+ len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */
+
+ ptcache_path(pid, path);
+ dir = opendir(path);
+ if(dir==NULL) {
+ strcpy(pid->cache->name, old_name);
+ return;
+ }
+
+ snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
+
+ /* put new name into cache */
+ strcpy(pid->cache->name, to);
+
+ while ((de = readdir(dir)) != NULL) {
+ if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
+ if (strncmp(old_filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+ /* read the number of the file */
+ int frame, len2 = (int)strlen(de->d_name);
+ char num[7];
+
+ if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
+ BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
+ frame = atoi(num);
+
+ BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name);
+ ptcache_filename(pid, new_path_full, frame, 1, 1);
+ BLI_rename(old_path_full, new_path_full);
+ }
+ }
+ }
+ }
+ closedir(dir);
+
+ strcpy(pid->cache->name, old_name);
+}
+
void BKE_ptcache_load_external(PTCacheID *pid)
{
/*todo*/
PointCache *cache = pid->cache;
int len; /* store the length of the string */
int info = 0;
+ int start = MAXFRAME;
+ int end = -1;
/* mode is same as fopen's modes */
DIR *dir;
@@ -2746,13 +2890,9 @@ void BKE_ptcache_load_external(PTCacheID *pid)
if(!cache)
return;
- cache->startframe = MAXFRAME;
- cache->endframe = -1;
- cache->totpoint = 0;
-
ptcache_path(pid, path);
- len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */
+ len = ptcache_filename(pid, filename, 1, 0, 0); /* no path */
dir = opendir(path);
if (dir==NULL)
@@ -2775,8 +2915,8 @@ void BKE_ptcache_load_external(PTCacheID *pid)
frame = atoi(num);
if(frame) {
- cache->startframe = MIN2(cache->startframe, frame);
- cache->endframe = MAX2(cache->endframe, frame);
+ start = MIN2(start, frame);
+ end = MAX2(end, frame);
}
else
info = 1;
@@ -2786,15 +2926,21 @@ void BKE_ptcache_load_external(PTCacheID *pid)
}
closedir(dir);
- if(cache->startframe != MAXFRAME) {
+ if(start != MAXFRAME) {
PTCacheFile *pf;
+ cache->startframe = start;
+ cache->endframe = end;
+ cache->totpoint = 0;
+
+ if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
+ ; /*necessary info in every file*/
/* read totpoint from info file (frame 0) */
- if(info) {
+ else if(info) {
pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0);
if(pf) {
- if(ptcache_file_read_header_begin(pf)) {
+ if(ptcache_file_header_begin_read(pf)) {
if(pf->type == pid->type && pid->read_header(pf)) {
cache->totpoint = pf->totpoint;
cache->flag |= PTCACHE_READ_INFO;
@@ -2809,7 +2955,7 @@ void BKE_ptcache_load_external(PTCacheID *pid)
/* or from any old format cache file */
else {
float old_data[14];
- int elemsize = ptcache_pid_old_elemsize(pid);
+ int elemsize = ptcache_old_elemsize(pid);
pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
if(pf) {
@@ -2819,16 +2965,17 @@ void BKE_ptcache_load_external(PTCacheID *pid)
ptcache_file_close(pf);
}
}
+ cache->flag |= (PTCACHE_BAKED|PTCACHE_DISK_CACHE|PTCACHE_SIMULATION_VALID);
+ cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
}
- cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
-
BKE_ptcache_update_info(pid);
}
void BKE_ptcache_update_info(PTCacheID *pid)
{
PointCache *cache = pid->cache;
+ PTCacheExtra *extra = NULL;
int totframes = 0;
char mem_info[64];
@@ -2840,7 +2987,10 @@ void BKE_ptcache_update_info(PTCacheID *pid)
totframes++;
}
- if(totframes && cache->totpoint)
+ /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */
+ if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes)
+ sprintf(cache->info, "%i frames found!", totframes);
+ else if(totframes && cache->totpoint)
sprintf(cache->info, "%i points found!", cache->totpoint);
else
sprintf(cache->info, "No valid data to read!");
@@ -2848,14 +2998,25 @@ void BKE_ptcache_update_info(PTCacheID *pid)
}
if(cache->flag & PTCACHE_DISK_CACHE) {
- int cfra = cache->startframe;
+ if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
+ {
+ int totpoint = pid->totpoint(pid->calldata, 0);
- for(; cfra<=cache->endframe; cfra++) {
- if(BKE_ptcache_id_exist(pid, cfra))
- totframes++;
+ if(cache->totpoint > totpoint)
+ sprintf(mem_info, "%i cells + High Resolution cached", totpoint);
+ else
+ sprintf(mem_info, "%i cells cached", totpoint);
}
+ else {
+ int cfra = cache->startframe;
- sprintf(mem_info, "%i frames on disk", totframes);
+ for(; cfra<=cache->endframe; cfra++) {
+ if(BKE_ptcache_id_exist(pid, cfra))
+ totframes++;
+ }
+
+ sprintf(mem_info, "%i frames on disk", totframes);
+ }
}
else {
PTCacheMem *pm = cache->mem_cache.first;
@@ -2864,7 +3025,15 @@ void BKE_ptcache_update_info(PTCacheID *pid)
for(; pm; pm=pm->next) {
for(i=0; i<BPHYS_TOT_DATA; i++)
- bytes += pm->data[i] ? MEM_allocN_len(pm->data[i]) : 0.0f;
+ bytes += MEM_allocN_len(pm->data[i]);
+
+ for(extra=pm->extradata.first; extra; extra=extra->next) {
+ bytes += MEM_allocN_len(extra->data);
+ bytes += sizeof(PTCacheExtra);
+ }
+
+ bytes += sizeof(PTCacheMem);
+
totframes++;
}
@@ -2888,13 +3057,17 @@ void BKE_ptcache_update_info(PTCacheID *pid)
void BKE_ptcache_validate(PointCache *cache, int framenr)
{
- cache->flag |= PTCACHE_SIMULATION_VALID;
- cache->simframe = framenr;
+ if(cache) {
+ cache->flag |= PTCACHE_SIMULATION_VALID;
+ cache->simframe = framenr;
+ }
}
void BKE_ptcache_invalidate(PointCache *cache)
{
- cache->flag &= ~PTCACHE_SIMULATION_VALID;
- cache->simframe = 0;
- cache->last_exact = MIN2(cache->startframe, 0);
+ if(cache) {
+ cache->flag &= ~PTCACHE_SIMULATION_VALID;
+ cache->simframe = 0;
+ cache->last_exact = MIN2(cache->startframe, 0);
+ }
}
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index d8001572b4f..e907b628242 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -43,6 +43,8 @@
#include "BLI_blenlib.h"
+#include "BKE_property.h"
+
void free_property(bProperty *prop)
{
@@ -93,7 +95,7 @@ void init_property(bProperty *prop)
/* also use when property changes type */
if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
- prop->poin= 0;
+ prop->poin= NULL;
prop->data= 0;
@@ -179,7 +181,7 @@ void unique_property(bProperty *first, bProperty *prop, int force)
}
}
-bProperty *get_ob_property(Object *ob, char *name)
+bProperty *get_ob_property(Object *ob, const char *name)
{
return BLI_findstring(&ob->prop, name, offsetof(bProperty, name));
}
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 3773757f5d5..fa2e867d483 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -29,10 +29,11 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
#include "BKE_report.h"
#include "BKE_global.h" /* G.background only */
-#include "BKE_utildefines.h"
+
#include <stdarg.h>
#include <stdio.h>
@@ -44,7 +45,7 @@
#endif
#endif
-static char *report_type_str(int type)
+static const char *report_type_str(int type)
{
switch(type) {
case RPT_DEBUG: return "Debug";
@@ -82,7 +83,7 @@ void BKE_reports_clear(ReportList *reports)
while (report) {
report_next= report->next;
- MEM_freeN(report->message);
+ MEM_freeN((void *)report->message);
MEM_freeN(report);
report= report_next;
}
@@ -95,23 +96,23 @@ void BKE_report(ReportList *reports, ReportType type, const char *message)
Report *report;
int len;
- /* exception, print and return in background, no reason to store a list */
- if(G.background)
- reports= NULL;
-
- if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
+ /* in background mode always print otherwise there are cases the errors wont be displayed,
+ * but still add to the report list since this is used for python exception handling */
+ if(G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
printf("%s: %s\n", report_type_str(type), message);
fflush(stdout); /* this ensures the message is printed before a crash */
}
if(reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
+ char *message_alloc;
report= MEM_callocN(sizeof(Report), "Report");
report->type= type;
report->typestr= report_type_str(type);
len= strlen(message);
- report->message= MEM_callocN(sizeof(char)*(len+1), "ReportMessage");
- memcpy(report->message, message, sizeof(char)*(len+1));
+ message_alloc= MEM_callocN(sizeof(char)*(len+1), "ReportMessage");
+ memcpy(message_alloc, message, sizeof(char)*(len+1));
+ report->message= message_alloc;
report->len= len;
BLI_addtail(&reports->list, report);
}
@@ -123,10 +124,11 @@ void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...)
Report *report;
va_list args;
- if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
+ if(G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
va_start(args, format);
vprintf(format, args);
va_end(args);
+ fprintf(stdout, "\n"); /* otherise each report needs to include a \n */
fflush(stdout); /* this ensures the message is printed before a crash */
}
@@ -162,7 +164,7 @@ void BKE_reports_prepend(ReportList *reports, const char *prepend)
BLI_dynstr_append(ds, prepend);
BLI_dynstr_append(ds, report->message);
- MEM_freeN(report->message);
+ MEM_freeN((void *)report->message);
report->message= BLI_dynstr_get_cstring(ds);
report->len= BLI_dynstr_get_len(ds);
@@ -187,7 +189,7 @@ void BKE_reports_prependf(ReportList *reports, const char *prepend, ...)
va_end(args);
BLI_dynstr_append(ds, report->message);
- MEM_freeN(report->message);
+ MEM_freeN((void *)report->message);
report->message= BLI_dynstr_get_cstring(ds);
report->len= BLI_dynstr_get_len(ds);
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 9589b1e4f98..c8a855c8156 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -86,7 +86,7 @@ void copy_sensors(ListBase *lbn, ListBase *lbo)
{
bSensor *sens, *sensn;
- lbn->first= lbn->last= 0;
+ lbn->first= lbn->last= NULL;
sens= lbo->first;
while(sens) {
sensn= copy_sensor(sens);
@@ -253,7 +253,7 @@ void copy_controllers(ListBase *lbn, ListBase *lbo)
{
bController *cont, *contn;
- lbn->first= lbn->last= 0;
+ lbn->first= lbn->last= NULL;
cont= lbo->first;
while(cont) {
contn= copy_controller(cont);
@@ -267,7 +267,7 @@ void init_controller(bController *cont)
/* also use when controller changes type, leave actuators... */
if(cont->data) MEM_freeN(cont->data);
- cont->data= 0;
+ cont->data= NULL;
switch(cont->type) {
case CONT_EXPRESSION:
@@ -375,7 +375,7 @@ void copy_actuators(ListBase *lbn, ListBase *lbo)
{
bActuator *act, *actn;
- lbn->first= lbn->last= 0;
+ lbn->first= lbn->last= NULL;
act= lbo->first;
while(act) {
actn= copy_actuator(act);
@@ -393,7 +393,7 @@ void init_actuator(bActuator *act)
bSoundActuator *sa;
if(act->data) MEM_freeN(act->data);
- act->data= 0;
+ act->data= NULL;
switch(act->type) {
case ACT_ACTION:
@@ -512,7 +512,7 @@ void clear_sca_new_poins_ob(Object *ob)
}
}
-void clear_sca_new_poins()
+void clear_sca_new_poins(void)
{
Object *ob;
@@ -579,7 +579,16 @@ void set_sca_new_poins_ob(Object *ob)
else if(act->type==ACT_PARENT) {
bParentActuator *para = act->data;
ID_NEW(para->ob);
- }
+ }
+ else if(act->type==ACT_ARMATURE) {
+ bArmatureActuator *aa = act->data;
+ ID_NEW(aa->target);
+ ID_NEW(aa->subtarget);
+ }
+ else if(act->type==ACT_PROPERTY) {
+ bPropertyActuator *pa= act->data;
+ ID_NEW(pa->ob);
+ }
else if(act->type==ACT_ARMATURE) {
bArmatureActuator *aa = act->data;
ID_NEW(aa->target);
@@ -595,7 +604,7 @@ void set_sca_new_poins_ob(Object *ob)
}
-void set_sca_new_poins()
+void set_sca_new_poins(void)
{
Object *ob;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 8793c412d7d..1611116f0af 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -39,6 +39,8 @@
#include <io.h>
#endif
+#include "MEM_guardedalloc.h"
+
#include "DNA_anim_types.h"
#include "DNA_group_types.h"
#include "DNA_object_types.h"
@@ -46,7 +48,9 @@
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
-#include "MEM_guardedalloc.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
@@ -63,15 +67,12 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_world.h"
-#include "BKE_utildefines.h"
+
#include "BKE_sound.h"
//XXX #include "BIF_previewrender.h"
//XXX #include "BIF_editseq.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-
//XXX #include "nla.h"
#ifdef WIN32
@@ -106,7 +107,7 @@ void free_qtcodecdata(QuicktimeCodecData *qcd)
}
}
-Scene *copy_scene(Main *bmain, Scene *sce, int type)
+Scene *copy_scene(Scene *sce, int type)
{
Scene *scen;
ToolSettings *ts;
@@ -128,7 +129,6 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
id_us_plus((ID *)scen->world);
id_us_plus((ID *)scen->set);
- id_us_plus((ID *)scen->ima);
id_us_plus((ID *)scen->gm.dome.warptext);
scen->ed= NULL;
@@ -171,7 +171,7 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets));
if(sce->nodetree) {
- scen->nodetree= ntreeCopyTree(sce->nodetree, 0);
+ scen->nodetree= ntreeCopyTree(sce->nodetree); /* copies actions */
ntreeSwitchID(scen->nodetree, &sce->id, &scen->id);
}
@@ -210,23 +210,26 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
if(type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) {
ID_NEW(scen->camera);
}
+
+ /* before scene copy */
+ sound_create_scene(scen);
/* world */
if(type == SCE_COPY_FULL) {
+ BKE_copy_animdata_id_action((ID *)scen);
if(scen->world) {
id_us_plus((ID *)scen->world);
scen->world= copy_world(scen->world);
+ BKE_copy_animdata_id_action((ID *)scen->world);
}
if(sce->ed) {
scen->ed= MEM_callocN( sizeof(Editing), "addseq");
scen->ed->seqbasep= &scen->ed->seqbase;
- seqbase_dupli_recursive(sce, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL);
+ seqbase_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL);
}
}
- sound_create_scene(scen);
-
return scen;
}
@@ -315,7 +318,7 @@ void free_scene(Scene *sce)
sound_destroy_scene(sce);
}
-Scene *add_scene(char *name)
+Scene *add_scene(const char *name)
{
Main *bmain= G.main;
Scene *sce;
@@ -336,26 +339,42 @@ Scene *add_scene(char *name)
sce->r.yasp= 1;
sce->r.xparts= 8;
sce->r.yparts= 8;
- sce->r.size= 25;
+ sce->r.mblur_samples= 1;
+ sce->r.filtertype= R_FILTER_MITCH;
+ sce->r.size= 50;
sce->r.planes= 24;
+ sce->r.imtype= R_PNG;
sce->r.quality= 90;
+ sce->r.displaymode= R_OUTPUT_AREA;
sce->r.framapto= 100;
sce->r.images= 100;
sce->r.framelen= 1.0;
- sce->r.frs_sec= 25;
+ sce->r.blurfac= 0.5;
+ sce->r.frs_sec= 24;
sce->r.frs_sec_base= 1;
+ sce->r.edgeint= 10;
sce->r.ocres = 128;
sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT;
+ sce->r.gauss= 1.0;
+
+ /* deprecated but keep for upwards compat */
+ sce->r.postgamma= 1.0;
+ sce->r.posthue= 0.0;
+ sce->r.postsat= 1.0;
sce->r.bake_mode= 1; /* prevent to include render stuff here */
- sce->r.bake_filter= 8;
+ sce->r.bake_filter= 2;
sce->r.bake_osa= 5;
sce->r.bake_flag= R_BAKE_CLEAR;
sce->r.bake_normal_space= R_BAKE_SPACE_TANGENT;
-
sce->r.scemode= R_DOCOMP|R_DOSEQ|R_EXTENSION;
- sce->r.stamp= R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_SCENE|R_STAMP_CAMERA|R_STAMP_RENDERTIME;
+ sce->r.stamp= R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_CAMERA|R_STAMP_SCENE|R_STAMP_FILENAME|R_STAMP_RENDERTIME;
sce->r.stamp_font_id= 12;
+ sce->r.fg_stamp[0]= sce->r.fg_stamp[1]= sce->r.fg_stamp[2]= 0.8f;
+ sce->r.fg_stamp[3]= 1.0f;
+ sce->r.bg_stamp[0]= sce->r.bg_stamp[1]= sce->r.bg_stamp[2]= 0.0f;
+ sce->r.bg_stamp[3]= 0.25f;
+ sce->r.raytrace_options = R_RAYTRACE_USE_INSTANCES;
sce->r.seq_prev_type= OB_SOLID;
sce->r.seq_rend_type= OB_SOLID;
@@ -441,9 +460,11 @@ Scene *add_scene(char *name)
pset->brush[a].count= 10;
}
pset->brush[PE_BRUSH_CUT].strength= 100;
-
- sce->jumpframe = 10;
+
sce->r.ffcodecdata.audio_mixrate = 44100;
+ sce->r.ffcodecdata.audio_volume = 1.0f;
+
+ BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
sce->audio.distance_model = 2.0;
sce->audio.doppler_factor = 1.0;
@@ -469,8 +490,8 @@ Scene *add_scene(char *name)
sce->gm.dome.resbuf = 1.0f;
sce->gm.dome.tilt = 0;
- sce->gm.xplay= 800;
- sce->gm.yplay= 600;
+ sce->gm.xplay= 640;
+ sce->gm.yplay= 480;
sce->gm.freqplay= 60;
sce->gm.depth= 32;
@@ -560,16 +581,16 @@ void set_scene_bg(Main *bmain, Scene *scene)
}
/* called from creator.c */
-Scene *set_scene_name(Main *bmain, char *name)
+Scene *set_scene_name(Main *bmain, const char *name)
{
Scene *sce= (Scene *)find_id("SC", name);
if(sce) {
set_scene_bg(bmain, sce);
- printf("Scene switch: '%s' in file: '%s'\n", name, G.sce);
+ printf("Scene switch: '%s' in file: '%s'\n", name, G.main->name);
return sce;
}
- printf("Can't find scene: '%s' in file: '%s'\n", name, G.sce);
+ printf("Can't find scene: '%s' in file: '%s'\n", name, G.main->name);
return NULL;
}
@@ -840,6 +861,21 @@ int scene_marker_tfm_extend(Scene *scene, int delta, int flag, int frame, char s
return tot;
}
+int scene_marker_tfm_scale(struct Scene *scene, float value, int flag)
+{
+ TimeMarker *marker;
+ int tot= 0;
+
+ for (marker= scene->markers.first; marker; marker= marker->next) {
+ if ((marker->flag & flag) == flag) {
+ marker->frame= CFRA + (int)floorf(((float)(marker->frame - CFRA) * value) + 0.5f);
+ tot++;
+ }
+ }
+
+ return tot;
+}
+
Base *scene_add_base(Scene *sce, Object *ob)
{
Base *b= MEM_callocN(sizeof(*b), "scene_add_base");
@@ -909,31 +945,75 @@ float BKE_curframe(Scene *scene)
return ctime;
}
+/* drivers support/hacks
+ * - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render
+ * - these are always run since the depsgraph can't handle non-object data
+ * - these happen after objects are all done so that we can read in their final transform values,
+ * though this means that objects can't refer to scene info for guidance...
+ */
+static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
+{
+ float ctime = BKE_curframe(scene);
+
+ /* scene itself */
+ if (scene->adt && scene->adt->drivers.first) {
+ BKE_animsys_evaluate_animdata(&scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
+ }
+
+ /* world */
+ // TODO: what about world textures? but then those have nodes too...
+ if (scene->world) {
+ ID *wid = (ID *)scene->world;
+ AnimData *adt= BKE_animdata_from_id(wid);
+
+ if (adt && adt->drivers.first)
+ BKE_animsys_evaluate_animdata(wid, adt, ctime, ADT_RECALC_DRIVERS);
+ }
+
+ /* nodes */
+ if (scene->nodetree) {
+ ID *nid = (ID *)scene->nodetree;
+ AnimData *adt= BKE_animdata_from_id(nid);
+
+ if (adt && adt->drivers.first)
+ BKE_animsys_evaluate_animdata(nid, adt, ctime, ADT_RECALC_DRIVERS);
+ }
+}
+
static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent)
{
Base *base;
+
+
+ scene->customdata_mask= scene_parent->customdata_mask;
/* sets first, we allow per definition current scene to have
dependencies on sets, but not the other way around. */
- if(scene->set)
+ if (scene->set)
scene_update_tagged_recursive(bmain, scene->set, scene_parent);
-
- for(base= scene->base.first; base; base= base->next) {
+
+ /* scene objects */
+ for (base= scene->base.first; base; base= base->next) {
Object *ob= base->object;
-
+
object_handle_update(scene_parent, ob);
-
+
if(ob->dup_group && (ob->transflag & OB_DUPLIGROUP))
group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
/* always update layer, so that animating layers works */
base->lay= ob->lay;
}
+
+ /* scene drivers... */
+ scene_update_drivers(bmain, scene);
}
/* this is called in main loop, doing tagged updates before redraw */
void scene_update_tagged(Main *bmain, Scene *scene)
{
+ DAG_ids_flush_tagged(bmain);
+
scene->physics_settings.quick_cache_step= 0;
/* update all objects: drivers, matrices, displists, etc. flags set
@@ -943,14 +1023,14 @@ void scene_update_tagged(Main *bmain, Scene *scene)
/* recalc scene animation data here (for sequencer) */
{
- float ctime = BKE_curframe(scene);
AnimData *adt= BKE_animdata_from_id(&scene->id);
-
- if(adt && (adt->recalc & ADT_RECALC_ANIM))
+ float ctime = BKE_curframe(scene);
+
+ if (adt && (adt->recalc & ADT_RECALC_ANIM))
BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, 0);
}
-
- if(scene->physics_settings.quick_cache_step)
+
+ if (scene->physics_settings.quick_cache_step)
BKE_ptcache_quick_cache_all(bmain, scene);
/* in the future this should handle updates for all datablocks, not
@@ -974,7 +1054,7 @@ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
/* Following 2 functions are recursive
* so dont call within 'scene_update_tagged_recursive' */
- DAG_scene_update_flags(bmain, sce, lay); // only stuff that moves or needs display still
+ DAG_scene_update_flags(bmain, sce, lay, TRUE); // only stuff that moves or needs display still
/* All 'standard' (i.e. without any dependencies) animation is handled here,
* with an 'local' to 'macro' order of evaluation. This should ensure that
@@ -1041,20 +1121,20 @@ float get_render_aosss_error(RenderData *r, float error)
}
/* helper function for the SETLOOPER macro */
-Base *_setlooper_base_step(Scene **sce, Base *base)
+Base *_setlooper_base_step(Scene **sce_iter, Base *base)
{
if(base && base->next) {
/* common case, step to the next */
return base->next;
}
- else if(base==NULL && (*sce)->base.first) {
+ else if(base==NULL && (*sce_iter)->base.first) {
/* first time looping, return the scenes first base */
- return (Base *)(*sce)->base.first;
+ return (Base *)(*sce_iter)->base.first;
}
else {
/* reached the end, get the next base in the set */
- while((*sce= (*sce)->set)) {
- base= (Base *)(*sce)->base.first;
+ while((*sce_iter= (*sce_iter)->set)) {
+ base= (Base *)(*sce_iter)->base.first;
if(base) {
return base;
}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 6f1d32898f9..58900e603e3 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -109,7 +109,7 @@ ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid)
}
-const ListBase *BKE_spacetypes_list()
+const ListBase *BKE_spacetypes_list(void)
{
return &spacetypes;
}
diff --git a/source/blender/blenkernel/intern/script.c b/source/blender/blenkernel/intern/script.c
index c07032f71d7..6ffac09e843 100644
--- a/source/blender/blenkernel/intern/script.c
+++ b/source/blender/blenkernel/intern/script.c
@@ -36,7 +36,7 @@
/*
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
#include "BPY_extern.h" // Blender Python library
#endif
*/
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index 37bd3983769..000d08e4df2 100755
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -1,5 +1,5 @@
-/**
-* $Id: seqcache.c 30687 2010-07-24 08:47:14Z schlaile $
+/*
+* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -32,6 +32,7 @@
#include "DNA_sequence_types.h"
#include "BKE_sequencer.h"
+#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_mempool.h"
#include <pthread.h>
@@ -42,8 +43,7 @@
typedef struct seqCacheKey
{
struct Sequence * seq;
- int rectx;
- int recty;
+ SeqRenderData context;
float cfra;
seq_stripelem_ibuf_t type;
} seqCacheKey;
@@ -54,29 +54,29 @@ typedef struct seqCacheEntry
MEM_CacheLimiterHandleC * c_handle;
} seqCacheEntry;
-static GHash * hash = 0;
-static MEM_CacheLimiterC * limitor = 0;
-static struct BLI_mempool * entrypool = 0;
-static struct BLI_mempool * keypool = 0;
+static GHash * hash = NULL;
+static MEM_CacheLimiterC * limitor = NULL;
+static struct BLI_mempool * entrypool = NULL;
+static struct BLI_mempool * keypool = NULL;
static int ibufs_in = 0;
static int ibufs_rem = 0;
-static unsigned int HashHash(void *key_)
+static unsigned int HashHash(const void *key_)
{
- seqCacheKey * key = (seqCacheKey*) key_;
- unsigned int rval = key->rectx + key->recty;
+ const seqCacheKey *key = (seqCacheKey*) key_;
+ unsigned int rval = seq_hash_render_data(&key->context);
rval ^= *(unsigned int*) &key->cfra;
rval += key->type;
- rval ^= ((unsigned int) key->seq) << 6;
+ rval ^= ((intptr_t) key->seq) << 6;
return rval;
}
-static int HashCmp(void *a_, void *b_)
+static int HashCmp(const void *a_, const void *b_)
{
- seqCacheKey * a = (seqCacheKey*) a_;
- seqCacheKey * b = (seqCacheKey*) b_;
+ const seqCacheKey * a = (seqCacheKey*) a_;
+ const seqCacheKey * b = (seqCacheKey*) b_;
if (a->seq < b->seq) {
return -1;
@@ -99,21 +99,7 @@ static int HashCmp(void *a_, void *b_)
return 1;
}
- if (a->rectx < b->rectx) {
- return -1;
- }
- if (a->rectx > b->rectx) {
- return 1;
- }
-
- if (a->recty < b->recty) {
- return -1;
- }
- if (a->recty > b->recty) {
- return 1;
- }
-
- return 0;
+ return seq_cmp_render_data(&a->context, &b->context);
}
static void HashKeyFree(void *key)
@@ -133,8 +119,8 @@ static void HashValFree(void *val)
ibufs_rem++;
}
- e->ibuf = 0;
- e->c_handle = 0;
+ e->ibuf = NULL;
+ e->c_handle = NULL;
BLI_mempool_free(entrypool, e);
}
@@ -149,12 +135,12 @@ static void IMB_seq_cache_destructor(void * p)
IMB_freeImBuf(e->ibuf);
ibufs_rem++;
- e->ibuf = 0;
- e->c_handle = 0;
+ e->ibuf = NULL;
+ e->c_handle = NULL;
}
}
-void seq_stripelem_cache_init()
+void seq_stripelem_cache_init(void)
{
hash = BLI_ghash_new(HashHash, HashCmp, "seq stripelem cache hash");
limitor = new_MEM_CacheLimiter( IMB_seq_cache_destructor );
@@ -163,7 +149,7 @@ void seq_stripelem_cache_init()
keypool = BLI_mempool_create(sizeof(seqCacheKey), 64, 64, 0, 0);
}
-void seq_stripelem_cache_destruct()
+void seq_stripelem_cache_destruct(void)
{
if (!entrypool) {
return;
@@ -174,7 +160,7 @@ void seq_stripelem_cache_destruct()
BLI_mempool_destroy(keypool);
}
-void seq_stripelem_cache_cleanup()
+void seq_stripelem_cache_cleanup(void)
{
if (!entrypool) {
seq_stripelem_cache_init();
@@ -192,14 +178,14 @@ void seq_stripelem_cache_cleanup()
}
struct ImBuf * seq_stripelem_cache_get(
- struct Sequence * seq, int rectx, int recty,
+ SeqRenderData context, struct Sequence * seq,
float cfra, seq_stripelem_ibuf_t type)
{
seqCacheKey key;
seqCacheEntry * e;
if (!seq) {
- return 0;
+ return NULL;
}
if (!entrypool) {
@@ -207,8 +193,7 @@ struct ImBuf * seq_stripelem_cache_get(
}
key.seq = seq;
- key.rectx = rectx;
- key.recty = recty;
+ key.context = context;
key.cfra = cfra - seq->start;
key.type = type;
@@ -220,11 +205,11 @@ struct ImBuf * seq_stripelem_cache_get(
MEM_CacheLimiter_touch(e->c_handle);
return e->ibuf;
}
- return 0;
+ return NULL;
}
void seq_stripelem_cache_put(
- struct Sequence * seq, int rectx, int recty,
+ SeqRenderData context, struct Sequence * seq,
float cfra, seq_stripelem_ibuf_t type, struct ImBuf * i)
{
seqCacheKey * key;
@@ -243,18 +228,18 @@ void seq_stripelem_cache_put(
key = (seqCacheKey*) BLI_mempool_alloc(keypool);
key->seq = seq;
- key->rectx = rectx;
- key->recty = recty;
+ key->context = context;
key->cfra = cfra - seq->start;
key->type = type;
- /* we want our own version */
- IMB_refImBuf(i);
+ /* Normally we want our own version, but start and end stills are duplicates of the original. */
+ if(ELEM(type, SEQ_STRIPELEM_IBUF_STARTSTILL, SEQ_STRIPELEM_IBUF_ENDSTILL)==0)
+ IMB_refImBuf(i);
e = (seqCacheEntry*) BLI_mempool_alloc(entrypool);
e->ibuf = i;
- e->c_handle = 0;
+ e->c_handle = NULL;
BLI_ghash_remove(hash, key, HashKeyFree, HashValFree);
BLI_ghash_insert(hash, key, e);
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 461cb075bb0..7ddd1fbd6bb 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -35,6 +35,7 @@
#include "PIL_dynlib.h"
#include "BLI_math.h" /* windows needs for M_PI */
+#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
@@ -53,7 +54,7 @@
#include "RNA_access.h"
/* **** XXX **** */
-static void error(const char *error, ...) {}
+static void error(const char *UNUSED(error), ...) {}
#define INT 96
#define FLO 128
@@ -69,23 +70,25 @@ enum {
};
static struct ImBuf * prepare_effect_imbufs(
- int x, int y,
+ SeqRenderData context,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
struct ImBuf * out;
+ int x = context.rectx;
+ int y = context.recty;
if (!ibuf1 && !ibuf2 && !ibuf3) {
/* hmmm, global float option ? */
- out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect, 0);
+ out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect);
} else if ((ibuf1 && ibuf1->rect_float) ||
(ibuf2 && ibuf2->rect_float) ||
(ibuf3 && ibuf3->rect_float)) {
/* if any inputs are rectfloat, output is float too */
- out = IMB_allocImBuf((short)x, (short)y, 32, IB_rectfloat, 0);
+ out = IMB_allocImBuf((short)x, (short)y, 32, IB_rectfloat);
} else {
- out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect, 0);
+ out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect);
}
if (ibuf1 && !ibuf1->rect_float && out->rect_float) {
@@ -117,17 +120,17 @@ static struct ImBuf * prepare_effect_imbufs(
static void open_plugin_seq(PluginSeq *pis, const char *seqname)
{
- int (*version)();
- void* (*alloc_private)();
+ int (*version)(void);
+ void* (*alloc_private)(void);
char *cp;
/* to be sure: (is tested for) */
- pis->doit= 0;
- pis->pname= 0;
- pis->varstr= 0;
- pis->cfra= 0;
+ pis->doit= NULL;
+ pis->pname= NULL;
+ pis->varstr= NULL;
+ pis->cfra= NULL;
pis->version= 0;
- pis->instance_private_data = 0;
+ pis->instance_private_data = NULL;
/* clear the error list */
PIL_dynlib_get_error_as_string(NULL);
@@ -139,12 +142,12 @@ static void open_plugin_seq(PluginSeq *pis, const char *seqname)
pis->handle= PIL_dynlib_open(pis->name);
if(test_dlerr(pis->name, pis->name)) return;
- if (pis->handle != 0) {
+ if (pis->handle != NULL) {
/* find the address of the version function */
- version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
+ version= (int (*)(void))PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
- if (version != 0) {
+ if (version != NULL) {
pis->version= version();
if (pis->version >= 2 && pis->version <= 6) {
int (*info_func)(PluginInfo *);
@@ -175,7 +178,7 @@ static void open_plugin_seq(PluginSeq *pis, const char *seqname)
return;
}
}
- alloc_private = (void* (*)())PIL_dynlib_find_symbol(
+ alloc_private = (void* (*)(void))PIL_dynlib_find_symbol(
pis->handle, "plugin_seq_alloc_private_data");
if (alloc_private) {
pis->instance_private_data = alloc_private();
@@ -198,11 +201,11 @@ static PluginSeq *add_plugin_seq(const char *str, const char *seqname)
strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE);
open_plugin_seq(pis, seqname);
- if(pis->doit==0) {
- if(pis->handle==0) error("no plugin: %s", str);
+ if(pis->doit==NULL) {
+ if(pis->handle==NULL) error("no plugin: %s", str);
else error("in plugin: %s", str);
MEM_freeN(pis);
- return 0;
+ return NULL;
}
/* default values */
@@ -219,7 +222,7 @@ static PluginSeq *add_plugin_seq(const char *str, const char *seqname)
static void free_plugin_seq(PluginSeq *pis)
{
- if(pis==0) return;
+ if(pis==NULL) return;
/* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */
@@ -244,7 +247,7 @@ static void init_plugin(Sequence * seq, const char * fname)
/*
* FIXME: should query plugin! Could be generator, that needs zero inputs...
*/
-static int num_inputs_plugin()
+static int num_inputs_plugin(void)
{
return 1;
}
@@ -267,15 +270,14 @@ static void copy_plugin(Sequence * dst, Sequence * src)
static ImBuf * IMB_cast_away_list(ImBuf * i)
{
if (!i) {
- return 0;
+ return NULL;
}
return (ImBuf*) (((void**) i) + 2);
}
static struct ImBuf * do_plugin_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *seq, float cfra,
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
@@ -285,7 +287,9 @@ static struct ImBuf * do_plugin_effect(
old plugins) do very bad stuff
with imbuf-internals */
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
+ int x = context.rectx;
+ int y = context.recty;
if(seq->plugin && seq->plugin->doit) {
@@ -370,8 +374,8 @@ static struct ImBuf * do_plugin_effect(
return out;
}
-static int do_plugin_early_out(struct Sequence *seq,
- float facf0, float facf1)
+static int do_plugin_early_out(struct Sequence *UNUSED(seq),
+ float UNUSED(facf0), float UNUSED(facf1))
{
return 0;
}
@@ -379,7 +383,7 @@ static int do_plugin_early_out(struct Sequence *seq,
static void free_plugin(struct Sequence * seq)
{
free_plugin_seq(seq->plugin);
- seq->plugin = 0;
+ seq->plugin = NULL;
}
/* **********************************************************************
@@ -524,22 +528,21 @@ static void do_alphaover_effect_float(float facf0, float facf1, int x, int y,
}
static struct ImBuf * do_alphaover_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
if (out->rect_float) {
do_alphaover_effect_float(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
ibuf1->rect_float, ibuf2->rect_float,
out->rect_float);
} else {
do_alphaover_effect_byte(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
(char*) ibuf1->rect, (char*) ibuf2->rect,
(char*) out->rect);
}
@@ -551,7 +554,7 @@ static struct ImBuf * do_alphaover_effect(
ALPHA UNDER
********************************************************************** */
-void do_alphaunder_effect_byte(
+static void do_alphaunder_effect_byte(
float facf0, float facf1, int x, int y, char *rect1,
char *rect2, char *out)
{
@@ -696,22 +699,22 @@ static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y,
}
static struct ImBuf* do_alphaunder_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(
+ context, ibuf1, ibuf2, ibuf3);
if (out->rect_float) {
do_alphaunder_effect_float(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
ibuf1->rect_float, ibuf2->rect_float,
out->rect_float);
} else {
do_alphaunder_effect_byte(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
(char*) ibuf1->rect, (char*) ibuf2->rect,
(char*) out->rect);
}
@@ -723,7 +726,7 @@ static struct ImBuf* do_alphaunder_effect(
CROSS
********************************************************************** */
-void do_cross_effect_byte(float facf0, float facf1, int x, int y,
+static void do_cross_effect_byte(float facf0, float facf1, int x, int y,
char *rect1, char *rect2,
char *out)
{
@@ -771,7 +774,7 @@ void do_cross_effect_byte(float facf0, float facf1, int x, int y,
}
}
-void do_cross_effect_float(float facf0, float facf1, int x, int y,
+static void do_cross_effect_float(float facf0, float facf1, int x, int y,
float *rect1, float *rect2, float *out)
{
float fac1, fac2, fac3, fac4;
@@ -821,22 +824,22 @@ void do_cross_effect_float(float facf0, float facf1, int x, int y,
/* carefull: also used by speed effect! */
static struct ImBuf* do_cross_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(
+ context, ibuf1, ibuf2, ibuf3);
if (out->rect_float) {
do_cross_effect_float(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
ibuf1->rect_float, ibuf2->rect_float,
out->rect_float);
} else {
do_cross_effect_byte(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
(char*) ibuf1->rect, (char*) ibuf2->rect,
(char*) out->rect);
}
@@ -967,7 +970,7 @@ static void gamtabs(float gamma)
}
-static void build_gammatabs()
+static void build_gammatabs(void)
{
if (gamma_tabs_init == FALSE) {
gamtabs(2.0f);
@@ -976,19 +979,19 @@ static void build_gammatabs()
}
}
-static void init_gammacross(Sequence * seq)
+static void init_gammacross(Sequence * UNUSED(seq))
{
}
-static void load_gammacross(Sequence * seq)
+static void load_gammacross(Sequence * UNUSED(seq))
{
}
-static void free_gammacross(Sequence * seq)
+static void free_gammacross(Sequence * UNUSED(seq))
{
}
-static void do_gammacross_effect_byte(float facf0, float facf1,
+static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1),
int x, int y,
unsigned char *rect1,
unsigned char *rect2,
@@ -1044,7 +1047,7 @@ static void do_gammacross_effect_byte(float facf0, float facf1,
}
-static void do_gammacross_effect_float(float facf0, float facf1,
+static void do_gammacross_effect_float(float facf0, float UNUSED(facf1),
int x, int y,
float *rect1, float *rect2,
float *out)
@@ -1088,24 +1091,24 @@ static void do_gammacross_effect_float(float facf0, float facf1,
}
static struct ImBuf * do_gammacross_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context,
+ Sequence *UNUSED(seq), float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
build_gammatabs();
if (out->rect_float) {
do_gammacross_effect_float(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
ibuf1->rect_float, ibuf2->rect_float,
out->rect_float);
} else {
do_gammacross_effect_byte(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
(unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
(unsigned char*) out->rect);
}
@@ -1206,22 +1209,22 @@ static void do_add_effect_float(float facf0, float facf1, int x, int y,
}
}
-static struct ImBuf * do_add_effect(Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+static struct ImBuf * do_add_effect(SeqRenderData context,
+ Sequence *UNUSED(seq), float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
if (out->rect_float) {
do_add_effect_float(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
ibuf1->rect_float, ibuf2->rect_float,
out->rect_float);
} else {
do_add_effect_byte(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
(unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
(unsigned char*) out->rect);
}
@@ -1323,22 +1326,21 @@ static void do_sub_effect_float(float facf0, float facf1, int x, int y,
}
static struct ImBuf * do_sub_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
if (out->rect_float) {
do_sub_effect_float(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
ibuf1->rect_float, ibuf2->rect_float,
out->rect_float);
} else {
do_sub_effect_byte(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
(char*) ibuf1->rect, (char*) ibuf2->rect,
(char*) out->rect);
}
@@ -1537,22 +1539,21 @@ static void do_mul_effect_float(float facf0, float facf1, int x, int y,
}
static struct ImBuf * do_mul_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
if (out->rect_float) {
do_mul_effect_float(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
ibuf1->rect_float, ibuf2->rect_float,
out->rect_float);
} else {
do_mul_effect_byte(
- facf0, facf1, x, y,
+ facf0, facf1, context.rectx, context.recty,
(unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
(unsigned char*) out->rect);
}
@@ -1591,15 +1592,10 @@ static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo
// This function calculates the blur band for the wipe effects
static float in_band(WipeZone *wipezone,float width,float dist,float perc,int side,int dir)
{
- float t1,t2,alpha,percwidth;
+ float t1,t2,alpha;
if(width == 0)
return (float)side;
-
- if(side == 1)
- percwidth = width * perc;
- else
- percwidth = width * (1 - perc);
if(width < dist)
return side;
@@ -1860,7 +1856,7 @@ static void init_wipe_effect(Sequence *seq)
seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars");
}
-static int num_inputs_wipe()
+static int num_inputs_wipe(void)
{
return 1;
}
@@ -1868,7 +1864,7 @@ static int num_inputs_wipe()
static void free_wipe_effect(Sequence *seq)
{
if(seq->effectdata)MEM_freeN(seq->effectdata);
- seq->effectdata = 0;
+ seq->effectdata = NULL;
}
static void copy_wipe_effect(Sequence *dst, Sequence *src)
@@ -1876,7 +1872,7 @@ static void copy_wipe_effect(Sequence *dst, Sequence *src)
dst->effectdata = MEM_dupallocN(src->effectdata);
}
-static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1,
+static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
int x, int y,
unsigned char *rect1,
unsigned char *rect2, unsigned char *out)
@@ -1934,7 +1930,7 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1,
}
}
-static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1,
+static void do_wipe_effect_float(Sequence *seq, float facf0, float UNUSED(facf1),
int x, int y,
float *rect1,
float *rect2, float *out)
@@ -1993,24 +1989,23 @@ static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1,
}
static struct ImBuf * do_wipe_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *seq, float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
if (out->rect_float) {
do_wipe_effect_float(seq,
- facf0, facf1, x, y,
- ibuf1->rect_float, ibuf2->rect_float,
- out->rect_float);
+ facf0, facf1, context.rectx, context.recty,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
} else {
do_wipe_effect_byte(seq,
- facf0, facf1, x, y,
- (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
- (unsigned char*) out->rect);
+ facf0, facf1, context.rectx, context.recty,
+ (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
+ (unsigned char*) out->rect);
}
return out;
@@ -2045,7 +2040,7 @@ static void init_transform_effect(Sequence *seq)
transform->uniform_scale=0;
}
-static int num_inputs_transform()
+static int num_inputs_transform(void)
{
return 1;
}
@@ -2053,7 +2048,7 @@ static int num_inputs_transform()
static void free_transform_effect(Sequence *seq)
{
if(seq->effectdata)MEM_freeN(seq->effectdata);
- seq->effectdata = 0;
+ seq->effectdata = NULL;
}
static void copy_transform_effect(Sequence *dst, Sequence *src)
@@ -2062,8 +2057,8 @@ static void copy_transform_effect(Sequence *dst, Sequence *src)
}
static void transform_image(int x, int y, struct ImBuf *ibuf1, struct ImBuf *out,
- float scale_x, float scale_y, float translate_x, float translate_y,
- float rotate, int interpolation)
+ float scale_x, float scale_y, float translate_x, float translate_y,
+ float rotate, int interpolation)
{
int xo, yo, xi, yi;
float xt, yt, xr, yr;
@@ -2111,7 +2106,7 @@ static void transform_image(int x, int y, struct ImBuf *ibuf1, struct ImBuf *out
}
}
-static void do_transform(Scene *scene, Sequence *seq, float facf0, int x, int y,
+static void do_transform(Scene *scene, Sequence *seq, float UNUSED(facf0), int x, int y,
struct ImBuf *ibuf1,struct ImBuf *out)
{
TransformVars *transform = (TransformVars *)seq->effectdata;
@@ -2144,15 +2139,15 @@ static void do_transform(Scene *scene, Sequence *seq, float facf0, int x, int y,
static struct ImBuf * do_transform_effect(
- Main *bmain, Scene *scene, Sequence *seq,float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *seq,float UNUSED(cfra),
+ float facf0, float UNUSED(facf1),
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
- do_transform(scene, seq, facf0, x, y, ibuf1, out);
+ do_transform(context.scene, seq, facf0,
+ context.rectx, context.recty, ibuf1, out);
return out;
}
@@ -2614,7 +2609,7 @@ static void init_glow_effect(Sequence *seq)
glow->bNoComp = 0;
}
-static int num_inputs_glow()
+static int num_inputs_glow(void)
{
return 1;
}
@@ -2622,7 +2617,7 @@ static int num_inputs_glow()
static void free_glow_effect(Sequence *seq)
{
if(seq->effectdata)MEM_freeN(seq->effectdata);
- seq->effectdata = 0;
+ seq->effectdata = NULL;
}
static void copy_glow_effect(Sequence *dst, Sequence *src)
@@ -2631,55 +2626,56 @@ static void copy_glow_effect(Sequence *dst, Sequence *src)
}
//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use)
-static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1,
+static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1),
int x, int y, char *rect1,
- char *rect2, char *out)
+ char *UNUSED(rect2), char *out)
{
unsigned char *outbuf=(unsigned char *)out;
unsigned char *inbuf=(unsigned char *)rect1;
GlowVars *glow = (GlowVars *)seq->effectdata;
- int size= 100; // renderdata XXX
RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost * facf0, glow->fClamp);
- RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality);
+ RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (render_size / 100.0f),glow->dQuality);
if (!glow->bNoComp)
RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y);
}
-static void do_glow_effect_float(Sequence *seq, float facf0, float facf1,
+static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1),
int x, int y,
- float *rect1, float *rect2, float *out)
+ float *rect1, float *UNUSED(rect2), float *out)
{
float *outbuf = out;
float *inbuf = rect1;
GlowVars *glow = (GlowVars *)seq->effectdata;
- int size= 100; // renderdata XXX
RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*3.0f, glow->fBoost * facf0, glow->fClamp);
- RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality);
+ RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (render_size / 100.0f),glow->dQuality);
if (!glow->bNoComp)
RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y);
}
static struct ImBuf * do_glow_effect(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *seq, float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
+
+ int render_size = 100*context.rectx/context.scene->r.xsch;
if (out->rect_float) {
- do_glow_effect_float(seq,
- facf0, facf1, x, y,
- ibuf1->rect_float, ibuf2->rect_float,
- out->rect_float);
+ do_glow_effect_float(seq, render_size,
+ facf0, facf1,
+ context.rectx, context.recty,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
} else {
- do_glow_effect_byte(seq,
- facf0, facf1, x, y,
- (char*) ibuf1->rect, (char*) ibuf2->rect,
- (char*) out->rect);
+ do_glow_effect_byte(seq, render_size,
+ facf0, facf1,
+ context.rectx, context.recty,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
}
return out;
@@ -2700,7 +2696,7 @@ static void init_solid_color(Sequence *seq)
cv->col[0] = cv->col[1] = cv->col[2] = 0.5;
}
-static int num_inputs_color()
+static int num_inputs_color(void)
{
return 0;
}
@@ -2708,7 +2704,7 @@ static int num_inputs_color()
static void free_solid_color(Sequence *seq)
{
if(seq->effectdata)MEM_freeN(seq->effectdata);
- seq->effectdata = 0;
+ seq->effectdata = NULL;
}
static void copy_solid_color(Sequence *dst, Sequence *src)
@@ -2716,25 +2712,26 @@ static void copy_solid_color(Sequence *dst, Sequence *src)
dst->effectdata = MEM_dupallocN(src->effectdata);
}
-static int early_out_color(struct Sequence *seq,
- float facf0, float facf1)
+static int early_out_color(struct Sequence *UNUSED(seq),
+ float UNUSED(facf0), float UNUSED(facf1))
{
return -1;
}
static struct ImBuf * do_solid_color(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
+ SeqRenderData context, Sequence *seq, float UNUSED(cfra),
+ float facf0, float facf1,
struct ImBuf *ibuf1, struct ImBuf *ibuf2,
struct ImBuf *ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
unsigned char *rect;
float *rect_float;
+ int x; /*= context.rectx;*/ /*UNUSED*/
+ int y; /*= context.recty;*/ /*UNUSED*/
if (out->rect) {
unsigned char col0[3];
@@ -2808,22 +2805,21 @@ static struct ImBuf * do_solid_color(
********************************************************************** */
/* no effect inputs for multicam, we use give_ibuf_seq */
-static int num_inputs_multicam()
+static int num_inputs_multicam(void)
{
return 0;
}
-static int early_out_multicam(struct Sequence *seq, float facf0, float facf1)
+static int early_out_multicam(struct Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
{
return -1;
}
static struct ImBuf * do_multicam(
- Main *bmain, Scene *scene, Sequence *seq, float cfra,
- float facf0, float facf1, int x, int y,
- int preview_render_size,
- struct ImBuf *ibuf1, struct ImBuf *ibuf2,
- struct ImBuf *ibuf3)
+ SeqRenderData context, Sequence *seq, float cfra,
+ float UNUSED(facf0), float UNUSED(facf1),
+ struct ImBuf *UNUSED(ibuf1), struct ImBuf *UNUSED(ibuf2),
+ struct ImBuf *UNUSED(ibuf3))
{
struct ImBuf * i;
struct ImBuf * out;
@@ -2831,25 +2827,24 @@ static struct ImBuf * do_multicam(
ListBase * seqbasep;
if (seq->multicam_source == 0 || seq->multicam_source >= seq->machine) {
- return 0;
+ return NULL;
}
- ed = scene->ed;
+ ed = context.scene->ed;
if (!ed) {
- return 0;
+ return NULL;
}
seqbasep = seq_seqbase(&ed->seqbase, seq);
if (!seqbasep) {
- return 0;
+ return NULL;
}
- i = give_ibuf_seqbase(bmain, scene, x, y, cfra, seq->multicam_source,
- preview_render_size, seqbasep);
+ i = give_ibuf_seqbase(context, cfra, seq->multicam_source, seqbasep);
if (!i) {
- return 0;
+ return NULL;
}
- if (input_have_to_preprocess(scene, seq, cfra, x, y)) {
+ if (input_have_to_preprocess(context, seq, cfra)) {
out = IMB_dupImBuf(i);
IMB_freeImBuf(i);
} else {
@@ -2872,8 +2867,8 @@ static void init_speed_effect(Sequence *seq)
v = (SpeedControlVars *)seq->effectdata;
v->globalSpeed = 1.0;
- v->frameMap = 0;
- v->flags = 0;
+ v->frameMap = NULL;
+ v->flags |= SEQ_SPEED_INTEGRATE; /* should be default behavior */
v->length = 0;
}
@@ -2881,11 +2876,11 @@ static void load_speed_effect(Sequence * seq)
{
SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
- v->frameMap = 0;
+ v->frameMap = NULL;
v->length = 0;
}
-static int num_inputs_speed()
+static int num_inputs_speed(void)
{
return 1;
}
@@ -2895,7 +2890,7 @@ static void free_speed_effect(Sequence *seq)
SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
if(v->frameMap) MEM_freeN(v->frameMap);
if(seq->effectdata) MEM_freeN(seq->effectdata);
- seq->effectdata = 0;
+ seq->effectdata = NULL;
}
static void copy_speed_effect(Sequence *dst, Sequence *src)
@@ -2903,18 +2898,18 @@ static void copy_speed_effect(Sequence *dst, Sequence *src)
SpeedControlVars * v;
dst->effectdata = MEM_dupallocN(src->effectdata);
v = (SpeedControlVars *)dst->effectdata;
- v->frameMap = 0;
+ v->frameMap = NULL;
v->length = 0;
}
-static int early_out_speed(struct Sequence *seq,
- float facf0, float facf1)
+static int early_out_speed(struct Sequence *UNUSED(seq),
+ float UNUSED(facf0), float UNUSED(facf1))
{
return 1;
}
static void store_icu_yrange_speed(struct Sequence * seq,
- short adrcode, float * ymin, float * ymax)
+ short UNUSED(adrcode), float * ymin, float * ymax)
{
SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
@@ -2936,11 +2931,11 @@ static void store_icu_yrange_speed(struct Sequence * seq,
}
void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
{
- float ctime, div;
int cfra;
- float fallback_fac;
+ float fallback_fac = 1.0f;
SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
FCurve *fcu= NULL;
+ int flags = v->flags;
/* if not already done, load / initialize data */
get_sequence_effect(seq);
@@ -2955,7 +2950,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
/* XXX - new in 2.5x. should we use the animation system this way?
* The fcurve is needed because many frames need evaluating at once - campbell */
- fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_fader", 0);
+ fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0);
if (!v->frameMap || v->length != seq->len) {
@@ -2968,15 +2963,23 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
}
fallback_fac = 1.0;
-
- /* if there is no fcurve, try to make retiming easy by stretching the
- strip */
- if (!fcu && seq->seq1->enddisp != seq->seq1->start && seq->seq1->len != 0) {
- fallback_fac = (float) seq->seq1->len /
- (float) (seq->seq1->enddisp - seq->seq1->start);
+
+ if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
+ if (seq->seq1->enddisp != seq->seq1->start
+ && seq->seq1->len != 0) {
+ fallback_fac = (float) seq->seq1->len /
+ (float) (seq->seq1->enddisp - seq->seq1->start);
+ flags = SEQ_SPEED_INTEGRATE;
+ fcu = NULL;
+ }
+ } else {
+ /* if there is no fcurve, use value as simple multiplier */
+ if (!fcu) {
+ fallback_fac = seq->speed_fader; /* same as speed_factor in rna*/
+ }
}
- if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
+ if (flags & SEQ_SPEED_INTEGRATE) {
float cursor = 0;
float facf;
@@ -2985,10 +2988,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
for (cfra = 1; cfra < v->length; cfra++) {
if(fcu) {
- ctime = seq->startdisp + cfra;
- div = 1.0;
-
- facf = evaluate_fcurve(fcu, ctime/div);
+ facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
} else {
facf = fallback_fac;
}
@@ -3010,19 +3010,16 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
for (cfra = 0; cfra < v->length; cfra++) {
if(fcu) {
- ctime = seq->startdisp + cfra;
- div = 1.0;
-
- facf = evaluate_fcurve(fcu, ctime / div);
- if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
- facf *= v->length;
- }
+ facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
+ } else {
+ facf = fallback_fac;
}
-
- if (!fcu) {
- facf = (float) cfra * fallback_fac;
+
+ if (flags & SEQ_SPEED_COMPRESS_IPO_Y) {
+ facf *= seq->seq1->len;
}
facf *= v->globalSpeed;
+
if (facf >= seq->seq1->len) {
facf = seq->seq1->len - 1;
} else {
@@ -3033,56 +3030,43 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
}
}
-/*
- simply reuse do_cross_effect for blending...
-
-static void do_speed_effect(Sequence * seq,int cfra,
- float facf0, float facf1, int x, int y,
- struct ImBuf *ibuf1, struct ImBuf *ibuf2,
- struct ImBuf *ibuf3, struct ImBuf *out)
-{
-
-}
-*/
-
-
/* **********************************************************************
sequence effect factory
********************************************************************** */
-static void init_noop(struct Sequence *seq)
+static void init_noop(struct Sequence *UNUSED(seq))
{
}
-static void load_noop(struct Sequence *seq)
+static void load_noop(struct Sequence *UNUSED(seq))
{
}
-static void init_plugin_noop(struct Sequence *seq, const char * fname)
+static void init_plugin_noop(struct Sequence *UNUSED(seq), const char *UNUSED(fname))
{
}
-static void free_noop(struct Sequence *seq)
+static void free_noop(struct Sequence *UNUSED(seq))
{
}
-static int num_inputs_default()
+static int num_inputs_default(void)
{
return 2;
}
-static int early_out_noop(struct Sequence *seq,
- float facf0, float facf1)
+static int early_out_noop(struct Sequence *UNUSED(seq),
+ float UNUSED(facf0), float UNUSED(facf1))
{
return 0;
}
-static int early_out_fade(struct Sequence *seq,
+static int early_out_fade(struct Sequence *UNUSED(seq),
float facf0, float facf1)
{
if (facf0 == 0.0 && facf1 == 0.0) {
@@ -3093,7 +3077,7 @@ static int early_out_fade(struct Sequence *seq,
return 0;
}
-static int early_out_mul_input2(struct Sequence *seq,
+static int early_out_mul_input2(struct Sequence *UNUSED(seq),
float facf0, float facf1)
{
if (facf0 == 0.0 && facf1 == 0.0) {
@@ -3102,13 +3086,13 @@ static int early_out_mul_input2(struct Sequence *seq,
return 0;
}
-static void store_icu_yrange_noop(struct Sequence * seq,
- short adrcode, float * ymin, float * ymax)
+static void store_icu_yrange_noop(struct Sequence * UNUSED(seq),
+ short UNUSED(adrcode), float *UNUSED(ymin), float *UNUSED(ymax))
{
/* defaults are fine */
}
-static void get_default_fac_noop(struct Sequence *seq, float cfra,
+static void get_default_fac_noop(struct Sequence *UNUSED(seq), float UNUSED(cfra),
float * facf0, float * facf1)
{
*facf0 = *facf1 = 1.0;
@@ -3123,15 +3107,17 @@ static void get_default_fac_fade(struct Sequence *seq, float cfra,
*facf1 /= seq->len;
}
-static struct ImBuf * do_overdrop_effect(Main *bmain, Scene *scene, Sequence *seq, float cfra,
+static struct ImBuf * do_overdrop_effect(SeqRenderData context,
+ Sequence *UNUSED(seq),
+ float UNUSED(cfra),
float facf0, float facf1,
- int x, int y,
- int preview_render_size,
struct ImBuf * ibuf1,
struct ImBuf * ibuf2,
struct ImBuf * ibuf3)
{
- struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3);
+ struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
+ int x = context.rectx;
+ int y = context.recty;
if (out->rect_float) {
do_drop_effect_float(
@@ -3274,9 +3260,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
struct SeqEffectHandle get_sequence_effect(Sequence * seq)
{
- struct SeqEffectHandle rval;
-
- memset(&rval, 0, sizeof(struct SeqEffectHandle));
+ struct SeqEffectHandle rval= {NULL};
if (seq->type & SEQ_EFFECT) {
rval = get_sequence_effect_impl(seq->type);
@@ -3291,9 +3275,7 @@ struct SeqEffectHandle get_sequence_effect(Sequence * seq)
struct SeqEffectHandle get_sequence_blend(Sequence * seq)
{
- struct SeqEffectHandle rval;
-
- memset(&rval, 0, sizeof(struct SeqEffectHandle));
+ struct SeqEffectHandle rval= {NULL};
if (seq->blend_mode != 0) {
rval = get_sequence_effect_impl(seq->blend_mode);
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index b6bb5c3a51b..83e28db771a 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -41,6 +41,14 @@
#include "DNA_object_types.h"
#include "DNA_sound_types.h"
+#include "BLI_math.h"
+#include "BLI_fileops.h"
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
#include "BKE_animsys.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -49,21 +57,15 @@
#include "BKE_fcurve.h"
#include "BKE_scene.h"
#include "RNA_access.h"
+#include "BKE_utildefines.h"
+
#include "RE_pipeline.h"
-#include "BLI_math.h"
-#include "BLI_fileops.h"
-#include "BLI_listbase.h"
-#include "BLI_path_util.h"
-#include "BLI_string.h"
-#include "BLI_threads.h"
#include <pthread.h>
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-
-
#include "BKE_context.h"
#include "BKE_sound.h"
#include "AUD_C-API.h"
@@ -133,7 +135,7 @@ static void free_proxy_seq(Sequence *seq)
{
if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) {
IMB_free_anim(seq->strip->proxy->anim);
- seq->strip->proxy->anim = 0;
+ seq->strip->proxy->anim = NULL;
}
}
@@ -191,7 +193,7 @@ void seq_free_sequence(Scene *scene, Sequence *seq)
if (ed->act_seq==seq)
ed->act_seq= NULL;
- if(seq->scene_sound)
+ if(seq->scene_sound && ELEM(seq->type, SEQ_SOUND, SEQ_SCENE))
sound_remove_scene_sound(scene, seq->scene_sound);
seq_free_animdata(scene, seq);
@@ -244,7 +246,95 @@ void seq_free_editing(Scene *scene)
MEM_freeN(ed);
}
-/* ************************* itterator ************************** */
+/* **********************************************************************
+ * sequencer pipeline functions
+ ********************************************************************** */
+
+SeqRenderData seq_new_render_data(
+ struct Main * bmain, struct Scene * scene,
+ int rectx, int recty, int preview_render_size)
+{
+ SeqRenderData rval;
+
+ rval.bmain = bmain;
+ rval.scene = scene;
+ rval.rectx = rectx;
+ rval.recty = recty;
+ rval.preview_render_size = preview_render_size;
+ rval.motion_blur_samples = 0;
+ rval.motion_blur_shutter = 0;
+
+ return rval;
+}
+
+int seq_cmp_render_data(const SeqRenderData * a, const SeqRenderData * b)
+{
+ if (a->preview_render_size < b->preview_render_size) {
+ return -1;
+ }
+ if (a->preview_render_size > b->preview_render_size) {
+ return 1;
+ }
+
+ if (a->rectx < b->rectx) {
+ return -1;
+ }
+ if (a->rectx > b->rectx) {
+ return 1;
+ }
+
+ if (a->recty < b->recty) {
+ return -1;
+ }
+ if (a->recty > b->recty) {
+ return 1;
+ }
+
+ if (a->bmain < b->bmain) {
+ return -1;
+ }
+ if (a->bmain > b->bmain) {
+ return 1;
+ }
+
+ if (a->scene < b->scene) {
+ return -1;
+ }
+ if (a->scene > b->scene) {
+ return 1;
+ }
+
+ if (a->motion_blur_shutter < b->motion_blur_shutter) {
+ return -1;
+ }
+ if (a->motion_blur_shutter > b->motion_blur_shutter) {
+ return 1;
+ }
+
+ if (a->motion_blur_samples < b->motion_blur_samples) {
+ return -1;
+ }
+ if (a->motion_blur_samples > b->motion_blur_samples) {
+ return 1;
+ }
+
+ return 0;
+}
+
+unsigned int seq_hash_render_data(const SeqRenderData * a)
+{
+ unsigned int rval = a->rectx + a->recty;
+
+ rval ^= a->preview_render_size;
+ rval ^= ((intptr_t) a->bmain) << 6;
+ rval ^= ((intptr_t) a->scene) << 6;
+ rval ^= (int) (a->motion_blur_shutter * 100.0) << 10;
+ rval ^= a->motion_blur_samples << 24;
+
+ return rval;
+}
+
+/* ************************* iterator ************************** */
/* *************** (replaces old WHILE_SEQ) ********************* */
/* **************** use now SEQ_BEGIN() SEQ_END ***************** */
@@ -339,7 +429,7 @@ void seq_end(SeqIterator *iter)
* in metastrips!)
**********************************************************************
*/
-
+#if 0 /* UNUSED */
static void do_seq_count(ListBase *seqbase, int *totseq)
{
Sequence *seq;
@@ -366,7 +456,7 @@ static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
}
}
-void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq)
+static void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq)
{
Sequence **tseqar;
@@ -374,7 +464,7 @@ void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq)
do_seq_count(seqbase, totseq);
if(*totseq==0) {
- *seqar= 0;
+ *seqar= NULL;
return;
}
*seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
@@ -383,6 +473,7 @@ void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq)
do_build_seqar(seqbase, seqar, 0);
*seqar= tseqar;
}
+#endif /* UNUSED */
static void do_seq_count_cb(ListBase *seqbase, int *totseq,
int (*test_func)(Sequence * seq))
@@ -413,8 +504,7 @@ static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth,
seq->depth= depth;
if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
- do_build_seqar_cb(&seq->seqbase, seqar, depth+1,
- test_func);
+ do_build_seqar_cb(&seq->seqbase, seqar, depth+1, test_func);
}
if (test & BUILD_SEQAR_COUNT_CURRENT) {
**seqar= seq;
@@ -433,7 +523,7 @@ void build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int *totseq,
do_seq_count_cb(seqbase, totseq, test_func);
if(*totseq==0) {
- *seqar= 0;
+ *seqar= NULL;
return;
}
*seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
@@ -473,7 +563,7 @@ static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
if(seq->type == SEQ_META) {
seq_update_sound_bounds_recursive(scene, seq);
}
- else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) {
+ else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
if(seq->scene_sound) {
int startofs = seq->startofs;
int endofs = seq->endofs;
@@ -504,8 +594,8 @@ void calc_sequence(Scene *scene, Sequence *seq)
if(seq->type & SEQ_EFFECT) {
/* pointers */
- if(seq->seq2==0) seq->seq2= seq->seq1;
- if(seq->seq3==0) seq->seq3= seq->seq1;
+ if(seq->seq2==NULL) seq->seq2= seq->seq1;
+ if(seq->seq3==NULL) seq->seq3= seq->seq1;
/* effecten go from seq1 -> seq2: test */
@@ -554,15 +644,13 @@ void calc_sequence(Scene *scene, Sequence *seq)
}
/* note: caller should run calc_sequence(scene, seq) after */
-void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int lock_range)
+void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range)
{
char str[FILE_MAXDIR+FILE_MAXFILE];
- int prev_startdisp, prev_enddisp;
+ int prev_startdisp=0, prev_enddisp=0;
/* note: dont rename the strip, will break animation curves */
- if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE ||
- seq->type == SEQ_SOUND ||
- seq->type == SEQ_SCENE || seq->type == SEQ_META)) {
+ if (ELEM5(seq->type, SEQ_MOVIE, SEQ_IMAGE, SEQ_SOUND, SEQ_SCENE, SEQ_META)==0) {
return;
}
@@ -576,13 +664,14 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
new_tstripdata(seq);
- if (seq->type != SEQ_SCENE && seq->type != SEQ_META &&
- seq->type != SEQ_IMAGE) {
- BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name);
- BLI_path_abs(str, G.sce);
+ if (ELEM3(seq->type, SEQ_SCENE, SEQ_META, SEQ_IMAGE)==0) {
+ BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name);
+ BLI_path_abs(str, G.main->name);
}
- if (seq->type == SEQ_IMAGE) {
+ switch(seq->type) {
+ case SEQ_IMAGE:
+ {
/* Hack? */
size_t olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem);
@@ -593,7 +682,9 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
seq->len = 0;
}
seq->strip->len = seq->len;
- } else if (seq->type == SEQ_MOVIE) {
+ break;
+ }
+ case SEQ_MOVIE:
if(seq->anim) IMB_free_anim(seq->anim);
seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0));
@@ -611,7 +702,9 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
seq->len = 0;
}
seq->strip->len = seq->len;
- } else if (seq->type == SEQ_SOUND) {
+ case SEQ_SOUND:
+ if(!seq->sound)
+ return;
seq->len = ceil(AUD_getInfo(seq->sound->playback_handle).length * FPS);
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
@@ -619,9 +712,11 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
seq->len = 0;
}
seq->strip->len = seq->len;
- } else if (seq->type == SEQ_SCENE) {
+ break;
+ case SEQ_SCENE:
+ {
/* 'seq->scenenr' should be replaced with something more reliable */
- Scene * sce = bmain->scene.first;
+ Scene * sce = G.main->scene.first;
int nr = 1;
while(sce) {
@@ -634,10 +729,8 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
if (sce) {
seq->scene = sce;
- } else {
- sce = seq->scene;
}
-
+
seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1;
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
@@ -645,6 +738,8 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
seq->len = 0;
}
seq->strip->len = seq->len;
+ break;
+ }
}
free_proxy_seq(seq);
@@ -668,8 +763,8 @@ void sort_seq(Scene *scene)
if(ed==NULL) return;
- seqbase.first= seqbase.last= 0;
- effbase.first= effbase.last= 0;
+ seqbase.first= seqbase.last= NULL;
+ effbase.first= effbase.last= NULL;
while( (seq= ed->seqbasep->first) ) {
BLI_remlink(ed->seqbasep, seq);
@@ -683,7 +778,7 @@ void sort_seq(Scene *scene)
}
seqt= seqt->next;
}
- if(seqt==0) BLI_addtail(&effbase, seq);
+ if(seqt==NULL) BLI_addtail(&effbase, seq);
}
else {
seqt= seqbase.first;
@@ -694,11 +789,11 @@ void sort_seq(Scene *scene)
}
seqt= seqt->next;
}
- if(seqt==0) BLI_addtail(&seqbase, seq);
+ if(seqt==NULL) BLI_addtail(&seqbase, seq);
}
}
- addlisttolist(&seqbase, &effbase);
+ BLI_movelisttolist(&seqbase, &effbase);
*(ed->seqbasep)= seqbase;
}
@@ -783,7 +878,7 @@ void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq)
strcpy(seq->name+2, sui.name_dest);
}
-static char *give_seqname_by_type(int type)
+static const char *give_seqname_by_type(int type)
{
switch(type) {
case SEQ_META: return "Meta";
@@ -806,13 +901,13 @@ static char *give_seqname_by_type(int type)
case SEQ_MULTICAM: return "Multicam";
case SEQ_SPEED: return "Speed";
default:
- return 0;
+ return NULL;
}
}
-char *give_seqname(Sequence *seq)
+const char *give_seqname(Sequence *seq)
{
- char * name = give_seqname_by_type(seq->type);
+ const char *name = give_seqname_by_type(seq->type);
if (!name) {
if(seq->type<SEQ_EFFECT) {
@@ -839,7 +934,7 @@ static void make_black_ibuf(ImBuf *ibuf)
float *rect_float;
int tot;
- if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return;
+ if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) return;
tot= ibuf->x*ibuf->y;
@@ -898,19 +993,24 @@ static void multibuf(ImBuf *ibuf, float fmul)
static float give_stripelem_index(Sequence *seq, float cfra)
{
float nr;
+ int sta = seq->start;
+ int end = seq->start+seq->len-1;
if(seq->len == 0) return -1;
+
if(seq->flag&SEQ_REVERSE_FRAMES) {
/*reverse frame in this sequence */
- if(cfra <= seq->start) nr= seq->len-1;
- else if(cfra >= seq->start+seq->len-1) nr= 0;
- else nr= (seq->start + seq->len - 1) - cfra;
+ if(cfra <= sta) nr= seq->len-1;
+ else if(cfra >= end) nr= 0;
+ else nr= end - cfra;
} else {
- if(cfra <= seq->start) nr= 0;
- else if(cfra >= seq->start+seq->len-1) nr= seq->len-1;
- else nr= cfra-seq->start;
+ if(cfra <= sta) nr= 0;
+ else if(cfra >= end) nr= seq->len-1;
+ else nr= cfra - sta;
}
+
if (seq->strobe < 1.0) seq->strobe = 1.0;
+
if (seq->strobe > 1.0) {
nr -= fmod((double)nr, (double)seq->strobe);
}
@@ -922,14 +1022,10 @@ StripElem *give_stripelem(Sequence *seq, int cfra)
{
StripElem *se= seq->strip->stripdata;
- if(seq->type == SEQ_MOVIE) {
- /* use the first */
- }
- else {
+ if(seq->type != SEQ_MOVIE) { /* movie use the first */
int nr = (int) give_stripelem_index(seq, cfra);
- if (nr == -1) return 0;
- if (se == 0) return 0;
+ if (nr == -1 || se == NULL) return NULL;
se += nr + seq->anim_startofs;
}
@@ -966,9 +1062,7 @@ int evaluate_seq_frame(Scene *scene, int cfra)
static int video_seq_is_rendered(Sequence * seq)
{
- return (seq
- && !(seq->flag & SEQ_MUTE)
- && seq->type != SEQ_SOUND);
+ return (seq && !(seq->flag & SEQ_MUTE) && seq->type != SEQ_SOUND);
}
static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out)
@@ -983,7 +1077,7 @@ static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Se
if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) {
if (b > 0) {
- if (seq_arr[b] == 0) {
+ if (seq_arr[b] == NULL) {
return 0;
}
} else {
@@ -1005,7 +1099,7 @@ static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Se
}
}
- for (;b <= chanshown; b++) {
+ for (;b <= chanshown && b >= 0; b++) {
if (video_seq_is_rendered(seq_arr[b])) {
seq_arr_out[cnt++] = seq_arr[b];
}
@@ -1021,7 +1115,7 @@ static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Se
#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
-static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name, int render_size)
+static int seq_proxy_get_fname(SeqRenderData context, Sequence * seq, int cfra, char * name)
{
int frameno;
char dir[FILE_MAXDIR];
@@ -1030,103 +1124,96 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na
return FALSE;
}
- if ((seq->flag & SEQ_USE_PROXY_CUSTOM_DIR)
- || (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE)) {
+ if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR|SEQ_USE_PROXY_CUSTOM_FILE)) {
strcpy(dir, seq->strip->proxy->dir);
} else {
- if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
- snprintf(dir, FILE_MAXDIR, "%s/BL_proxy",
- seq->strip->dir);
+ if (ELEM(seq->type, SEQ_IMAGE, SEQ_MOVIE)) {
+ snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", seq->strip->dir);
} else {
return FALSE;
}
}
if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
- BLI_join_dirfile(name, dir, seq->strip->proxy->file);
- BLI_path_abs(name, G.sce);
+ BLI_join_dirfile(name, FILE_MAX, dir, seq->strip->proxy->file); /* XXX, not real length */
+ BLI_path_abs(name, G.main->name);
return TRUE;
}
/* generate a separate proxy directory for each preview size */
- if (seq->type == SEQ_IMAGE) {
- StripElem * se = give_stripelem(seq, cfra);
- snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy",
- dir, render_size, se->name);
+ switch(seq->type) {
+ case SEQ_IMAGE:
+ snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir,
+ context.preview_render_size,
+ give_stripelem(seq, cfra)->name);
frameno = 1;
- } else if (seq->type == SEQ_MOVIE) {
- frameno = (int) give_stripelem_index(seq, cfra)
- + seq->anim_startofs;
-
+ break;
+ case SEQ_MOVIE:
+ frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs;
snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
- seq->strip->stripdata->name,
- render_size);
- } else {
- frameno = (int) give_stripelem_index(seq, cfra)
- + seq->anim_startofs;
-
- snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
- render_size);
+ seq->strip->stripdata->name, context.preview_render_size);
+ break;
+ default:
+ frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs;
+ snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
+ context.preview_render_size);
}
- BLI_path_abs(name, G.sce);
+ BLI_path_abs(name, G.main->name);
BLI_path_frame(name, frameno, 0);
-
strcat(name, ".jpg");
return TRUE;
}
-static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, int render_size)
+static struct ImBuf * seq_proxy_fetch(SeqRenderData context, Sequence * seq, int cfra)
{
char name[PROXY_MAXFILE];
if (!(seq->flag & SEQ_USE_PROXY)) {
- return 0;
+ return NULL;
}
/* rendering at 100% ? No real sense in proxy-ing, right? */
- if (render_size == 100) {
- return 0;
+ if (context.preview_render_size == 100) {
+ return NULL;
}
if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
- int frameno = (int) give_stripelem_index(seq, cfra)
- + seq->anim_startofs;
- if (!seq->strip->proxy->anim) {
- if (!seq_proxy_get_fname(
- scene, seq, cfra, name, render_size)) {
- return 0;
+ int frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs;
+ if (seq->strip->proxy->anim == NULL) {
+ if (seq_proxy_get_fname(context, seq, cfra, name)==0) {
+ return NULL;
}
seq->strip->proxy->anim = openanim(name, IB_rect);
}
- if (!seq->strip->proxy->anim) {
- return 0;
+ if (seq->strip->proxy->anim==NULL) {
+ return NULL;
}
return IMB_anim_absolute(seq->strip->proxy->anim, frameno);
}
- if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
- return 0;
+ if (seq_proxy_get_fname(context, seq, cfra, name) == 0) {
+ return NULL;
}
if (BLI_exists(name)) {
return IMB_loadiffname(name, IB_rect);
} else {
- return 0;
+ return NULL;
}
}
#if 0
static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
- int build_proxy_run, int render_size);
+ int build_proxy_run, int preview_render_size);
-static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size, int seqrectx, int seqrecty)
+static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int preview_render_size, int seqrectx, int seqrecty)
{
char name[PROXY_MAXFILE];
int quality;
@@ -1140,7 +1227,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re
}
/* rendering at 100% ? No real sense in proxy-ing, right? */
- if (render_size == 100) {
+ if (preview_render_size == 100) {
return;
}
@@ -1149,7 +1236,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re
return;
}
- if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
+ if (!seq_proxy_get_fname(scene, seq, cfra, name, preview_render_size)) {
return;
}
@@ -1163,15 +1250,15 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re
se->ibuf = 0;
}
- do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size,
+ do_build_seq_ibuf(scene, seq, se, cfra, TRUE, preview_render_size,
seqrectx, seqrecty);
if (!se->ibuf) {
return;
}
- rectx= (render_size*scene->r.xsch)/100;
- recty= (render_size*scene->r.ysch)/100;
+ rectx= (preview_render_size*scene->r.xsch)/100;
+ recty= (preview_render_size*scene->r.ysch)/100;
ibuf = se->ibuf;
@@ -1380,8 +1467,7 @@ static void color_balance_byte_float(Sequence * seq, ImBuf* ibuf, float mul)
cb = calc_cb(seq->strip->color_balance);
for (c = 0; c < 3; c++) {
- make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c],
- cb_tab[c], mul);
+ make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
}
for (i = 0; i < 256; i++) {
@@ -1444,17 +1530,12 @@ static void color_balance(Sequence * seq, ImBuf* ibuf, float mul)
*/
int input_have_to_preprocess(
- Scene *scene, Sequence * seq, float cfra, int seqrectx, int seqrecty)
+ SeqRenderData UNUSED(context), Sequence * seq, float UNUSED(cfra))
{
float mul;
- if ((seq->flag & SEQ_FILTERY) ||
- (seq->flag & SEQ_USE_CROP) ||
- (seq->flag & SEQ_USE_TRANSFORM) ||
- (seq->flag & SEQ_FLIPX) ||
- (seq->flag & SEQ_FLIPY) ||
- (seq->flag & SEQ_USE_COLOR_BALANCE) ||
- (seq->flag & SEQ_MAKE_PREMUL)) {
+ if (seq->flag & (SEQ_FILTERY|SEQ_USE_CROP|SEQ_USE_TRANSFORM|SEQ_FLIPX|
+ SEQ_FLIPY|SEQ_USE_COLOR_BALANCE|SEQ_MAKE_PREMUL)) {
return TRUE;
}
@@ -1476,26 +1557,19 @@ int input_have_to_preprocess(
}
static ImBuf * input_preprocess(
- Scene *scene, Sequence *seq, float cfra, int seqrectx, int seqrecty,
- ImBuf * ibuf)
+ SeqRenderData context, Sequence *seq, float UNUSED(cfra), ImBuf * ibuf)
{
float mul;
- seq->strip->orx= ibuf->x;
- seq->strip->ory= ibuf->y;
-
if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
IMB_filtery(ibuf);
}
- if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) {
- StripCrop c;
- StripTransform t;
+ if(seq->flag & (SEQ_USE_CROP|SEQ_USE_TRANSFORM)) {
+ StripCrop c= {0};
+ StripTransform t= {0};
int sx,sy,dx,dy;
- memset(&c, 0, sizeof(StripCrop));
- memset(&t, 0, sizeof(StripTransform));
-
if(seq->flag & SEQ_USE_CROP && seq->strip->crop) {
c = *seq->strip->crop;
}
@@ -1509,27 +1583,17 @@ static ImBuf * input_preprocess(
dy = sy;
if (seq->flag & SEQ_USE_TRANSFORM) {
- dx = scene->r.xsch;
- dy = scene->r.ysch;
+ dx = context.scene->r.xsch;
+ dy = context.scene->r.ysch;
}
- if (c.top + c.bottom >= ibuf->y ||
- c.left + c.right >= ibuf->x ||
- t.xofs >= dx || t.yofs >= dy) {
+ if (c.top + c.bottom >= ibuf->y || c.left + c.right >= ibuf->x ||
+ t.xofs >= dx || t.yofs >= dy) {
make_black_ibuf(ibuf);
} else {
- ImBuf * i;
+ ImBuf * i = IMB_allocImBuf(dx, dy,32, ibuf->rect_float ? IB_rectfloat : IB_rect);
- if (ibuf->rect_float) {
- i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0);
- } else {
- i = IMB_allocImBuf(dx, dy,32, IB_rect, 0);
- }
-
- IMB_rectcpy(i, ibuf,
- t.xofs, t.yofs,
- c.left, c.bottom,
- sx, sy);
+ IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy);
IMB_freeImBuf(ibuf);
@@ -1548,7 +1612,7 @@ static ImBuf * input_preprocess(
if(seq->sat != 1.0f) {
/* inline for now, could become an imbuf function */
int i;
- char *rct= (char *)ibuf->rect;
+ unsigned char *rct= (unsigned char *)ibuf->rect;
float *rctf= ibuf->rect_float;
const float sat= seq->sat;
float hsv[3];
@@ -1596,38 +1660,35 @@ static ImBuf * input_preprocess(
}
if(seq->flag & SEQ_MAKE_PREMUL) {
- if(ibuf->depth == 32 && ibuf->zbuf == 0) {
+ if(ibuf->depth == 32 && ibuf->zbuf == NULL) {
IMB_premultiply_alpha(ibuf);
}
}
- if(ibuf->x != seqrectx || ibuf->y != seqrecty ) {
- if(scene->r.mode & R_OSA) {
- IMB_scaleImBuf(ibuf,
- (short)seqrectx, (short)seqrecty);
+ if(ibuf->x != context.rectx || ibuf->y != context.recty ) {
+ if(context.scene->r.mode & R_OSA) {
+ IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty);
} else {
- IMB_scalefastImBuf(ibuf,
- (short)seqrectx, (short)seqrecty);
+ IMB_scalefastImBuf(ibuf, (short)context.rectx, (short)context.recty);
}
}
return ibuf;
}
-static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr,
- int seqrectx, int seqrecty)
+static ImBuf * copy_from_ibuf_still(SeqRenderData context, Sequence * seq,
+ float nr)
{
- ImBuf * rval = 0;
- ImBuf * ibuf = 0;
+ ImBuf * rval = NULL;
+ ImBuf * ibuf = NULL;
if (nr == 0) {
ibuf = seq_stripelem_cache_get(
- seq, seqrectx, seqrecty, seq->start,
+ context, seq, seq->start,
SEQ_STRIPELEM_IBUF_STARTSTILL);
- }
- if (nr == seq->len - 1) {
+ } else if (nr == seq->len - 1) {
ibuf = seq_stripelem_cache_get(
- seq, seqrectx, seqrecty, seq->start,
+ context, seq, seq->start,
SEQ_STRIPELEM_IBUF_ENDSTILL);
}
@@ -1639,18 +1700,19 @@ static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr,
return rval;
}
-static void copy_to_ibuf_still(Sequence * seq, float nr,
+static void copy_to_ibuf_still(SeqRenderData context, Sequence * seq, float nr,
ImBuf * ibuf)
{
if (nr == 0) {
seq_stripelem_cache_put(
- seq, 0, 0, seq->start,
- SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf);
- }
+ context, seq, seq->start,
+ SEQ_STRIPELEM_IBUF_STARTSTILL, IMB_dupImBuf(ibuf));
+ }
+
if (nr == seq->len - 1) {
seq_stripelem_cache_put(
- seq, 0, 0, seq->start,
- SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf);
+ context, seq, seq->start,
+ SEQ_STRIPELEM_IBUF_ENDSTILL, IMB_dupImBuf(ibuf));
}
}
@@ -1658,45 +1720,46 @@ static void copy_to_ibuf_still(Sequence * seq, float nr,
strip rendering functions
********************************************************************** */
-static ImBuf* seq_render_strip_stack(
- Main *bmain, Scene *scene,
- ListBase *seqbasep, float cfra, int chanshown, int render_size,
- int seqrectx, int seqrecty);
+static ImBuf* seq_render_strip_stack(
+ SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
-static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra,
- int render_size,
- int seqrectx, int seqrecty);
+static ImBuf * seq_render_strip(
+ SeqRenderData context, Sequence * seq, float cfra);
static ImBuf* seq_render_effect_strip_impl(
- Main *bmain, Scene *scene, float cfra, Sequence *seq, int render_size,
- int seqrectx, int seqrecty)
+ SeqRenderData context, Sequence *seq, float cfra)
{
float fac, facf;
int early_out;
int i;
- int must_preprocess = FALSE;
-
struct SeqEffectHandle sh = get_sequence_effect(seq);
FCurve *fcu= NULL;
ImBuf * ibuf[3];
- ImBuf * out = 0;
+ Sequence *input[3];
+ ImBuf * out = NULL;
+
+ ibuf[0] = ibuf[1] = ibuf[2] = NULL;
- ibuf[0] = ibuf[1] = ibuf[2] = 0;
+ input[0] = seq->seq1; input[1] = seq->seq2; input[2] = seq->seq3;
if (!sh.execute) { /* effect not supported in this version... */
- goto finish;
+ out = IMB_allocImBuf((short)context.rectx,
+ (short)context.recty, 32, IB_rect);
+ return out;
}
- if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) {
+ if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
sh.get_default_fac(seq, cfra, &fac, &facf);
- if( scene->r.mode & R_FIELDS ); else facf= fac;
- } else {
- fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence,
- "effect_fader", 0);
+
+ if ((context.scene->r.mode & R_FIELDS)==0)
+ facf= fac;
+ }
+ else {
+ fcu = id_data_find_fcurve(&context.scene->id, seq, &RNA_Sequence, "effect_fader", 0);
if (fcu) {
fac = facf = evaluate_fcurve(fcu, cfra);
- if( scene->r.mode & R_FIELDS ) {
+ if( context.scene->r.mode & R_FIELDS ) {
facf = evaluate_fcurve(fcu, cfra + 0.5);
}
} else {
@@ -1706,88 +1769,57 @@ static ImBuf* seq_render_effect_strip_impl(
early_out = sh.early_out(seq, fac, facf);
- if (early_out == -1) { /* no input needed */
- out = sh.execute(bmain, scene, seq, cfra, fac, facf,
- seqrectx, seqrecty, render_size,
- 0, 0, 0);
- goto finish;
- }
-
-
- must_preprocess = input_have_to_preprocess(
- scene, seq, cfra, seqrectx, seqrecty);
-
switch (early_out) {
- case 0:
+ case EARLY_NO_INPUT:
+ out = sh.execute(context, seq, cfra, fac, facf,
+ NULL, NULL, NULL);
break;
- case 1:
- if (seq->seq1) {
- ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra,
- render_size,
- seqrectx, seqrecty);
+ case EARLY_DO_EFFECT:
+ for(i=0; i<3; i++) {
+ if(input[i])
+ ibuf[i] = seq_render_strip(
+ context, input[i], cfra);
+ }
+
+ if (ibuf[0] && ibuf[1]) {
+ out = sh.execute(context, seq, cfra, fac, facf,
+ ibuf[0], ibuf[1], ibuf[2]);
+ }
+ break;
+ case EARLY_USE_INPUT_1:
+ if (input[0]) {
+ ibuf[0] = seq_render_strip(context, input[0], cfra);
}
if (ibuf[0]) {
- if (must_preprocess) {
+ if (input_have_to_preprocess(context, seq, cfra)) {
out = IMB_dupImBuf(ibuf[0]);
} else {
out = ibuf[0];
IMB_refImBuf(out);
}
}
- goto finish;
- case 2:
- if (seq->seq2) {
- ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra,
- render_size,
- seqrectx, seqrecty);
+ break;
+ case EARLY_USE_INPUT_2:
+ if (input[1]) {
+ ibuf[1] = seq_render_strip(context, input[1], cfra);
}
if (ibuf[1]) {
- if (must_preprocess) {
+ if (input_have_to_preprocess(context, seq, cfra)) {
out = IMB_dupImBuf(ibuf[1]);
} else {
out = ibuf[1];
IMB_refImBuf(out);
}
}
- goto finish;
- default:
- goto finish;
- }
-
- if (seq->seq1) {
- ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra,
- render_size,
- seqrectx, seqrecty);
- }
-
- if (seq->seq2) {
- ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra,
- render_size,
- seqrectx, seqrecty);
- }
-
- if (seq->seq3) {
- ibuf[2] = seq_render_strip(bmain, scene, seq->seq3, cfra,
- render_size,
- seqrectx, seqrecty);
- }
-
- if (!ibuf[0] || !ibuf[1]) {
- goto finish;
+ break;
}
- out = sh.execute(bmain, scene, seq, cfra, fac, facf, seqrectx, seqrecty,
- render_size,
- ibuf[0], ibuf[1], ibuf[2]);
-
-finish:
for (i = 0; i < 3; i++) {
IMB_freeImBuf(ibuf[i]);
}
- if (!out) {
- out = IMB_allocImBuf(
- (short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+ if (out == NULL) {
+ out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
}
return out;
@@ -1795,15 +1827,16 @@ finish:
static ImBuf * seq_render_scene_strip_impl(
- Main *bmain, Scene * scene, Sequence * seq, float nr, int seqrectx, int seqrecty)
+ SeqRenderData context, Sequence * seq, float nr)
{
- ImBuf * ibuf = 0;
+ ImBuf * ibuf = NULL;
float frame= seq->sfra + nr + seq->anim_startofs;
float oldcfra;
Object *oldcamera;
ListBase oldmarkers;
- /* Hack! This function can be called from do_render_seq(), in that case
+ /* Old info:
+ Hack! This function can be called from do_render_seq(), in that case
the seq->scene can already have a Render initialized with same name,
so we have to use a default name. (compositor uses scene name to
find render).
@@ -1815,9 +1848,27 @@ static ImBuf * seq_render_scene_strip_impl(
and since G.rendering is uhm, gone... (Peter)
*/
+ /* New info:
+ Using the same name for the renders works just fine as the do_render_seq()
+ render is not used while the scene strips are rendered.
+
+ However rendering from UI (through sequencer_preview_area_draw) can crash in
+ very many cases since other renders (material preview, an actual render etc.)
+ can be started while this sequence preview render is running. The only proper
+ solution is to make the sequencer preview render a proper job, which can be
+ stopped when needed. This would also give a nice progress bar for the preview
+ space so that users know there's something happening.
+
+ As a result the active scene now only uses OpenGL rendering for the sequencer
+ preview. This is far from nice, but is the only way to prevent crashes at this
+ time.
+
+ -jahka
+ */
+
int rendering = G.rendering;
int doseq;
- int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : (scene->r.seq_flag & R_SEQ_GL_PREV);
+ int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : /*(scene->r.seq_flag & R_SEQ_GL_PREV)*/ 1;
int have_seq= FALSE;
Scene *sce= seq->scene; /* dont refer to seq->scene above this point!, it can be NULL */
int sce_valid= FALSE;
@@ -1834,8 +1885,8 @@ static ImBuf * seq_render_scene_strip_impl(
oldcamera= seq->scene->camera;
/* prevent eternal loop */
- doseq= scene->r.scemode & R_DOSEQ;
- scene->r.scemode &= ~R_DOSEQ;
+ doseq= context.scene->r.scemode & R_DOSEQ;
+ context.scene->r.scemode &= ~R_DOSEQ;
seq->scene->r.cfra= frame;
if(seq->scene_camera)
@@ -1849,27 +1900,34 @@ static ImBuf * seq_render_scene_strip_impl(
seq->scene->markers.first= seq->scene->markers.last= NULL;
#endif
- if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (seq->scene == scene || have_seq==0) && seq->scene->camera) {
+ if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (seq->scene == context.scene || have_seq==0) && seq->scene->camera) {
+ /* for old scened this can be uninitialized, should probably be added to do_versions at some point if the functionality stays */
+ if(context.scene->r.seq_prev_type==0)
+ context.scene->r.seq_prev_type = 3 /* ==OB_SOLID */;
+
/* opengl offscreen render */
- scene_update_for_newframe(bmain, seq->scene, seq->scene->lay);
- ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty, IB_rect,
- scene->r.seq_prev_type);
+ scene_update_for_newframe(context.bmain, seq->scene, seq->scene->lay);
+ ibuf= sequencer_view3d_cb(seq->scene, context.rectx, context.recty, IB_rect, context.scene->r.seq_prev_type);
}
else {
- Render *re;
+ Render *re = RE_GetRender(sce->id.name);
RenderResult rres;
-
- if(rendering)
- re= RE_NewRender(" do_build_seq_ibuf");
- else
- re= RE_NewRender(sce->id.name);
-
- RE_BlenderFrame(re, bmain, sce, NULL, sce->lay, frame);
+
+ /* XXX: this if can be removed when sequence preview rendering uses the job system */
+ if(rendering || context.scene != sce) {
+ if(re==NULL)
+ re= RE_NewRender(sce->id.name);
+
+ RE_BlenderFrame(re, context.bmain, sce, NULL, sce->lay, frame, FALSE);
+
+ /* restore previous state after it was toggled on & off by RE_BlenderFrame */
+ G.rendering = rendering;
+ }
RE_AcquireResultImage(re, &rres);
if(rres.rectf) {
- ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
+ ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat);
memcpy(ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
if(rres.rectz) {
addzbuffloatImBuf(ibuf);
@@ -1881,7 +1939,7 @@ static ImBuf * seq_render_scene_strip_impl(
IMB_convert_profile(ibuf, IB_PROFILE_SRGB);
}
else if (rres.rect32) {
- ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0);
+ ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
memcpy(ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
}
@@ -1891,10 +1949,12 @@ static ImBuf * seq_render_scene_strip_impl(
}
/* restore */
- scene->r.scemode |= doseq;
+ context.scene->r.scemode |= doseq;
seq->scene->r.cfra = oldcfra;
seq->scene->camera= oldcamera;
+ if(frame != oldcfra)
+ scene_update_for_newframe(context.bmain, seq->scene, seq->scene->lay);
#ifdef DURIAN_CAMERA_SWITCH
/* stooping to new low's in hackyness :( */
@@ -1904,186 +1964,152 @@ static ImBuf * seq_render_scene_strip_impl(
return ibuf;
}
-static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra,
- int render_size,
- int seqrectx, int seqrecty)
+static ImBuf * seq_render_strip(SeqRenderData context, Sequence * seq, float cfra)
{
+ ImBuf * ibuf = NULL;
char name[FILE_MAXDIR+FILE_MAXFILE];
- int use_preprocess = input_have_to_preprocess(
- scene, seq, cfra, seqrectx, seqrecty);
- ImBuf * ibuf = seq_stripelem_cache_get(
- seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF);
+ int use_preprocess = input_have_to_preprocess(context, seq, cfra);
float nr = give_stripelem_index(seq, cfra);
+ /* all effects are handled similarly with the exception of speed effect */
+ int type = (seq->type & SEQ_EFFECT && seq->type != SEQ_SPEED) ? SEQ_EFFECT : seq->type;
- /* currently, we cache preprocessed images */
- if (ibuf) {
+ ibuf = seq_stripelem_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
+
+ /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
+ but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */
+ if (ibuf)
use_preprocess = FALSE;
- }
- if(seq->type == SEQ_META) {
- ImBuf * meta_ibuf = 0;
+ if (ibuf == NULL)
+ ibuf = copy_from_ibuf_still(context, seq, nr);
+
+ if (ibuf == NULL)
+ ibuf = seq_proxy_fetch(context, seq, cfra);
- if (ibuf == 0) {
- ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
- }
+ if(ibuf == NULL) switch(type) {
+ case SEQ_META:
+ {
+ ImBuf * meta_ibuf = NULL;
- if(!ibuf && seq->seqbase.first) {
- meta_ibuf = seq_render_strip_stack(
- bmain, scene,
- &seq->seqbase, seq->start + nr, 0,
- render_size, seqrectx, seqrecty);
- }
+ if(seq->seqbase.first)
+ meta_ibuf = seq_render_strip_stack(
+ context, &seq->seqbase,
+ seq->start + nr, 0);
- if(!ibuf && meta_ibuf) {
- ibuf = meta_ibuf;
- if(ibuf && use_preprocess) {
- struct ImBuf * i = IMB_dupImBuf(ibuf);
+ if(meta_ibuf) {
+ ibuf = meta_ibuf;
+ if(ibuf && use_preprocess) {
+ struct ImBuf * i = IMB_dupImBuf(ibuf);
- IMB_freeImBuf(ibuf);
+ IMB_freeImBuf(ibuf);
- ibuf = i;
+ ibuf = i;
+ }
}
+ break;
}
- } else if(seq->type == SEQ_SPEED) {
- ImBuf * child_ibuf = 0;
-
- if (ibuf == 0) {
- ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
- }
+ case SEQ_SPEED:
+ {
+ ImBuf * child_ibuf = NULL;
- if (ibuf == 0) {
float f_cfra;
- SpeedControlVars * s
- = (SpeedControlVars *)seq->effectdata;
+ SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
- sequence_effect_speed_rebuild_map(scene, seq, 0);
+ sequence_effect_speed_rebuild_map(context.scene,seq, 0);
/* weeek! */
f_cfra = seq->start + s->frameMap[(int) nr];
- child_ibuf = seq_render_strip(bmain, scene, seq->seq1, f_cfra,
- render_size,
- seqrectx, seqrecty);
- }
+ child_ibuf = seq_render_strip(context,seq->seq1,f_cfra);
- if (!ibuf && child_ibuf) {
- ibuf = child_ibuf;
- if(ibuf && use_preprocess) {
- struct ImBuf * i = IMB_dupImBuf(ibuf);
+ if (child_ibuf) {
+ ibuf = child_ibuf;
+ if(ibuf && use_preprocess) {
+ struct ImBuf * i = IMB_dupImBuf(ibuf);
- IMB_freeImBuf(ibuf);
+ IMB_freeImBuf(ibuf);
- ibuf = i;
+ ibuf = i;
+ }
}
+ break;
}
- } else if(seq->type & SEQ_EFFECT) {
- /* should the effect be recalculated? */
-
- if (ibuf == 0) {
- ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
- }
-
- if(ibuf == 0) {
- ibuf = seq_render_effect_strip_impl(
- bmain, scene, cfra, seq, render_size,
- seqrectx, seqrecty);
+ case SEQ_EFFECT:
+ {
+ ibuf = seq_render_effect_strip_impl(context, seq, cfra);
+ break;
}
- } else if(seq->type == SEQ_IMAGE) {
- StripElem * s_elem = give_stripelem(seq, cfra);
-
- if(ibuf == 0 && s_elem) {
- BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
- BLI_path_abs(name, G.sce);
+ case SEQ_IMAGE:
+ {
+ StripElem * s_elem = give_stripelem(seq, cfra);
- ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
- }
+ if (s_elem) {
+ BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
+ BLI_path_abs(name, G.main->name);
+ }
- if (ibuf == 0) {
- ibuf = copy_from_ibuf_still(seq,nr,seqrectx,seqrecty);
- }
+ if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) {
+ /* we don't need both (speed reasons)! */
+ if (ibuf->rect_float && ibuf->rect)
+ imb_freerectImBuf(ibuf);
- if (ibuf == 0 && s_elem &&
- (ibuf = IMB_loadiffname(name, IB_rect))) {
- /* we don't need both (speed reasons)! */
- if (ibuf->rect_float && ibuf->rect)
- imb_freerectImBuf(ibuf);
+ /* all sequencer color is done in SRGB space, linear gives odd crossfades */
+ if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
+ IMB_convert_profile(ibuf, IB_PROFILE_NONE);
- /* all sequencer color is done in SRGB space, linear gives odd crossfades */
- if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
- IMB_convert_profile(ibuf, IB_PROFILE_NONE);
+ copy_to_ibuf_still(context, seq, nr, ibuf);
- copy_to_ibuf_still(seq, nr, ibuf);
- }
- } else if(seq->type == SEQ_MOVIE) {
- if(ibuf == 0) {
- ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-
- }
-
- if (ibuf == 0) {
- ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty);
+ s_elem->orig_width = ibuf->x;
+ s_elem->orig_height = ibuf->y;
+ }
+ break;
}
-
- if (ibuf == 0) {
- if(seq->anim==0) {
- BLI_join_dirfile(name,
- seq->strip->dir,
- seq->strip->stripdata->name);
- BLI_path_abs(name, G.sce);
+ case SEQ_MOVIE:
+ {
+ if(seq->anim==NULL) {
+ BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name);
+ BLI_path_abs(name, G.main->name);
- seq->anim = openanim(
- name, IB_rect |
- ((seq->flag & SEQ_FILTERY)
- ? IB_animdeinterlace : 0));
+ seq->anim = openanim(name, IB_rect |
+ ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0));
}
+
if(seq->anim) {
- IMB_anim_set_preseek(seq->anim,
- seq->anim_preseek);
- ibuf = IMB_anim_absolute(seq->anim,
- nr
- + seq->anim_startofs);
+ IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
+ ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs);
/* we don't need both (speed reasons)! */
- if (ibuf && ibuf->rect_float
- && ibuf->rect) {
+ if (ibuf && ibuf->rect_float && ibuf->rect)
imb_freerectImBuf(ibuf);
+ if (ibuf) {
+ seq->strip->stripdata->orig_width = ibuf->x;
+ seq->strip->stripdata->orig_height = ibuf->y;
}
-
}
- copy_to_ibuf_still(seq, nr, ibuf);
- }
-
- } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions
- if (ibuf == 0) {
- ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
- }
- if (ibuf == 0) {
- ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty);
+ copy_to_ibuf_still(context, seq, nr, ibuf);
+ break;
}
-
- if (ibuf == 0) {
- ibuf = seq_render_scene_strip_impl(bmain, scene, seq, nr,
- seqrectx, seqrecty);
+ case SEQ_SCENE:
+ { // scene can be NULL after deletions
+ ibuf = seq_render_scene_strip_impl(context, seq, nr);
+
+ /* Scene strips update all animation, so we need to restore original state.*/
+ BKE_animsys_evaluate_all_animation(context.bmain, cfra);
- copy_to_ibuf_still(seq, nr, ibuf);
+ copy_to_ibuf_still(context, seq, nr, ibuf);
+ break;
}
}
- if (!ibuf) {
- ibuf = IMB_allocImBuf(
- (short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
- }
+ if (ibuf == NULL)
+ ibuf = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
- if (ibuf->x != seqrectx || ibuf->y != seqrecty) {
+ if (ibuf->x != context.rectx || ibuf->y != context.recty)
use_preprocess = TRUE;
- }
- if (use_preprocess) {
- ibuf = input_preprocess(scene, seq, cfra, seqrectx,
- seqrecty, ibuf);
- }
+ if (use_preprocess)
+ ibuf = input_preprocess(context, seq, cfra, ibuf);
- seq_stripelem_cache_put(
- seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF, ibuf);
+ seq_stripelem_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
return ibuf;
}
@@ -2099,9 +2125,7 @@ static int seq_must_swap_input_in_blend_mode(Sequence * seq)
/* bad hack, to fix crazy input ordering of
those two effects */
- if (seq->blend_mode == SEQ_ALPHAOVER ||
- seq->blend_mode == SEQ_ALPHAUNDER ||
- seq->blend_mode == SEQ_OVERDROP) {
+ if (ELEM3(seq->blend_mode, SEQ_ALPHAOVER, SEQ_ALPHAUNDER, SEQ_OVERDROP)) {
swap_input = TRUE;
}
@@ -2114,34 +2138,32 @@ static int seq_get_early_out_for_blend_mode(Sequence * seq)
float facf = seq->blend_opacity / 100.0;
int early_out = sh.early_out(seq, facf, facf);
- if (early_out < 1) {
+ if (ELEM(early_out, EARLY_DO_EFFECT, EARLY_NO_INPUT)) {
return early_out;
}
if (seq_must_swap_input_in_blend_mode(seq)) {
- if (early_out == 2) {
- return 1;
- } else if (early_out == 1) {
- return 2;
+ if (early_out == EARLY_USE_INPUT_2) {
+ return EARLY_USE_INPUT_1;
+ } else if (early_out == EARLY_USE_INPUT_1) {
+ return EARLY_USE_INPUT_2;
}
}
return early_out;
}
static ImBuf* seq_render_strip_stack(
- Main *bmain, Scene *scene, ListBase *seqbasep, float cfra, int chanshown,
- int render_size, int seqrectx, int seqrecty)
+ SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown)
{
Sequence* seq_arr[MAXSEQ+1];
int count;
int i;
- ImBuf* out = 0;
+ ImBuf* out = NULL;
- count = get_shown_sequences(seqbasep, cfra, chanshown,
- (Sequence **)&seq_arr);
+ count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr);
- if (!count) {
- return 0;
+ if (count == 0) {
+ return NULL;
}
#if 0 /* commentind since this breaks keyframing, since it resets the value on draw */
@@ -2152,22 +2174,17 @@ static ImBuf* seq_render_strip_stack(
}
#endif
- out = seq_stripelem_cache_get(
- seq_arr[count - 1],
- seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP);
+ out = seq_stripelem_cache_get(context, seq_arr[count - 1],
+ cfra, SEQ_STRIPELEM_IBUF_COMP);
if (out) {
return out;
}
if(count == 1) {
- out = seq_render_strip(bmain, scene, seq_arr[0],
- cfra, render_size,
- seqrectx, seqrecty);
- seq_stripelem_cache_put(
- seq_arr[0],
- seqrectx, seqrecty, cfra,
- SEQ_STRIPELEM_IBUF_COMP, out);
+ out = seq_render_strip(context, seq_arr[0], cfra);
+ seq_stripelem_cache_put(context, seq_arr[0], cfra,
+ SEQ_STRIPELEM_IBUF_COMP, out);
return out;
}
@@ -2175,43 +2192,34 @@ static ImBuf* seq_render_strip_stack(
for (i = count - 1; i >= 0; i--) {
int early_out;
- Sequence * seq = seq_arr[i];
+ Sequence *seq = seq_arr[i];
out = seq_stripelem_cache_get(
- seq,
- seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP);
+ context, seq, cfra, SEQ_STRIPELEM_IBUF_COMP);
if (out) {
break;
}
if (seq->blend_mode == SEQ_BLEND_REPLACE) {
- out = seq_render_strip(bmain, scene, seq, cfra,
- render_size,
- seqrectx, seqrecty);
+ out = seq_render_strip(context, seq, cfra);
break;
}
early_out = seq_get_early_out_for_blend_mode(seq);
switch (early_out) {
- case -1:
- case 2:
- out = seq_render_strip(bmain, scene, seq, cfra,
- render_size,
- seqrectx, seqrecty);
+ case EARLY_NO_INPUT:
+ case EARLY_USE_INPUT_2:
+ out = seq_render_strip(context, seq, cfra);
break;
- case 1:
+ case EARLY_USE_INPUT_1:
if (i == 0) {
- out = IMB_allocImBuf(
- (short)seqrectx, (short)seqrecty,
- 32, IB_rect, 0);
+ out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
}
break;
- case 0:
+ case EARLY_DO_EFFECT:
if (i == 0) {
- out = seq_render_strip(bmain, scene, seq, cfra,
- render_size,
- seqrectx, seqrecty);
+ out = seq_render_strip(context, seq, cfra);
}
break;
@@ -2221,9 +2229,8 @@ static ImBuf* seq_render_strip_stack(
}
}
- seq_stripelem_cache_put(
- seq_arr[i], seqrectx, seqrecty, cfra,
- SEQ_STRIPELEM_IBUF_COMP, out);
+ seq_stripelem_cache_put(context, seq_arr[i], cfra,
+ SEQ_STRIPELEM_IBUF_COMP, out);
i++;
@@ -2231,37 +2238,30 @@ static ImBuf* seq_render_strip_stack(
for (; i < count; i++) {
Sequence * seq = seq_arr[i];
- if (seq_get_early_out_for_blend_mode(seq) == 0) {
+ if (seq_get_early_out_for_blend_mode(seq) == EARLY_DO_EFFECT) {
struct SeqEffectHandle sh = get_sequence_blend(seq);
ImBuf * ibuf1 = out;
- ImBuf * ibuf2 = seq_render_strip(bmain, scene, seq, cfra,
- render_size,
- seqrectx, seqrecty);
+ ImBuf * ibuf2 = seq_render_strip(context, seq, cfra);
float facf = seq->blend_opacity / 100.0;
- int swap_input
- = seq_must_swap_input_in_blend_mode(seq);
-
- int x= seqrectx;
- int y= seqrecty;
+ int swap_input = seq_must_swap_input_in_blend_mode(seq);
if (swap_input) {
- out = sh.execute(bmain, scene, seq, cfra,
- facf, facf, x, y, render_size,
- ibuf2, ibuf1, 0);
+ out = sh.execute(context, seq, cfra,
+ facf, facf,
+ ibuf2, ibuf1, NULL);
} else {
- out = sh.execute(bmain, scene, seq, cfra,
- facf, facf, x, y, render_size,
- ibuf1, ibuf2, 0);
+ out = sh.execute(context, seq, cfra,
+ facf, facf,
+ ibuf1, ibuf2, NULL);
}
IMB_freeImBuf(ibuf1);
IMB_freeImBuf(ibuf2);
}
- seq_stripelem_cache_put(
- seq_arr[i], seqrectx, seqrecty, cfra,
- SEQ_STRIPELEM_IBUF_COMP, out);
+ seq_stripelem_cache_put(context, seq_arr[i], cfra,
+ SEQ_STRIPELEM_IBUF_COMP, out);
}
return out;
@@ -2272,9 +2272,9 @@ static ImBuf* seq_render_strip_stack(
* you have to free after usage!
*/
-ImBuf *give_ibuf_seq(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
+ImBuf *give_ibuf_seq(SeqRenderData context, float cfra, int chanshown)
{
- Editing *ed= seq_give_editing(scene, FALSE);
+ Editing *ed= seq_give_editing(context.scene, FALSE);
int count;
ListBase *seqbasep;
@@ -2288,19 +2288,18 @@ ImBuf *give_ibuf_seq(Main *bmain, Scene *scene, int rectx, int recty, int cfra,
seqbasep= ed->seqbasep;
}
- return seq_render_strip_stack(
- bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
+ return seq_render_strip_stack(context, seqbasep, cfra, chanshown);
}
-ImBuf *give_ibuf_seqbase(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size, ListBase *seqbasep)
+ImBuf *give_ibuf_seqbase(SeqRenderData context, float cfra, int chanshown, ListBase *seqbasep)
{
- return seq_render_strip_stack(bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
+ return seq_render_strip_stack(context, seqbasep, cfra, chanshown);
}
-ImBuf *give_ibuf_seq_direct(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq)
+ImBuf *give_ibuf_seq_direct(SeqRenderData context, float cfra, Sequence *seq)
{
- return seq_render_strip(bmain, scene, seq, cfra, render_size, rectx, recty);
+ return seq_render_strip(context, seq, cfra);
}
#if 0
@@ -2350,9 +2349,9 @@ typedef struct PrefetchQueueElem {
int rectx;
int recty;
- int cfra;
+ float cfra;
int chanshown;
- int render_size;
+ int preview_render_size;
int monoton_cfra;
@@ -2400,7 +2399,7 @@ static void *seq_prefetch_thread(void * This_)
if (e->cfra >= s_last) {
e->ibuf = give_ibuf_seq_impl(This->scene,
e->rectx, e->recty, e->cfra, e->chanshown,
- e->render_size);
+ e->preview_render_size);
}
pthread_mutex_lock(&queue_lock);
@@ -2510,8 +2509,7 @@ static void seq_stop_threads()
}
#endif
-void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown,
- int render_size)
+void give_ibuf_prefetch_request(SeqRenderData context, float cfra, int chanshown)
{
PrefetchQueueElem *e;
if (seq_thread_shutdown) {
@@ -2519,11 +2517,11 @@ void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown,
}
e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem");
- e->rectx = rectx;
- e->recty = recty;
+ e->rectx = context.rectx;
+ e->recty = context.recty;
e->cfra = cfra;
e->chanshown = chanshown;
- e->render_size = render_size;
+ e->preview_render_size = context.preview_render_size;
e->monoton_cfra = monoton_cfra++;
pthread_mutex_lock(&queue_lock);
@@ -2566,13 +2564,13 @@ static void seq_wait_for_prefetch_ready()
}
#endif
-ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
+ImBuf *give_ibuf_seq_threaded(SeqRenderData context, float cfra, int chanshown)
{
PrefetchQueueElem *e = NULL;
int found_something = FALSE;
if (seq_thread_shutdown) {
- return give_ibuf_seq(bmain, scene, rectx, recty, cfra, chanshown, render_size);
+ return give_ibuf_seq(context, cfra, chanshown);
}
while (!e) {
@@ -2582,9 +2580,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i
for (e = prefetch_done.first; e; e = e->next) {
if (cfra == e->cfra &&
chanshown == e->chanshown &&
- rectx == e->rectx &&
- recty == e->recty &&
- render_size == e->render_size) {
+ context.rectx == e->rectx &&
+ context.recty == e->recty &&
+ context.preview_render_size == e->preview_render_size) {
success = TRUE;
found_something = TRUE;
break;
@@ -2595,9 +2593,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i
for (e = prefetch_wait.first; e; e = e->next) {
if (cfra == e->cfra &&
chanshown == e->chanshown &&
- rectx == e->rectx &&
- recty == e->recty &&
- render_size == e->render_size) {
+ context.rectx == e->rectx &&
+ context.recty == e->recty &&
+ context.preview_render_size == e->preview_render_size) {
found_something = TRUE;
break;
}
@@ -2612,9 +2610,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i
if (tslot->current &&
cfra == tslot->current->cfra &&
chanshown == tslot->current->chanshown &&
- rectx == tslot->current->rectx &&
- recty == tslot->current->recty &&
- render_size== tslot->current->render_size){
+ context.rectx == tslot->current->rectx &&
+ context.recty == tslot->current->recty &&
+ context.preview_render_size== tslot->current->preview_render_size){
found_something = TRUE;
break;
}
@@ -2644,7 +2642,7 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i
}
}
- return e ? e->ibuf : 0;
+ return e ? e->ibuf : NULL;
}
/* Functions to free imbuf and anim data on changes */
@@ -2653,7 +2651,7 @@ static void free_anim_seq(Sequence *seq)
{
if(seq->anim) {
IMB_free_anim(seq->anim);
- seq->anim = 0;
+ seq->anim = NULL;
}
}
@@ -2697,8 +2695,7 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage,
}
}
if(seq->type==SEQ_META) {
- free_imbuf_seq(scene, &seq->seqbase, FALSE,
- keep_file_handles);
+ free_imbuf_seq(scene, &seq->seqbase, FALSE, keep_file_handles);
}
if(seq->type==SEQ_SCENE) {
/* FIXME: recurs downwards,
@@ -2822,11 +2819,7 @@ void seq_tx_set_final_right(Sequence *seq, int val)
since they work a bit differently to normal image seq's (during transform) */
int seq_single_check(Sequence *seq)
{
- if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR
- || seq->type == SEQ_MULTICAM))
- return 1;
- else
- return 0;
+ return (seq->len==1 && ELEM3(seq->type, SEQ_IMAGE, SEQ_COLOR, SEQ_MULTICAM));
}
/* check if the selected seq's reference unselected seq's */
@@ -2848,17 +2841,20 @@ int seqbase_isolated_sel_check(ListBase *seqbase)
/* test relationships */
for(seq= seqbase->first; seq; seq= seq->next) {
+ if((seq->type & SEQ_EFFECT)==0)
+ continue;
+
if(seq->flag & SELECT) {
- if(seq->type & SEQ_EFFECT) {
- if(seq->seq1 && (seq->seq1->flag & SELECT)==0) return FALSE;
- if(seq->seq2 && (seq->seq2->flag & SELECT)==0) return FALSE;
- if(seq->seq3 && (seq->seq3->flag & SELECT)==0) return FALSE;
- }
+ if( (seq->seq1 && (seq->seq1->flag & SELECT)==0) ||
+ (seq->seq2 && (seq->seq2->flag & SELECT)==0) ||
+ (seq->seq3 && (seq->seq3->flag & SELECT)==0) )
+ return FALSE;
}
- else if(seq->type & SEQ_EFFECT) {
- if(seq->seq1 && (seq->seq1->flag & SELECT)) return FALSE;
- if(seq->seq2 && (seq->seq2->flag & SELECT)) return FALSE;
- if(seq->seq3 && (seq->seq3->flag & SELECT)) return FALSE;
+ else {
+ if( (seq->seq1 && (seq->seq1->flag & SELECT)) ||
+ (seq->seq2 && (seq->seq2->flag & SELECT)) ||
+ (seq->seq3 && (seq->seq3->flag & SELECT)) )
+ return FALSE;
}
}
@@ -2935,12 +2931,8 @@ int seq_tx_test(Sequence * seq)
static int seq_overlap(Sequence *seq1, Sequence *seq2)
{
- if(seq1 != seq2)
- if(seq1->machine==seq2->machine)
- if(((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0)
- return 1;
-
- return 0;
+ return (seq1 != seq2 && seq1->machine == seq2->machine &&
+ ((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0);
}
int seq_test_overlap(ListBase * seqbasep, Sequence *test)
@@ -2958,7 +2950,7 @@ int seq_test_overlap(ListBase * seqbasep, Sequence *test)
}
-static void seq_translate(Scene *evil_scene, Sequence *seq, int delta)
+void seq_translate(Scene *evil_scene, Sequence *seq, int delta)
{
seq_offset_animdata(evil_scene, seq, delta);
seq->start += delta;
@@ -2973,6 +2965,28 @@ static void seq_translate(Scene *evil_scene, Sequence *seq, int delta)
calc_sequence_disp(evil_scene, seq);
}
+Sequence *seq_foreground_frame_get(Scene *scene, int frame)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq, *best_seq=NULL;
+ int best_machine = -1;
+
+ if(!ed) return NULL;
+
+ for (seq=ed->seqbasep->first; seq; seq= seq->next) {
+ if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
+ continue;
+ /* only use elements you can see - not */
+ if (ELEM5(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR)) {
+ if (seq->machine > best_machine) {
+ best_seq = seq;
+ best_machine = seq->machine;
+ }
+ }
+ }
+ return best_seq;
+}
+
/* return 0 if there werent enough space */
int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene)
{
@@ -3107,7 +3121,7 @@ static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequen
seq_update_muting_recursive(scene, &seq->seqbase, metaseq, seqmute);
}
- else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) {
+ else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
if(seq->scene_sound) {
sound_mute_scene_sound(scene, seq->scene_sound, seqmute);
}
@@ -3210,7 +3224,7 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs)
for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) {
if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) {
- int i;
+ unsigned int i;
for (i = 0; i < fcu->totvert; i++) {
BezTriple *bezt= &fcu->bezt[i];
bezt->vec[0][0] += ofs;
@@ -3247,7 +3261,7 @@ void seq_dupe_animdata(Scene *scene, char *name_from, char *name_to)
BKE_animdata_fix_paths_rename(&scene->id, scene->adt, "sequence_editor.sequences_all", name_from, name_to, 0, 0, 0);
/* add the original fcurves back */
- addlisttolist(&scene->adt->action->curves, &lb);
+ BLI_movelisttolist(&scene->adt->action->curves, &lb);
}
/* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */
@@ -3385,6 +3399,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
seq->mul= 1.0;
seq->blend_opacity = 100.0;
seq->volume = 1.0f;
+ seq->scene_sound = NULL;
return seq;
}
@@ -3395,7 +3410,6 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
Scene *scene= CTX_data_scene(C); /* only for active seq */
Sequence *seq;
Strip *strip;
- StripElem *se;
seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel);
seq->type= SEQ_IMAGE;
@@ -3406,7 +3420,7 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
strip->len = seq->len = seq_load->len ? seq_load->len : 1;
strip->us= 1;
- strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+ strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir));
seq_load_apply(scene, seq, seq_load);
@@ -3476,14 +3490,14 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
Scene *scene= CTX_data_scene(C); /* only for sound */
char path[sizeof(seq_load->path)];
- Sequence *seq, *soundseq; /* generic strip vars */
+ Sequence *seq; /* generic strip vars */
Strip *strip;
StripElem *se;
struct anim *an;
BLI_strncpy(path, seq_load->path, sizeof(path));
- BLI_path_abs(path, G.sce);
+ BLI_path_abs(path, G.main->name);
an = openanim(path, IB_rect);
@@ -3515,7 +3529,7 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
int start_frame_back= seq_load->start_frame;
seq_load->channel++;
- soundseq = sequencer_add_sound_strip(C, seqbasep, seq_load);
+ sequencer_add_sound_strip(C, seqbasep, seq_load);
seq_load->start_frame= start_frame_back;
seq_load->channel--;
@@ -3531,8 +3545,9 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
}
-static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
+static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence *seq, int dupe_flag)
{
+ Scene *sce_audio= scene_to ? scene_to : scene;
Sequence *seqn = MEM_dupallocN(seq);
seq->tmp = seqn;
@@ -3550,6 +3565,7 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
if (seq->strip->proxy) {
seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
+ seqn->strip->proxy->anim = NULL;
}
if (seq->strip->color_balance) {
@@ -3558,24 +3574,24 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
}
if(seq->type==SEQ_META) {
- seqn->strip->stripdata = 0;
+ seqn->strip->stripdata = NULL;
- seqn->seqbase.first= seqn->seqbase.last= 0;
+ seqn->seqbase.first= seqn->seqbase.last= NULL;
/* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
/* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/
} else if(seq->type == SEQ_SCENE) {
- seqn->strip->stripdata = 0;
+ seqn->strip->stripdata = NULL;
if(seq->scene_sound)
- seqn->scene_sound = sound_scene_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
+ seqn->scene_sound = sound_scene_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
} else if(seq->type == SEQ_MOVIE) {
seqn->strip->stripdata =
MEM_dupallocN(seq->strip->stripdata);
- seqn->anim= 0;
+ seqn->anim= NULL;
} else if(seq->type == SEQ_SOUND) {
seqn->strip->stripdata =
MEM_dupallocN(seq->strip->stripdata);
if(seq->scene_sound)
- seqn->scene_sound = sound_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
+ seqn->scene_sound = sound_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
seqn->sound->id.us++;
} else if(seq->type == SEQ_IMAGE) {
@@ -3593,7 +3609,7 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
sh.copy(seq, seqn);
}
- seqn->strip->stripdata = 0;
+ seqn->strip->stripdata = NULL;
} else {
fprintf(stderr, "Aiiiiekkk! sequence type not "
@@ -3610,13 +3626,13 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
return seqn;
}
-Sequence * seq_dupli_recursive(struct Scene *scene, Sequence * seq, int dupe_flag)
+Sequence * seq_dupli_recursive(struct Scene *scene, struct Scene *scene_to, Sequence * seq, int dupe_flag)
{
- Sequence * seqn = seq_dupli(scene, seq, dupe_flag);
+ Sequence * seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
if (seq->type == SEQ_META) {
Sequence *s;
for(s= seq->seqbase.first; s; s = s->next) {
- Sequence *n = seq_dupli_recursive(scene, s, dupe_flag);
+ Sequence *n = seq_dupli_recursive(scene, scene_to, s, dupe_flag);
if (n) {
BLI_addtail(&seqn->seqbase, n);
}
@@ -3625,16 +3641,16 @@ Sequence * seq_dupli_recursive(struct Scene *scene, Sequence * seq, int dupe_fla
return seqn;
}
-void seqbase_dupli_recursive(Scene *scene, ListBase *nseqbase, ListBase *seqbase, int dupe_flag)
+void seqbase_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag)
{
Sequence *seq;
- Sequence *seqn = 0;
+ Sequence *seqn = NULL;
Sequence *last_seq = seq_active_get(scene);
for(seq= seqbase->first; seq; seq= seq->next) {
seq->tmp= NULL;
if((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) {
- seqn = seq_dupli(scene, seq, dupe_flag);
+ seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
if (seqn) { /*should never fail */
if(dupe_flag & SEQ_DUPE_CONTEXT) {
seq->flag &= ~SEQ_ALLSEL;
@@ -3643,7 +3659,7 @@ void seqbase_dupli_recursive(Scene *scene, ListBase *nseqbase, ListBase *seqbase
BLI_addtail(nseqbase, seqn);
if(seq->type==SEQ_META)
- seqbase_dupli_recursive(scene, &seqn->seqbase, &seq->seqbase, dupe_flag);
+ seqbase_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag);
if(dupe_flag & SEQ_DUPE_CONTEXT) {
if (seq == last_seq) {
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 454a82c2ad3..5311f3a9c38 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -1,5 +1,5 @@
-/**
- * shrinkwrap.c
+/*
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -22,7 +22,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): André Pinto
+ * Contributor(s): Andr Pinto
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -41,25 +41,21 @@
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
+#include "BLI_editVert.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
#include "BKE_shrinkwrap.h"
#include "BKE_DerivedMesh.h"
#include "BKE_lattice.h"
-#include "BKE_utildefines.h"
+
#include "BKE_deform.h"
#include "BKE_mesh.h"
#include "BKE_subsurf.h"
#include "BKE_mesh.h"
#include "BKE_tessmesh.h"
-#include "BLI_math.h"
-#include "BLI_editVert.h"
-
-
-
/* Util macros */
-#define TO_STR(a) #a
-#define JOIN(a,b) a##b
-
#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
/* Benchmark macros */
@@ -90,20 +86,18 @@ typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *c
/* get derived mesh */
//TODO is anyfunction that does this? returning the derivedFinal witouth we caring if its in edit mode or not?
-DerivedMesh *object_get_derived_final(struct Scene *scene, Object *ob, CustomDataMask dataMask)
+DerivedMesh *object_get_derived_final(Object *ob)
{
Mesh *me= ob->data;
BMEditMesh *em = me->edit_btmesh;
if (em)
{
- DerivedMesh *final = NULL;
- editbmesh_get_derived_cage_and_final(scene, ob, em, &final, dataMask);
-
- return final;
+ DerivedMesh *dm = em->derivedFinal;
+ return dm;
}
- else
- return mesh_get_derived_final(scene, ob, dataMask);
+
+ return ob->derivedFinal;
}
/* Space transform */
@@ -111,7 +105,7 @@ void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float
{
float itarget[4][4];
invert_m4_m4(itarget, target);
- mul_serie_m4(data->local2target, itarget, local, 0, 0, 0, 0, 0, 0);
+ mul_serie_m4(data->local2target, itarget, local, NULL, NULL, NULL, NULL, NULL, NULL);
invert_m4_m4(data->target2local, data->local2target);
}
@@ -264,22 +258,26 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata);
- if(hit_tmp.index != -1)
- {
- float dot = INPR( dir, hit_tmp.no);
-
- if(((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f)
- || ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f))
- return FALSE; //Ignore hit
-
+ if(hit_tmp.index != -1) {
+ /* invert the normal first so face culling works on rotated objects */
+ if(transf) {
+ space_transform_invert_normal(transf, hit_tmp.no);
+ }
- //Inverting space transform (TODO make coeherent with the initial dist readjust)
- if(transf)
- {
- space_transform_invert( transf, hit_tmp.co );
- space_transform_invert_normal( transf, hit_tmp.no );
+ if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE|MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) {
+ /* apply backface */
+ const float dot= dot_v3v3(dir, hit_tmp.no);
+ if( ((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) ||
+ ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f)
+ ) {
+ return FALSE; /* Ignore hit */
+ }
+ }
- hit_tmp.dist = len_v3v3( (float*)vert, hit_tmp.co );
+ if(transf) {
+ /* Inverting space transform (TODO make coeherent with the initial dist readjust) */
+ space_transform_invert(transf, hit_tmp.co);
+ hit_tmp.dist = len_v3v3((float *)vert, hit_tmp.co);
}
memcpy(hit, &hit_tmp, sizeof(hit_tmp) );
@@ -289,7 +287,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
}
-static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct Scene *scene)
+static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
{
int i;
@@ -334,12 +332,14 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S
if(calc->smd->auxTarget)
{
- auxMesh = object_get_derived_final(scene, calc->smd->auxTarget, CD_MASK_BAREMESH);
+ auxMesh = object_get_derived_final(calc->smd->auxTarget);
+ if(!auxMesh)
+ return;
space_transform_setup( &local2aux, calc->ob, calc->smd->auxTarget);
}
//After sucessufuly build the trees, start projection vertexs
- if( bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6)
+ if( bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 4, 6)
&& (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6)))
{
@@ -388,10 +388,10 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S
}
//Project over negative direction of axis
- if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)
+ if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR && hit.index == -1)
{
- float inv_no[3] = { -tmp_no[0], -tmp_no[1], -tmp_no[2] };
-
+ float inv_no[3];
+ negate_v3_v3(inv_no, tmp_no);
if(auxData.tree)
normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
@@ -402,6 +402,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S
if(hit.index != -1)
{
+ madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist);
interp_v3_v3v3(co, co, hit.co, weight);
}
}
@@ -500,7 +501,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
}
/* Main shrinkwrap function */
-void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
+void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *ss_mesh = NULL;
@@ -531,7 +532,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object
if(smd->target)
{
- calc.target = object_get_derived_final(scene, smd->target, CD_MASK_BAREMESH);
+ calc.target = object_get_derived_final(smd->target);
//TODO there might be several "bugs" on non-uniform scales matrixs
//because it will no longer be nearest surface, not sphere projection
@@ -555,8 +556,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object
//Using vertexs positions/normals as if a subsurface was applied
if(smd->subsurfLevels)
{
- SubsurfModifierData ssmd;
- memset(&ssmd, 0, sizeof(ssmd));
+ SubsurfModifierData ssmd= {{0}};
ssmd.subdivType = ME_CC_SUBSURF; //catmull clark
ssmd.levels = smd->subsurfLevels; //levels
@@ -589,7 +589,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object
break;
case MOD_SHRINKWRAP_PROJECT:
- BENCH(shrinkwrap_calc_normal_projection(&calc, scene));
+ BENCH(shrinkwrap_calc_normal_projection(&calc));
break;
case MOD_SHRINKWRAP_NEAREST_VERTEX:
diff --git a/source/blender/blenkernel/intern/sketch.c b/source/blender/blenkernel/intern/sketch.c
index 7e39cdd1196..8917d2946bd 100644
--- a/source/blender/blenkernel/intern/sketch.c
+++ b/source/blender/blenkernel/intern/sketch.c
@@ -1,4 +1,4 @@
-/**
+/*
*
* $Id$
*
@@ -31,9 +31,10 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_sketch.h"
-#include "BKE_utildefines.h"
+
#include "DNA_userdef_types.h"
@@ -53,7 +54,7 @@ void freeSketch(SK_Sketch *sketch)
MEM_freeN(sketch);
}
-SK_Sketch* createSketch()
+SK_Sketch* createSketch(void)
{
SK_Sketch *sketch;
@@ -101,7 +102,7 @@ void sk_freeStroke(SK_Stroke *stk)
MEM_freeN(stk);
}
-SK_Stroke* sk_createStroke()
+SK_Stroke* sk_createStroke(void)
{
SK_Stroke *stk;
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index c6993e933c2..b2f8831cced 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -1,4 +1,4 @@
-/**
+/*
* smoke.c
*
* $Id$
@@ -48,6 +48,7 @@
#include "BLI_edgehash.h"
#include "BLI_kdtree.h"
#include "BLI_kdopbvh.h"
+#include "BLI_utildefines.h"
#include "BKE_bvhutils.h"
#include "BKE_cdderivedmesh.h"
@@ -58,7 +59,7 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_smoke.h"
-#include "BKE_utildefines.h"
+
#include "DNA_customdata_types.h"
#include "DNA_group_types.h"
@@ -94,7 +95,7 @@ static void tend ( void )
{
QueryPerformanceCounter ( &liCurrentTime );
}
-static double tval()
+static double tval( void )
{
return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart)* (double)1000.0/(double)liFrequency.QuadPart ));
}
@@ -110,6 +111,8 @@ static void tend ( void )
{
gettimeofday ( &_tend,&tz );
}
+
+#if 0 // unused
static double tval()
{
double t1, t2;
@@ -118,6 +121,7 @@ static double tval()
return t2-t1;
}
#endif
+#endif
struct Object;
struct Scene;
@@ -131,7 +135,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
#define TRI_UVOFFSET (1./4.)
-int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm)
+static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm)
{
if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
{
@@ -177,7 +181,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive
if(size[0] > size[1])
{
- if(size[0] > size[1])
+ if(size[0] > size[2])
{
scale = res / size[0];
smd->domain->dx = size[0] / res;
@@ -187,11 +191,11 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive
}
else
{
- scale = res / size[1];
- smd->domain->dx = size[1] / res;
- smd->domain->res[1] = res;
+ scale = res / size[2];
+ smd->domain->dx = size[2] / res;
+ smd->domain->res[2] = res;
smd->domain->res[0] = (int)(size[0] * scale + 0.5);
- smd->domain->res[2] = (int)(size[2] * scale + 0.5);
+ smd->domain->res[1] = (int)(size[1] * scale + 0.5);
}
}
else
@@ -435,7 +439,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
}
/*! init triangle divisions */
-void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *faces, int numfaces, int numtris, int **tridivs, float cell_len)
+void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFace *faces, int numfaces, int numtris, int **tridivs, float cell_len)
{
// mTriangleDivs1.resize( faces.size() );
// mTriangleDivs2.resize( faces.size() );
@@ -554,8 +558,6 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd)
BKE_ptcache_free_list(&(smd->domain->ptcaches[0]));
smd->domain->point_cache[0] = NULL;
- BKE_ptcache_free_list(&(smd->domain->ptcaches[1]));
- smd->domain->point_cache[1] = NULL;
MEM_freeN(smd->domain);
smd->domain = NULL;
@@ -629,9 +631,6 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
smd->domain->fluid = NULL;
}
- smd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED;
- smd->domain->point_cache[1]->flag |= PTCACHE_OUTDATED;
-
smokeModifier_reset_turbulence(smd);
smd->time = -1;
@@ -698,10 +697,9 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->point_cache[0]->flag |= PTCACHE_DISK_CACHE;
smd->domain->point_cache[0]->step = 1;
- smd->domain->point_cache[1] = BKE_ptcache_add(&(smd->domain->ptcaches[1]));
- smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE;
- smd->domain->point_cache[1]->step = 1;
-
+ /* Deprecated */
+ smd->domain->point_cache[1] = NULL;
+ smd->domain->ptcaches[1].first = smd->domain->ptcaches[1].last = NULL;
/* set some standard values */
smd->domain->fluid = NULL;
smd->domain->wt = NULL;
@@ -779,6 +777,9 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
tsmd->domain->viewsettings = smd->domain->viewsettings;
tsmd->domain->fluid_group = smd->domain->fluid_group;
tsmd->domain->coll_group = smd->domain->coll_group;
+ tsmd->domain->vorticity = smd->domain->vorticity;
+ tsmd->domain->time_scale = smd->domain->time_scale;
+ tsmd->domain->border_collisions = smd->domain->border_collisions;
MEM_freeN(tsmd->domain->effector_weights);
tsmd->domain->effector_weights = MEM_dupallocN(smd->domain->effector_weights);
@@ -787,6 +788,8 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
tsmd->flow->temp = smd->flow->temp;
tsmd->flow->psys = smd->flow->psys;
tsmd->flow->type = smd->flow->type;
+ tsmd->flow->flags = smd->flow->flags;
+ tsmd->flow->vel_multi = smd->flow->vel_multi;
} else if (tsmd->coll) {
;
/* leave it as initialised, collision settings is mostly caches */
@@ -800,20 +803,25 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix
static int get_lamp(Scene *scene, float *light)
{
Base *base_tmp = NULL;
- for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next)
- {
- if(base_tmp->object->type == OB_LAMP)
- {
- Lamp *la = (Lamp *)base_tmp->object->data;
-
- if(la->type == LA_LOCAL)
- {
- VECCOPY(light, base_tmp->object->obmat[3]);
- return 1;
- }
- }
- }
- return 0;
+ int found_lamp = 0;
+
+ // try to find a lamp, preferably local
+ for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) {
+ if(base_tmp->object->type == OB_LAMP) {
+ Lamp *la = base_tmp->object->data;
+
+ if(la->type == LA_LOCAL) {
+ copy_v3_v3(light, base_tmp->object->obmat[3]);
+ return 1;
+ }
+ else if(!found_lamp) {
+ copy_v3_v3(light, base_tmp->object->obmat[3]);
+ found_lamp = 1;
+ }
+ }
+ }
+
+ return found_lamp;
}
static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
@@ -822,9 +830,109 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
GroupObject *go = NULL;
Base *base = NULL;
+ // do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells
+ if(1)
+ {
+ Object *otherobj = NULL;
+ ModifierData *md = NULL;
+
+ if(sds->coll_group) // we use groups since we have 2 domains
+ go = sds->coll_group->gobject.first;
+ else
+ base = scene->base.first;
+
+ while(base || go)
+ {
+ otherobj = NULL;
+ if(sds->coll_group)
+ {
+ if(go->ob)
+ otherobj = go->ob;
+ }
+ else
+ otherobj = base->object;
+ if(!otherobj)
+ {
+ if(sds->coll_group)
+ go = go->next;
+ else
+ base= base->next;
+ continue;
+ }
+ md = modifiers_findByType(otherobj, eModifierType_Smoke);
+
+ // check for active smoke modifier
+ if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
+ {
+ SmokeModifierData *smd2 = (SmokeModifierData *)md;
+
+ if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points)
+ {
+ // we got nice collision object
+ SmokeCollSettings *scs = smd2->coll;
+ size_t i, j;
+ unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid);
+
+ for(i = 0; i < scs->numpoints; i++)
+ {
+ int badcell = 0;
+ size_t index = 0;
+ int cell[3];
+
+ // 1. get corresponding cell
+ get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, &scs->points[3 * i], cell, 0);
+
+ // check if cell is valid (in the domain boundary)
+ for(j = 0; j < 3; j++)
+ if((cell[j] > sds->res[j] - 1) || (cell[j] < 0))
+ {
+ badcell = 1;
+ break;
+ }
+
+ if(badcell)
+ continue;
+ // 2. set cell values (heat, density and velocity)
+ index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
+
+ // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]);
+ // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index);
+ obstacles[index] = 1;
+ // for moving gobstacles
+ /*
+ const LbmFloat maxVelVal = 0.1666;
+ const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5;
+
+ LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec);
+ {
+ const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5;
+ USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz);
+ if(usqr>maxusqr) {
+ // cutoff at maxVelVal
+ for(int jj=0; jj<3; jj++) {
+ if(objvel[jj]>0.) objvel[jj] = maxVelVal;
+ if(objvel[jj]<0.) objvel[jj] = -maxVelVal;
+ }
+ }
+ }
+ const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) );
+ const LbmVec oldov=objvel; // debug
+ objvel = vec2L((*pNormals)[n]) *dp;
+ */
+ }
+ }
+ }
+
+ if(sds->coll_group)
+ go = go->next;
+ else
+ base= base->next;
+ }
+ }
+
// do flows and fluids
if(1)
- {
+ {
Object *otherobj = NULL;
ModifierData *md = NULL;
if(sds->fluid_group) // we use groups since we have 2 domains
@@ -866,9 +974,8 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
if(sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected
{
+ ParticleSimulationData sim;
ParticleSystem *psys = sfs->psys;
- ParticleSettings *part=psys->part;
- ParticleData *pa = NULL;
int p = 0;
float *density = smoke_get_density(sds->fluid);
float *bigdensity = smoke_turbulence_get_density(sds->wt);
@@ -888,6 +995,10 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
*/
float *temp_emission_map = NULL;
+ sim.scene = scene;
+ sim.ob = otherobj;
+ sim.psys = psys;
+
// initialize temp emission map
if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
{
@@ -900,19 +1011,26 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
}
// mostly copied from particle code
- for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++)
- {
- int cell[3];
- size_t i = 0;
- size_t index = 0;
- int badcell = 0;
- if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue;
- else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue;
- else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;
+ for(p=0; p<psys->totpart; p++)
+ {
+ int cell[3];
+ size_t i = 0;
+ size_t index = 0;
+ int badcell = 0;
+ ParticleKey state;
+
+ if(psys->particles[p].flag & (PARS_NO_DISP|PARS_UNEXIST))
+ continue;
+
+ state.time = smd->time;
+
+ if(psys_get_particle_state(&sim, p, &state, 0) == 0)
+ continue;
+
// VECCOPY(pos, pa->state.co);
// mul_m4_v3(ob->imat, pos);
// 1. get corresponding cell
- get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, pa->state.co, cell, 0);
+ get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, state.co, cell, 0);
// check if cell is valid (in the domain boundary)
for(i = 0; i < 3; i++)
{
@@ -926,7 +1044,7 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
continue;
// 2. set cell values (heat, density and velocity)
index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
- if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index] & 2)) // this is inflow
+ if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // this is inflow
{
// heat[index] += sfs->temp * 0.1;
// density[index] += sfs->density * 0.1;
@@ -938,9 +1056,9 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
// Uses particle velocity as initial velocity for smoke
if(sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO))
{
- velocity_x[index] = pa->state.vel[0]*sfs->vel_multi;
- velocity_y[index] = pa->state.vel[1]*sfs->vel_multi;
- velocity_z[index] = pa->state.vel[2]*sfs->vel_multi;
+ velocity_x[index] = state.vel[0]*sfs->vel_multi;
+ velocity_y[index] = state.vel[1]*sfs->vel_multi;
+ velocity_z[index] = state.vel[2]*sfs->vel_multi;
}
}
else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow
@@ -1165,107 +1283,8 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
pdEndEffectors(&effectors);
}
- // do collisions
- if(1)
- {
- Object *otherobj = NULL;
- ModifierData *md = NULL;
-
- if(sds->coll_group) // we use groups since we have 2 domains
- go = sds->coll_group->gobject.first;
- else
- base = scene->base.first;
-
- while(base || go)
- {
- otherobj = NULL;
- if(sds->coll_group)
- {
- if(go->ob)
- otherobj = go->ob;
- }
- else
- otherobj = base->object;
- if(!otherobj)
- {
- if(sds->coll_group)
- go = go->next;
- else
- base= base->next;
- continue;
- }
- md = modifiers_findByType(otherobj, eModifierType_Smoke);
-
- // check for active smoke modifier
- if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
- {
- SmokeModifierData *smd2 = (SmokeModifierData *)md;
-
- if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points)
- {
- // we got nice collision object
- SmokeCollSettings *scs = smd2->coll;
- size_t i, j;
- unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid);
-
- for(i = 0; i < scs->numpoints; i++)
- {
- int badcell = 0;
- size_t index = 0;
- int cell[3];
-
- // 1. get corresponding cell
- get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, &scs->points[3 * i], cell, 0);
-
- // check if cell is valid (in the domain boundary)
- for(j = 0; j < 3; j++)
- if((cell[j] > sds->res[j] - 1) || (cell[j] < 0))
- {
- badcell = 1;
- break;
- }
-
- if(badcell)
- continue;
- // 2. set cell values (heat, density and velocity)
- index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
-
- // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]);
- // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index);
- obstacles[index] = 1;
- // for moving gobstacles
- /*
- const LbmFloat maxVelVal = 0.1666;
- const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5;
-
- LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec);
- {
- const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5;
- USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz);
- if(usqr>maxusqr) {
- // cutoff at maxVelVal
- for(int jj=0; jj<3; jj++) {
- if(objvel[jj]>0.) objvel[jj] = maxVelVal;
- if(objvel[jj]<0.) objvel[jj] = -maxVelVal;
- }
- }
- }
- const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) );
- const LbmVec oldov=objvel; // debug
- objvel = vec2L((*pNormals)[n]) *dp;
- */
- }
- }
- }
-
- if(sds->coll_group)
- go = go->next;
- else
- base= base->next;
- }
- }
}
-void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
+void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
{
if((smd->type & MOD_SMOKE_TYPE_FLOW))
{
@@ -1320,82 +1339,77 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
float light[3];
PointCache *cache = NULL;
PTCacheID pid;
- PointCache *cache_wt = NULL;
- PTCacheID pid_wt;
int startframe, endframe, framenr;
float timescale;
- int cache_result = 0, cache_result_wt = 0;
- int did_init = 0;
framenr = scene->r.cfra;
- printf("time: %d\n", scene->r.cfra);
+ //printf("time: %d\n", scene->r.cfra);
cache = sds->point_cache[0];
BKE_ptcache_id_from_smoke(&pid, ob, smd);
BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
- cache_wt = sds->point_cache[1];
- BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd);
-
- if(!smd->domain->fluid)
+ if(!smd->domain->fluid || framenr == startframe)
{
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED);
+ BKE_ptcache_validate(cache, framenr);
+ cache->flag &= ~PTCACHE_REDO_NEEDED;
}
- if(framenr < startframe)
+ if(!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0)
return;
- if(framenr > endframe)
- return;
+ smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD;
- if(!smd->domain->fluid && (framenr != startframe))
+ CLAMP(framenr, startframe, endframe);
+
+ /* If already viewing a pre/after frame, no need to reload */
+ if ((smd->time == framenr) && (framenr != scene->r.cfra))
return;
// printf("startframe: %d, framenr: %d\n", startframe, framenr);
- if(!(did_init = smokeModifier_init(smd, ob, scene, dm)))
+ if(smokeModifier_init(smd, ob, scene, dm)==0)
{
printf("bad smokeModifier_init\n");
return;
}
/* try to read from cache */
- cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec);
- // printf("cache_result: %d\n", cache_result);
-
- if(cache_result == PTCACHE_READ_EXACT)
- {
+ if(BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) {
BKE_ptcache_validate(cache, framenr);
-
- if(sds->wt)
- {
- cache_result_wt = BKE_ptcache_read_cache(&pid_wt, (float)framenr, scene->r.frs_sec);
-
- if(cache_result_wt == PTCACHE_READ_EXACT)
- {
- BKE_ptcache_validate(cache_wt, framenr);
-
- return;
- }
- else
- {
- ; /* don't return in the case we only got low res cache but no high res cache */
- /* we still need to calculate the high res cache */
- }
- }
- else
- return;
+ smd->time = framenr;
+ return;
}
+
+ /* only calculate something when we advanced a single frame */
+ if(framenr != (int)smd->time+1)
+ return;
- /* only calculate something when we advanced a frame */
- if(framenr == smd->time)
+ /* don't simulate if viewing start frame, but scene frame is not real start frame */
+ if (framenr != scene->r.cfra)
return;
tstart();
smoke_calc_domain(scene, ob, smd);
+
+ /* if on second frame, write cache for first frame */
+ if((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) {
+ // create shadows straight after domain initialization so we get nice shadows for startframe, too
+ if(get_lamp(scene, light))
+ smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx);
+
+ if(sds->wt)
+ {
+ if(sds->flags & MOD_SMOKE_DISSOLVE)
+ smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
+ smoke_turbulence_step(sds->wt, sds->fluid);
+ }
+
+ BKE_ptcache_write(&pid, startframe);
+ }
// set new time
smd->time = scene->r.cfra;
@@ -1412,39 +1426,24 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
smoke_step(sds->fluid, smd->time, scene->r.frs_sec / scene->r.frs_sec_base);
}
- else
- {
- /* Smoke did not load cache and was not reset but we're on startframe */
- /* So now reinit the smoke since it was not done yet */
- if(did_init == 2)
- {
- smokeModifier_reset(smd);
- smokeModifier_init(smd, ob, scene, dm);
- }
- }
- // create shadows before writing cache so we get nice shadows for startframe, too
+ // create shadows before writing cache so they get stored
if(get_lamp(scene, light))
smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx);
-
- BKE_ptcache_validate(cache, framenr);
- BKE_ptcache_write_cache(&pid, framenr);
if(sds->wt)
{
- if(framenr!=startframe)
- {
- if(sds->flags & MOD_SMOKE_DISSOLVE)
- smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
- smoke_turbulence_step(sds->wt, sds->fluid);
- }
-
- BKE_ptcache_validate(cache_wt, framenr);
- BKE_ptcache_write_cache(&pid_wt, framenr);
+ if(sds->flags & MOD_SMOKE_DISSOLVE)
+ smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
+ smoke_turbulence_step(sds->wt, sds->fluid);
}
+
+ BKE_ptcache_validate(cache, framenr);
+ if(framenr != startframe)
+ BKE_ptcache_write(&pid, framenr);
tend();
- printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() );
+ //printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() );
}
}
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index d9cb03be37f..d197541c620 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -63,6 +63,7 @@ variables on the UI for now
#include "DNA_meshdata_types.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_threads.h"
#include "BLI_cellalloc.h"
@@ -161,7 +162,7 @@ typedef struct SB_thread_context {
#define BFF_CLOSEVERT 2 /* collider vertex repulses face */
-float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
+static float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
/* local prototypes */
static void free_softbody_intern(SoftBody *sb);
@@ -172,7 +173,7 @@ static void Vec3PlusStVec(float *v, float s, float *v1);
/*physical unit of force is [kg * m / sec^2]*/
-static float sb_grav_force_scale(Object *ob)
+static float sb_grav_force_scale(Object *UNUSED(ob))
/* since unit of g is [m/sec^2] and F = mass * g we rescale unit mass of node to 1 gramm
put it to a function here, so we can add user options later without touching simulation code
*/
@@ -180,7 +181,7 @@ static float sb_grav_force_scale(Object *ob)
return (0.001f);
}
-static float sb_fric_force_scale(Object *ob)
+static float sb_fric_force_scale(Object *UNUSED(ob))
/* rescaling unit of drag [1 / sec] to somehow reasonable
put it to a function here, so we can add user options later without touching simulation code
*/
@@ -261,7 +262,7 @@ float operations still
/* just an ID here to reduce the prob for killing objects
** ob->sumohandle points to we should not kill :)
*/
-const int CCD_SAVETY = 190561;
+static const int CCD_SAVETY = 190561;
typedef struct ccdf_minmax{
float minx,miny,minz,maxx,maxy,maxz;
@@ -549,7 +550,7 @@ static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *h
}
/*+++ only with deflecting set */
- if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == 0) {
+ if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == NULL) {
DerivedMesh *dm= NULL;
if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */
@@ -679,7 +680,7 @@ static void add_mesh_quad_diag_springs(Object *ob)
}
}
-static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int addsprings)
+static void add_2nd_order_roller(Object *ob,float UNUSED(stiffness), int *counter, int addsprings)
{
/*assume we have a softbody*/
SoftBody *sb= ob->soft; /* is supposed to be there */
@@ -698,12 +699,12 @@ static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int ad
bs = sb->bspring + bp->springs[b-1];
/*nasty thing here that springs have two ends
so here we have to make sure we examine the other */
- if (( v0 == bs->v1) ){
+ if (v0 == bs->v1){
bpo =sb->bpoint+bs->v2;
notthis = bs->v2;
}
else {
- if (( v0 == bs->v2) ){
+ if (v0 == bs->v2){
bpo =sb->bpoint+bs->v1;
notthis = bs->v1;
}
@@ -1030,7 +1031,7 @@ static int query_external_colliders(Scene *scene, Object *me)
/* +++ the aabb "force" section*/
-static int sb_detect_aabb_collisionCached( float force[3], unsigned int par_layer,struct Object *vertexowner,float time)
+static int sb_detect_aabb_collisionCached( float UNUSED(force[3]), unsigned int UNUSED(par_layer),struct Object *vertexowner,float UNUSED(time))
{
Object *ob;
SoftBody *sb=vertexowner->soft;
@@ -1095,7 +1096,7 @@ static int sb_detect_aabb_collisionCached( float force[3], unsigned int par_laye
/* +++ the face external section*/
static int sb_detect_face_pointCached(float face_v1[3],float face_v2[3],float face_v3[3],float *damp,
- float force[3], unsigned int par_layer,struct Object *vertexowner,float time)
+ float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time)
{
Object *ob;
GHash *hash;
@@ -1193,7 +1194,7 @@ static int sb_detect_face_pointCached(float face_v1[3],float face_v2[3],float fa
static int sb_detect_face_collisionCached(float face_v1[3],float face_v2[3],float face_v3[3],float *damp,
- float force[3], unsigned int par_layer,struct Object *vertexowner,float time)
+ float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time)
{
Object *ob;
GHash *hash;
@@ -1419,7 +1420,7 @@ static void scan_for_ext_face_forces(Object *ob,float timenow)
/* +++ the spring external section*/
static int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp,
- float force[3], unsigned int par_layer,struct Object *vertexowner,float time)
+ float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time)
{
Object *ob;
GHash *hash;
@@ -1647,9 +1648,7 @@ static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow)
ListBase *do_effector = NULL;
do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights);
- if (sb){
- _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
- }
+ _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
pdEndEffectors(&do_effector);
}
@@ -1657,10 +1656,10 @@ static void *exec_scan_for_ext_spring_forces(void *data)
{
SB_thread_context *pctx = (SB_thread_context*)data;
_scan_for_ext_spring_forces(pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->do_effector);
- return 0;
+ return NULL;
}
-static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func())
+static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,int totsprings,int *UNUSED(ptr_to_break_func(void)))
{
ListBase *do_effector = NULL;
ListBase threads;
@@ -1750,7 +1749,7 @@ static int choose_winner(float*w, float* pos,float*a,float*b,float*c,float*ca,fl
static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *damp,
- float force[3], unsigned int par_layer,struct Object *vertexowner,
+ float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner,
float time,float vel[3], float *intrusion)
{
Object *ob= NULL;
@@ -2085,7 +2084,7 @@ static void dfdv_goal(int ia, int ic,float factor)
for(i=0;i<3;i++) nlMatrixAdd(ia+i,ic+i,factor);
}
*/
-static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags)
+static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float UNUSED(forcetime), int nl_flags)
{
SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp1,*bp2;
@@ -2176,7 +2175,7 @@ static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float fo
/* since this is definitely the most CPU consuming task here .. try to spread it */
/* core function _softbody_calc_forces_slice_in_a_thread */
/* result is int to be able to flag user break */
-static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow,int ifirst,int ilast,int *ptr_to_break_func(),ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor)
+static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow,int ifirst,int ilast,int *UNUSED(ptr_to_break_func(void)),ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor)
{
float iks;
int bb,do_selfcollision,do_springcollision,do_aero;
@@ -2384,10 +2383,10 @@ static void *exec_softbody_calc_forces(void *data)
{
SB_thread_context *pctx = (SB_thread_context*)data;
_softbody_calc_forces_slice_in_a_thread(pctx->scene, pctx->ob, pctx->forcetime, pctx->timenow, pctx->ifirst, pctx->ilast, NULL, pctx->do_effector,pctx->do_deflector,pctx->fieldfactor,pctx->windfactor);
- return 0;
+ return NULL;
}
-static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow,int totpoint,int *ptr_to_break_func(),struct ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor)
+static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow,int totpoint,int *UNUSED(ptr_to_break_func(void)),struct ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor)
{
ListBase threads;
SB_thread_context *sb_threads;
@@ -2445,7 +2444,7 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
MEM_freeN(sb_threads);
}
-static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow, int nl_flags)
+static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow, int UNUSED(nl_flags))
{
/* rule we never alter free variables :bp->vec bp->pos in here !
* this will ruin adaptive stepsize AKA heun! (BM)
@@ -2453,7 +2452,8 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bproot;
ListBase *do_effector = NULL;
- float iks, gravity;
+ float gravity;
+ /* float iks; */
float fieldfactor = -1.0f, windfactor = 0.25;
int do_deflector,do_selfcollision,do_springcollision,do_aero;
@@ -2465,7 +2465,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
- iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
+ /* iks = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */
bproot= sb->bpoint; /* need this for proper spring addressing */
if (do_springcollision || do_aero)
@@ -3823,7 +3823,7 @@ void SB_estimate_transform(Object *ob,float lloc[3],float lrot[3][3],float lscal
{
BodyPoint *bp;
ReferenceVert *rp;
- SoftBody *sb = 0;
+ SoftBody *sb = NULL;
float (*opos)[3];
float (*rpos)[3];
float com[3],rcom[3];
@@ -4135,7 +4135,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
}
/* try to read from cache */
- cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec);
+ cache_result = BKE_ptcache_read(&pid, framenr);
if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
softbody_to_object(ob, vertexCos, numVerts, sb->local);
@@ -4143,14 +4143,14 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
BKE_ptcache_validate(cache, framenr);
if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_write_cache(&pid, framenr);
+ BKE_ptcache_write(&pid, framenr);
return;
}
else if(cache_result==PTCACHE_READ_OLD) {
; /* do nothing */
}
- else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
+ else if(/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */
/* if baked and nothing in cache, do nothing */
BKE_ptcache_invalidate(cache);
return;
@@ -4158,7 +4158,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
/* if on second frame, write cache for first frame */
if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
- BKE_ptcache_write_cache(&pid, startframe);
+ BKE_ptcache_write(&pid, startframe);
softbody_update_positions(ob, sb, vertexCos, numVerts);
@@ -4171,6 +4171,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
softbody_to_object(ob, vertexCos, numVerts, 0);
BKE_ptcache_validate(cache, framenr);
- BKE_ptcache_write_cache(&pid, framenr);
+ BKE_ptcache_write(&pid, framenr);
}
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 8f3b82643e0..88ca0c33624 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -55,7 +55,7 @@ static void sound_sync_callback(void* data, int mode, float time)
}
#endif
-int sound_define_from_str(char *str)
+int sound_define_from_str(const char *str)
{
if (BLI_strcaseeq(str, "NULL"))
return AUD_NULL_DEVICE;
@@ -74,7 +74,7 @@ void sound_force_device(int device)
force_device = device;
}
-void sound_init_once()
+void sound_init_once(void)
{
AUD_initOnce();
}
@@ -110,15 +110,17 @@ void sound_init(struct Main *bmain)
#ifdef WITH_JACK
AUD_setSyncCallback(sound_sync_callback, bmain);
+#else
+ (void)bmain; /* unused */
#endif
}
-void sound_exit()
+void sound_exit(void)
{
AUD_exit();
}
-struct bSound* sound_new_file(struct Main *bmain, char* filename)
+struct bSound* sound_new_file(struct Main *bmain, const char *filename)
{
bSound* sound = NULL;
@@ -129,7 +131,7 @@ struct bSound* sound_new_file(struct Main *bmain, char* filename)
strcpy(str, filename);
- path = /*bmain ? bmain->name :*/ G.sce;
+ path = /*bmain ? bmain->name :*/ G.main->name;
BLI_path_abs(str, path);
@@ -264,7 +266,7 @@ void sound_load(struct Main *bmain, struct bSound* sound)
if(sound->id.lib)
path = sound->id.lib->filepath;
else
- path = /*bmain ? bmain->name :*/ G.sce;
+ path = bmain->name;
BLI_path_abs(fullpath, path);
@@ -274,7 +276,7 @@ void sound_load(struct Main *bmain, struct bSound* sound)
/* or else load it from disk */
else
sound->handle = AUD_load(fullpath);
- } // XXX
+ }
// XXX unused currently
#if 0
break;
@@ -380,7 +382,7 @@ void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, i
AUD_moveSequencer(scene->sound_scene, handle, startframe / FPS, endframe / FPS, frameskip / FPS);
}
-void sound_start_play_scene(struct Scene *scene)
+static void sound_start_play_scene(struct Scene *scene)
{
scene->sound_scene_handle = AUD_play(scene->sound_scene, 1);
AUD_setLoop(scene->sound_scene_handle, -1);
@@ -433,9 +435,11 @@ void sound_seek_scene(struct bContext *C)
if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
{
- // AUD_XXX TODO: fix scrubbing, it currently doesn't stop playing
if(scene->audio.flag & AUDIO_SYNC)
+ {
+ AUD_seek(scene->sound_scene_handle, CFRA / FPS);
AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS);
+ }
else
AUD_seek(scene->sound_scene_handle, CFRA / FPS);
AUD_resume(scene->sound_scene_handle);
@@ -480,3 +484,12 @@ int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length, flo
return AUD_readSound(limiter, buffer, length);
AUD_unload(limiter);
}
+
+int sound_get_channels(struct bSound* sound)
+{
+ AUD_SoundInfo info;
+
+ info = AUD_getInfo(sound->playback_handle);
+
+ return info.specs.channels;
+}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 7e3b5691177..86e901345c4 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -41,6 +41,13 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_pbvh.h"
+#include "BLI_utildefines.h"
+
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -51,11 +58,6 @@
#include "BKE_tessmesh.h"
#include "BKE_utildefines.h"
-#include "BLI_blenlib.h"
-#include "BLI_edgehash.h"
-#include "BLI_math.h"
-#include "BLI_memarena.h"
-#include "BLI_pbvh.h"
#include "PIL_time.h"
#include "BLI_array.h"
@@ -73,8 +75,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int useSubsurfUv,
DerivedMesh *dm);
-static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
-
///
static void *arena_alloc(CCGAllocatorHDL a, int numBytes) {
@@ -87,13 +87,13 @@ static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSiz
}
return p2;
}
-static void arena_free(CCGAllocatorHDL a, void *ptr) {
+static void arena_free(CCGAllocatorHDL UNUSED(a), void *UNUSED(ptr)) {
}
static void arena_release(CCGAllocatorHDL a) {
BLI_memarena_free(a);
}
-static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int useFlatSubdiv) {
+static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int UNUSED(useFlatSubdiv)) {
CCGMeshIFC ifc;
CCGSubSurf *ccgSS;
@@ -320,7 +320,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
CCGFace **faceMap;
MTFace *tf;
CCGFaceIterator *fi;
- int index, gridSize, gridFaces, edgeSize, totface, x, y, S;
+ int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
MTFace *dmtface = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, n);
MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
@@ -337,7 +337,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
/* get some info from CCGSubSurf */
totface = ccgSubSurf_getNumFaces(uvss);
- edgeSize = ccgSubSurf_getEdgeSize(uvss);
+ /* edgeSize = ccgSubSurf_getEdgeSize(uvss); */ /*UNUSED*/
gridSize = ccgSubSurf_getGridSize(uvss);
gridFaces = gridSize - 1;
@@ -1174,7 +1174,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
/* this edge comes from face data */
int lastface = ccgSubSurf_getNumFaces(ss) - 1;
CCGFace *f;
- int x, y, grid, numVerts;
+ int x, y, grid /*, numVerts*/;
int offset;
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeSize = ccgSubSurf_getEdgeSize(ss);
@@ -1186,7 +1186,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
++i;
f = cgdm->faceMap[i].face;
- numVerts = ccgSubSurf_getFaceNumVerts(f);
+ /* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/
gridSideEdges = gridSize - 1;
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
@@ -1251,7 +1251,7 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
int gridFaces = gridSideEdges * gridSideEdges;
int i;
CCGFace *f;
- int numVerts;
+ /*int numVerts;*/
int offset;
int grid;
int x, y;
@@ -1265,7 +1265,7 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
i = cgdm->reverseFaceMap[faceNum];
f = cgdm->faceMap[i].face;
- numVerts = ccgSubSurf_getFaceNumVerts(f);
+ /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/
offset = faceNum - cgdm->faceMap[i].startFace;
grid = offset / gridFaces;
@@ -1794,7 +1794,23 @@ static void ccgDM_drawVerts(DerivedMesh *dm) {
ccgFaceIterator_free(fi);
glEnd();
}
-static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges) {
+
+static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm)
+{
+ if(ccgdm->pbvh) {
+ CCGFace **faces;
+ int totface;
+
+ BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void***)&faces, &totface);
+ if(totface) {
+ ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
+ ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
+ MEM_freeN(faces);
+ }
+ }
+}
+
+static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int UNUSED(drawAllEdges)) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
@@ -1803,6 +1819,8 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdge
int gridSize = ccgSubSurf_getGridSize(ss);
int useAging;
+ ccgdm_pbvh_update(ccgdm);
+
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
@@ -1893,25 +1911,10 @@ void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
no[1] = b_dZ*a_cX - b_dX*a_cZ;
no[2] = b_dX*a_cY - b_dY*a_cX;
- /* don't normalize, GL_NORMALIZE is be enabled */
+ /* don't normalize, GL_NORMALIZE is enabled */
glNormal3fv(no);
}
-static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm)
-{
- if(ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) {
- CCGFace **faces;
- int totface;
-
- BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void***)&faces, &totface);
- if(totface) {
- ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
- ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
- MEM_freeN(faces);
- }
- }
-}
-
/* Only used by non-editmesh types */
static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int fast, int (*setMaterial)(int, void *attribs)) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
@@ -2006,7 +2009,7 @@ static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
CCGSubSurf *ss = cgdm->ss;
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
GPUVertexAttribs gattribs;
- DMVertexAttribs attribs;
+ DMVertexAttribs attribs= {{{0}}};
MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
@@ -2018,13 +2021,10 @@ static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
ccgdm_pbvh_update(cgdm);
doDraw = 0;
- numVerts = 0;
matnr = -1;
transp = GPU_get_material_blend_mode();
orig_transp = transp;
- memset(&attribs, 0, sizeof(attribs));
-
#define PASSATTRIB(dx, dy, vert) { \
if(attribs.totorco) { \
index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize); \
@@ -2042,7 +2042,7 @@ static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
} \
if(attribs.tottang) { \
float *tang = attribs.tang.array[a*4 + vert]; \
- glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
+ glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \
} \
}
@@ -2070,7 +2070,7 @@ static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
}
- if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) {
+ if(!doDraw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) && !setDrawOptions(userData, origIndex))) {
a += gridFaces*gridFaces*numVerts;
continue;
}
@@ -2268,9 +2268,12 @@ static void cgdm_drawFacesTex_common(DerivedMesh *dm,
if(drawParams)
flag = drawParams(tf, mcol!=NULL, mat_nr);
- else
+ else if (index != ORIGINDEX_NONE)
flag= (drawParamsMapped)? drawParamsMapped(userData, index): 1;
-
+ else
+ flag= GPU_enable_material(mat_nr, NULL) ? 1:0;
+
+
if (flag == 0) { /* flag 0 == the face is hidden or invisible */
if(tf) tf += gridFaces*gridFaces*numVerts;
if(mcol) mcol += gridFaces*gridFaces*numVerts*4;
@@ -2410,7 +2413,7 @@ static void cgdm_drawUVEdges(DerivedMesh *dm)
}
}
-static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) {
+static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs)) {
CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
CCGSubSurf *ss = cgdm->ss;
MCol *mcol= NULL;
@@ -2442,10 +2445,14 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
mcol += gridFaces*gridFaces*numVerts*4;
}
- if (index!=-1) {
- int draw;
- draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, index, &drawSmooth);
-
+ {
+ int draw= 1;
+
+ if(index == ORIGINDEX_NONE)
+ draw= setMaterial(faceFlags ? faceFlags[origIndex*2 + 1] + 1: 1, NULL); /* XXX, no faceFlags no material */
+ else if (setDrawOptions)
+ draw= setDrawOptions(userData, index, &drawSmooth);
+
if (draw) {
if (draw==2) {
glEnable(GL_POLYGON_STIPPLE);
@@ -2846,14 +2853,14 @@ static void ccgdm_create_grids(DerivedMesh *dm)
DMGridAdjacency *gridAdjacency, *adj;
CCGFace **gridFaces;
int *gridOffset;
- int index, numFaces, numGrids, S, gIndex, gridSize;
+ int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
if(cgdm->gridData)
return;
numGrids = ccgDM_getNumGrids(dm);
numFaces = ccgSubSurf_getNumFaces(ss);
- gridSize = ccgDM_getGridSize(dm);
+ /*gridSize = ccgDM_getGridSize(dm);*/ /*UNUSED*/
/* compute offset into grid array for each face */
gridOffset = MEM_mallocN(sizeof(int)*numFaces, "cgdm.gridOffset");
@@ -2939,28 +2946,10 @@ static ListBase *ccgDM_getFaceMap(Object *ob, DerivedMesh *dm)
return ccgdm->fmap;
}
-static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm)
-{
- ModifierData *md;
- MultiresModifierData *mmd= ccgdm->multires.mmd;
-
- /* in sync with sculpt mode, only use multires grid pbvh if we are
- the last enabled modifier in the stack, otherwise we use the base
- mesh */
- if(!mmd)
- return 0;
-
- for(md=mmd->modifier.next; md; md= md->next)
- if(modifier_isEnabled(mmd->modifier.scene, md, eModifierMode_Realtime))
- return 0;
-
- return 1;
-}
-
static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
- int gridSize, numGrids, grid_pbvh;
+ int gridSize, numGrids;
if(!ob) {
ccgdm->pbvh= NULL;
@@ -2970,20 +2959,15 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
if(!ob->sculpt)
return NULL;
- grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
-
if(ob->sculpt->pbvh) {
- if(grid_pbvh) {
- /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
- but this can be freed on ccgdm release, this updates the pointers
- when the ccgdm gets remade, the assumption is that the topology
- does not change. */
- ccgdm_create_grids(dm);
- BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void**)ccgdm->gridFaces);
- }
+ /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
+ but this can be freed on ccgdm release, this updates the pointers
+ when the ccgdm gets remade, the assumption is that the topology
+ does not change. */
+ ccgdm_create_grids(dm);
+ BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void**)ccgdm->gridFaces);
ccgdm->pbvh = ob->sculpt->pbvh;
- ccgdm->pbvh_draw = grid_pbvh;
}
if(ccgdm->pbvh)
@@ -2992,25 +2976,14 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
/* no pbvh exists yet, we need to create one. only in case of multires
we build a pbvh over the modified mesh, in other cases the base mesh
is being sculpted, so we build a pbvh from that. */
- if(grid_pbvh) {
- ccgdm_create_grids(dm);
-
- gridSize = ccgDM_getGridSize(dm);
- numGrids = ccgDM_getNumGrids(dm);
+ ccgdm_create_grids(dm);
- ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
- BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
- numGrids, gridSize, (void**)ccgdm->gridFaces);
- ccgdm->pbvh_draw = 1;
- }
- else if(ob->type == OB_MESH) {
- Mesh *me= ob->data;
+ gridSize = ccgDM_getGridSize(dm);
+ numGrids = ccgDM_getNumGrids(dm);
- ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
- BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
- me->totface, me->totvert);
- ccgdm->pbvh_draw = 0;
- }
+ ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
+ BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
+ numGrids, gridSize, (void**)ccgdm->gridFaces);
return ccgdm->pbvh;
}
@@ -3037,17 +3010,16 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int edgeSize, has_edge_origindex;
int gridSize;
int gridFaces, gridCuts;
- int gridSideVerts;
+ /*int gridSideVerts;*/
int gridSideEdges;
int numTex, numCol;
int gridInternalEdges;
- float *w = NULL, one = 1.0f;
+ float *w = NULL;
WeightTable wtable = {0};
MCol *mcol;
MEdge *medge = NULL, medge2;
MFace *mface = NULL;
MPoly *mpoly = NULL;
- int *orig_indices;
DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
ccgSubSurf_getNumFinalVerts(ss),
@@ -3167,7 +3139,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
edgeSize = ccgSubSurf_getEdgeSize(ss);
gridSize = ccgSubSurf_getGridSize(ss);
gridFaces = gridSize - 1;
- gridSideVerts = gridSize - 2;
gridCuts = gridSize - 2;
/*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
gridSideEdges = gridSize - 1;
diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c
index 1b720c1adaa..052b545cfb4 100644
--- a/source/blender/blenkernel/intern/suggestions.c
+++ b/source/blender/blenkernel/intern/suggestions.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -54,7 +54,7 @@ static int txttl_cmp(const char *first, const char *second, int len) {
return cmp;
}
-static void txttl_free_suggest() {
+static void txttl_free_suggest(void) {
SuggItem *item, *prev;
for (item = suggestions.last; item; item=prev) {
prev = item->prev;
@@ -66,7 +66,7 @@ static void txttl_free_suggest() {
suggestions.top = 0;
}
-static void txttl_free_docs() {
+static void txttl_free_docs(void) {
if (documentation) {
MEM_freeN(documentation);
documentation = NULL;
@@ -77,7 +77,7 @@ static void txttl_free_docs() {
/* General tool functions */
/**************************/
-void free_texttools() {
+void free_texttools(void) {
txttl_free_suggest();
txttl_free_docs();
}
@@ -88,7 +88,7 @@ void texttool_text_set_active(Text *text) {
activeToolText = text;
}
-void texttool_text_clear() {
+void texttool_text_clear(void) {
free_texttools();
activeToolText = NULL;
}
@@ -191,15 +191,15 @@ void texttool_suggest_prefix(const char *prefix) {
}
}
-void texttool_suggest_clear() {
+void texttool_suggest_clear(void) {
txttl_free_suggest();
}
-SuggItem *texttool_suggest_first() {
+SuggItem *texttool_suggest_first(void) {
return suggestions.firstmatch;
}
-SuggItem *texttool_suggest_last() {
+SuggItem *texttool_suggest_last(void) {
return suggestions.lastmatch;
}
@@ -207,11 +207,11 @@ void texttool_suggest_select(SuggItem *sel) {
suggestions.selected = sel;
}
-SuggItem *texttool_suggest_selected() {
+SuggItem *texttool_suggest_selected(void) {
return suggestions.selected;
}
-int *texttool_suggest_top() {
+int *texttool_suggest_top(void) {
return &suggestions.top;
}
@@ -243,10 +243,10 @@ void texttool_docs_show(const char *docs) {
documentation[len] = '\0';
}
-char *texttool_docs_get() {
+char *texttool_docs_get(void) {
return documentation;
}
-void texttool_docs_clear() {
+void texttool_docs_clear(void) {
txttl_free_docs();
}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 19bc853276a..1bd41c7aa86 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -36,6 +36,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "DNA_constraint_types.h"
#include "DNA_controller_types.h"
@@ -51,9 +52,9 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_text.h"
-#include "BKE_utildefines.h"
-#ifndef DISABLE_PYTHON
+
+#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -93,7 +94,7 @@ TMARK_EDITALL is set the group ID defines which other markers should be edited.
The mrk->clr field is used to visually group markers where the flags may not
match. A template system, for example, may allow editing of repeating tokens
(in one group) but include other marked positions (in another group) all in the
-same template with the same colour.
+same template with the same color.
Undo
--
@@ -167,12 +168,12 @@ void free_text(Text *text)
if(text->name) MEM_freeN(text->name);
MEM_freeN(text->undo_buf);
-#ifndef DISABLE_PYTHON
- if (text->compiled) BPY_free_compiled_text(text);
+#ifdef WITH_PYTHON
+ if (text->compiled) BPY_text_free_code(text);
#endif
}
-Text *add_empty_text(char *name)
+Text *add_empty_text(const char *name)
{
Main *bmain= G.main;
Text *ta;
@@ -241,7 +242,7 @@ int reopen_text(Text *text)
if (!text || !text->name) return 0;
BLI_strncpy(str, text->name, FILE_MAXDIR+FILE_MAXFILE);
- BLI_path_abs(str, G.sce);
+ BLI_path_abs(str, G.main->name);
fp= fopen(str, "r");
if(fp==NULL) return 0;
@@ -279,7 +280,6 @@ int reopen_text(Text *text)
text->mtime= st.st_mtime;
text->nlines=0;
- i=0;
llen=0;
for(i=0; i<len; i++) {
if (buffer[i]=='\n') {
@@ -325,7 +325,7 @@ int reopen_text(Text *text)
return 1;
}
-Text *add_text(char *file, const char *relpath)
+Text *add_text(const char *file, const char *relpath)
{
Main *bmain= G.main;
FILE *fp;
@@ -521,7 +521,7 @@ void unlink_text(Main *bmain, Text *text)
}
if(update)
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
/* pynodes */
@@ -559,7 +559,7 @@ void clear_text(Text *text) /* called directly from rna */
txt_make_dirty(text);
}
-void write_text(Text *text, char *str) /* called directly from rna */
+void write_text(Text *text, const char *str) /* called directly from rna */
{
int oldstate;
@@ -585,7 +585,7 @@ static void make_new_line (TextLine *line, char *newline)
line->format= NULL;
}
-static TextLine *txt_new_line(char *str)
+static TextLine *txt_new_line(const char *str)
{
TextLine *tmp;
@@ -683,8 +683,8 @@ int txt_get_span (TextLine *from, TextLine *to)
static void txt_make_dirty (Text *text)
{
text->flags |= TXT_ISDIRTY;
-#ifndef DISABLE_PYTHON
- if (text->compiled) BPY_free_compiled_text(text);
+#ifdef WITH_PYTHON
+ if (text->compiled) BPY_text_free_code(text);
#endif
}
@@ -991,8 +991,8 @@ void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel)
if ((*linep)->next) *linep= (*linep)->next;
else break;
}
- if (ch>(*linep)->len)
- ch= (*linep)->len;
+ if (ch>(unsigned int)((*linep)->len))
+ ch= (unsigned int)((*linep)->len);
*charp= ch;
if(!sel) txt_pop_sel(text);
@@ -1232,7 +1232,7 @@ int txt_find_string(Text *text, char *findstr, int wrap)
{
TextLine *tl, *startl;
char *s= NULL;
- int oldcl, oldsl, oldcc, oldsc;
+ int oldcl, oldsl;
if (!text || !text->curl || !text->sell) return 0;
@@ -1241,8 +1241,6 @@ int txt_find_string(Text *text, char *findstr, int wrap)
oldcl= txt_get_span(text->lines.first, text->curl);
oldsl= txt_get_span(text->lines.first, text->sell);
tl= startl= text->sell;
- oldcc= text->curc;
- oldsc= text->selc;
s= strstr(&tl->line[text->selc], findstr);
while (!s) {
@@ -1431,7 +1429,7 @@ void txt_print_undo(Text *text)
{
int i= 0;
int op;
- char *ops;
+ const char *ops;
int linep, charp;
dump_buffer(text);
@@ -2219,7 +2217,6 @@ static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
} while (mrk && mrk->lineno==lineno);
}
if (lineno==-1) lineno= txt_get_span(text->lines.first, lineb);
- if (!mrk) mrk= text->markers.first;
tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string");
@@ -2470,7 +2467,7 @@ void indent(Text *text)
int len, num;
char *tmp;
- char *add = "\t";
+ const char *add = "\t";
int indentlen = 1;
/* hardcoded: TXT_TABSIZE = 4 spaces: */
@@ -2531,7 +2528,7 @@ void indent(Text *text)
void unindent(Text *text)
{
int num = 0;
- char *remove = "\t";
+ const char *remove = "\t";
int indent = 1;
/* hardcoded: TXT_TABSIZE = 4 spaces: */
@@ -2694,7 +2691,7 @@ int setcurr_tab_spaces (Text *text, int space)
const char *word = ":";
const char *comm = "#";
const char indent= (text->flags & TXT_TABSTOSPACES) ? ' ' : '\t';
- static char *back_words[]= {"return", "break", "continue", "pass", "yield", NULL};
+ static const char *back_words[]= {"return", "break", "continue", "pass", "yield", NULL};
if (!text) return 0;
if (!text->curl) return 0;
@@ -2710,9 +2707,13 @@ int setcurr_tab_spaces (Text *text, int space)
}
if(strstr(text->curl->line, word))
{
- //if we find a : then add a tab but not if it is in a comment
+ /* if we find a ':' on this line, then add a tab but not if it is:
+ * 1) in a comment
+ * 2) within an identifier
+ * 3) after the cursor (text->curc), i.e. when creating space before a function def [#25414]
+ */
int a, indent = 0;
- for(a=0; text->curl->line[a] != '\0'; a++)
+ for(a=0; (a < text->curc) && (text->curl->line[a] != '\0'); a++)
{
if (text->curl->line[a]=='#') {
break;
@@ -2746,7 +2747,7 @@ int setcurr_tab_spaces (Text *text, int space)
/*********************************/
/* Creates and adds a marker to the list maintaining sorted order */
-void txt_add_marker(Text *text, TextLine *line, int start, int end, char color[4], int group, int flags) {
+void txt_add_marker(Text *text, TextLine *line, int start, int end, const unsigned char color[4], int group, int flags) {
TextMarker *tmp, *marker;
marker= MEM_mallocN(sizeof(TextMarker), "text_marker");
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 77416f4dd12..c22b1d32849 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -38,11 +38,10 @@
#include "PIL_dynlib.h"
-
-
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_kdopbvh.h"
+#include "BLI_utildefines.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
@@ -52,6 +51,7 @@
#include "DNA_brush_types.h"
#include "DNA_node_types.h"
#include "DNA_color_types.h"
+#include "DNA_particle_types.h"
#include "IMB_imbuf.h"
@@ -93,14 +93,14 @@ void open_plugin_tex(PluginTex *pit)
int (*version)(void);
/* init all the happy variables */
- pit->doit= 0;
- pit->pname= 0;
- pit->stnames= 0;
- pit->varstr= 0;
- pit->result= 0;
- pit->cfra= 0;
+ pit->doit= NULL;
+ pit->pname= NULL;
+ pit->stnames= NULL;
+ pit->varstr= NULL;
+ pit->result= NULL;
+ pit->cfra= NULL;
pit->version= 0;
- pit->instance_init= 0;
+ pit->instance_init= NULL;
/* clear the error list */
PIL_dynlib_get_error_as_string(NULL);
@@ -113,12 +113,12 @@ void open_plugin_tex(PluginTex *pit)
pit->handle= PIL_dynlib_open(pit->name);
if(test_dlerr(pit->name, pit->name)) return;
- if (pit->handle != 0) {
+ if (pit->handle != NULL) {
/* find the address of the version function */
version= (int (*)(void)) PIL_dynlib_find_symbol(pit->handle, "plugin_tex_getversion");
if (test_dlerr(pit->name, "plugin_tex_getversion")) return;
- if (version != 0) {
+ if (version != NULL) {
pit->version= version();
if( pit->version >= 2 && pit->version <=6) {
int (*info_func)(PluginInfo *);
@@ -168,8 +168,8 @@ PluginTex *add_plugin_tex(char *str)
strcpy(pit->name, str);
open_plugin_tex(pit);
- if(pit->doit==0) {
- if(pit->handle==0) {;} //XXX error("no plugin: %s", str);
+ if(pit->doit==NULL) {
+ if(pit->handle==NULL) {;} //XXX error("no plugin: %s", str);
else {;} //XXX error("in plugin: %s", str);
MEM_freeN(pit);
return NULL;
@@ -193,7 +193,7 @@ PluginTex *add_plugin_tex(char *str)
void free_plugin_tex(PluginTex *pit)
{
- if(pit==0) return;
+ if(pit==NULL) return;
/* no PIL_dynlib_close: same plugin can be opened multiple times, 1 handle */
MEM_freeN(pit);
@@ -573,6 +573,7 @@ void default_tex(Tex *tex)
tex->iuser.fie_ima= 2;
tex->iuser.ok= 1;
tex->iuser.frames= 100;
+ tex->iuser.sfra= 1;
tex->preview = NULL;
}
@@ -618,7 +619,7 @@ void default_mtex(MTex *mtex)
{
mtex->texco= TEXCO_ORCO;
mtex->mapto= MAP_COL;
- mtex->object= 0;
+ mtex->object= NULL;
mtex->projx= PROJ_X;
mtex->projy= PROJ_Y;
mtex->projz= PROJ_Z;
@@ -629,8 +630,8 @@ void default_mtex(MTex *mtex)
mtex->size[0]= 1.0;
mtex->size[1]= 1.0;
mtex->size[2]= 1.0;
- mtex->tex= 0;
- mtex->texflag= MTEX_NEW_BUMP;
+ mtex->tex= NULL;
+ mtex->texflag= MTEX_3TAP_BUMP | MTEX_BUMP_OBJECTSPACE;
mtex->colormodel= 0;
mtex->r= 1.0;
mtex->g= 0.0;
@@ -671,14 +672,16 @@ void default_mtex(MTex *mtex)
mtex->lifefac= 1.0f;
mtex->sizefac= 1.0f;
mtex->ivelfac= 1.0f;
- mtex->pvelfac= 1.0f;
+ mtex->dampfac= 1.0f;
+ mtex->gravityfac= 1.0f;
+ mtex->fieldfac= 1.0f;
mtex->normapspace= MTEX_NSPACE_TANGENT;
}
/* ------------------------------------------------------------------------- */
-MTex *add_mtex()
+MTex *add_mtex(void)
{
MTex *mtex;
@@ -740,7 +743,7 @@ Tex *copy_texture(Tex *tex)
texn= copy_libblock(tex);
if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima);
- else texn->ima= 0;
+ else texn->ima= NULL;
#if 0 // XXX old animation system
id_us_plus((ID *)texn->ipo);
@@ -760,7 +763,7 @@ Tex *copy_texture(Tex *tex)
if(tex->nodetree) {
ntreeEndExecTree(tex->nodetree);
- texn->nodetree= ntreeCopyTree(tex->nodetree, 0); /* 0 == full new tree */
+ texn->nodetree= ntreeCopyTree(tex->nodetree); /* 0 == full new tree */
}
return texn;
@@ -776,6 +779,7 @@ void make_local_texture(Tex *tex)
World *wrld;
Lamp *la;
Brush *br;
+ ParticleSettings *pa;
int a, local=0, lib=0;
/* - only lib users: do nothing
@@ -783,19 +787,19 @@ void make_local_texture(Tex *tex)
* - mixed: make copy
*/
- if(tex->id.lib==0) return;
+ if(tex->id.lib==NULL) return;
/* special case: ima always local immediately */
if(tex->ima) {
- tex->ima->id.lib= 0;
+ tex->ima->id.lib= NULL;
tex->ima->id.flag= LIB_LOCAL;
- new_id(0, (ID *)tex->ima, 0);
+ new_id(NULL, (ID *)tex->ima, NULL);
}
if(tex->id.us==1) {
- tex->id.lib= 0;
+ tex->id.lib= NULL;
tex->id.flag= LIB_LOCAL;
- new_id(0, (ID *)tex, 0);
+ new_id(NULL, (ID *)tex, NULL);
return;
}
@@ -838,11 +842,21 @@ void make_local_texture(Tex *tex)
}
br= br->id.next;
}
+ pa= bmain->particle.first;
+ while(pa) {
+ for(a=0; a<MAX_MTEX; a++) {
+ if(pa->mtex[a] && pa->mtex[a]->tex==tex) {
+ if(pa->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ pa= pa->id.next;
+ }
if(local && lib==0) {
- tex->id.lib= 0;
+ tex->id.lib= NULL;
tex->id.flag= LIB_LOCAL;
- new_id(0, (ID *)tex, 0);
+ new_id(NULL, (ID *)tex, NULL);
}
else if(local && lib) {
texn= copy_texture(tex);
@@ -852,7 +866,7 @@ void make_local_texture(Tex *tex)
while(ma) {
for(a=0; a<MAX_MTEX; a++) {
if(ma->mtex[a] && ma->mtex[a]->tex==tex) {
- if(ma->id.lib==0) {
+ if(ma->id.lib==NULL) {
ma->mtex[a]->tex= texn;
texn->id.us++;
tex->id.us--;
@@ -865,7 +879,7 @@ void make_local_texture(Tex *tex)
while(la) {
for(a=0; a<MAX_MTEX; a++) {
if(la->mtex[a] && la->mtex[a]->tex==tex) {
- if(la->id.lib==0) {
+ if(la->id.lib==NULL) {
la->mtex[a]->tex= texn;
texn->id.us++;
tex->id.us--;
@@ -878,7 +892,7 @@ void make_local_texture(Tex *tex)
while(wrld) {
for(a=0; a<MAX_MTEX; a++) {
if(wrld->mtex[a] && wrld->mtex[a]->tex==tex) {
- if(wrld->id.lib==0) {
+ if(wrld->id.lib==NULL) {
wrld->mtex[a]->tex= texn;
texn->id.us++;
tex->id.us--;
@@ -890,7 +904,7 @@ void make_local_texture(Tex *tex)
br= bmain->brush.first;
while(br) {
if(br->mtex.tex==tex) {
- if(br->id.lib==0) {
+ if(br->id.lib==NULL) {
br->mtex.tex= texn;
texn->id.us++;
tex->id.us--;
@@ -898,6 +912,19 @@ void make_local_texture(Tex *tex)
}
br= br->id.next;
}
+ pa= bmain->particle.first;
+ while(pa) {
+ for(a=0; a<MAX_MTEX; a++) {
+ if(pa->mtex[a] && pa->mtex[a]->tex==tex) {
+ if(pa->id.lib==NULL) {
+ pa->mtex[a]->tex= texn;
+ texn->id.us++;
+ tex->id.us--;
+ }
+ }
+ }
+ pa= pa->id.next;
+ }
}
}
@@ -940,8 +967,8 @@ Tex *give_current_object_texture(Object *ob)
Material *ma;
Tex *tex= NULL;
- if(ob==0) return 0;
- if(ob->totcol==0 && !(ob->type==OB_LAMP)) return 0;
+ if(ob==NULL) return NULL;
+ if(ob->totcol==0 && !(ob->type==OB_LAMP)) return NULL;
if(ob->type==OB_LAMP) {
tex= give_current_lamp_texture(ob->data);
@@ -1048,6 +1075,10 @@ int give_active_mtex(ID *id, MTex ***mtex_ar, short *act)
*mtex_ar= ((Lamp *)id)->mtex;
if(act) *act= (((Lamp *)id)->texact);
break;
+ case ID_PA:
+ *mtex_ar= ((ParticleSettings *)id)->mtex;
+ if(act) *act= (((ParticleSettings *)id)->texact);
+ break;
default:
*mtex_ar = NULL;
if(act) *act= 0;
@@ -1072,6 +1103,9 @@ void set_active_mtex(ID *id, short act)
case ID_LA:
((Lamp *)id)->texact= act;
break;
+ case ID_PA:
+ ((ParticleSettings *)id)->texact= act;
+ break;
}
}
@@ -1121,7 +1155,7 @@ Tex *give_current_world_texture(World *world)
MTex *mtex= NULL;
Tex *tex= NULL;
- if(!world) return 0;
+ if(!world) return NULL;
mtex= world->mtex[(int)(world->texact)];
if(mtex) tex= mtex->tex;
@@ -1167,6 +1201,42 @@ void set_current_brush_texture(Brush *br, Tex *newtex)
}
}
+Tex *give_current_particle_texture(ParticleSettings *part)
+{
+ MTex *mtex= NULL;
+ Tex *tex= NULL;
+
+ if(!part) return NULL;
+
+ mtex= part->mtex[(int)(part->texact)];
+ if(mtex) tex= mtex->tex;
+
+ return tex;
+}
+
+void set_current_particle_texture(ParticleSettings *part, Tex *newtex)
+{
+ int act= part->texact;
+
+ if(part->mtex[act] && part->mtex[act]->tex)
+ id_us_min(&part->mtex[act]->tex->id);
+
+ if(newtex) {
+ if(!part->mtex[act]) {
+ part->mtex[act]= add_mtex();
+ part->mtex[act]->texco= TEXCO_ORCO;
+ part->mtex[act]->blendtype= MTEX_MUL;
+ }
+
+ part->mtex[act]->tex= newtex;
+ id_us_plus(&newtex->id);
+ }
+ else if(part->mtex[act]) {
+ MEM_freeN(part->mtex[act]);
+ part->mtex[act]= NULL;
+ }
+}
+
/* ------------------------------------------------------------------------- */
EnvMap *BKE_add_envmap(void)
@@ -1285,8 +1355,7 @@ void BKE_free_pointdensity(PointDensity *pd)
void BKE_free_voxeldatadata(struct VoxelData *vd)
{
if (vd->dataset) {
- if(vd->file_format != TEX_VD_SMOKE)
- MEM_freeN(vd->dataset);
+ MEM_freeN(vd->dataset);
vd->dataset = NULL;
}
@@ -1337,13 +1406,11 @@ int BKE_texture_dependsOnTime(const struct Tex *texture)
else if( texture->ima &&
ELEM(texture->ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
return 1;
- }
-#if 0 // XXX old animation system
- else if(texture->ipo) {
- // assume any ipo means the texture is animated
+ }
+ else if(texture->adt) {
+ // assume anything in adt means the texture is animated
return 1;
}
-#endif // XXX old animation system
return 0;
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 133f858e9ea..b071f2c9da5 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -1,4 +1,5 @@
-/**
+/*
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -24,29 +25,59 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
-#ifdef WIN32
-#define _USE_MATH_DEFINES
-#endif
-#include <math.h>
+#include <assert.h>
+#include "BKE_unit.h"
+#include "BLI_math.h"
#include "BLI_winstuff.h"
+
#define TEMP_STR_SIZE 256
#define SEP_CHR '#'
#define SEP_STR "#"
-#define EPS 0.000001
-
+#define EPS 0.00001
+
+#define UN_SC_KM 1000.0f
+#define UN_SC_HM 100.0f
+#define UN_SC_DAM 10.0f
+#define UN_SC_M 1.0f
+#define UN_SC_DM 0.1f
+#define UN_SC_CM 0.01f
+#define UN_SC_MM 0.001f
+#define UN_SC_UM 0.000001f
+
+#define UN_SC_MI 1609.344f
+#define UN_SC_FUR 201.168f
+#define UN_SC_CH 20.1168f
+#define UN_SC_YD 0.9144f
+#define UN_SC_FT 0.3048f
+#define UN_SC_IN 0.0254f
+#define UN_SC_MIL 0.0000254f
+
+#define UN_SC_MTON 1000.0f /* metric ton */
+#define UN_SC_QL 100.0f
+#define UN_SC_KG 1.0f
+#define UN_SC_HG 0.1f
+#define UN_SC_DAG 0.01f
+#define UN_SC_G 0.001f
+
+#define UN_SC_ITON 907.18474f /* imperial ton */
+#define UN_SC_CWT 45.359237f
+#define UN_SC_ST 6.35029318f
+#define UN_SC_LB 0.45359237f
+#define UN_SC_OZ 0.028349523125f
/* define a single unit */
typedef struct bUnitDef {
- char *name;
- char *name_plural; /* abused a bit for the display name */
- char *name_short; /* this is used for display*/
- char *name_alt; /* can be NULL */
+ const char *name;
+ const char *name_plural; /* abused a bit for the display name */
+ const char *name_short; /* this is used for display*/
+ const char *name_alt; /* keyboard-friendly ASCII-only version of name_short, can be NULL */
+ /* if name_short has non-ASCII chars, name_alt should be present */
- char *name_display; /* can be NULL */
+ const char *name_display; /* can be NULL */
double scalar;
double bias; /* not used yet, needed for converting temperature */
@@ -59,7 +90,7 @@ typedef struct bUnitDef {
/* define a single unit */
typedef struct bUnitCollection {
struct bUnitDef *units;
- int base_unit; /* use for 0.0, or none given */
+ int base_unit; /* basic unit index (when user desn't specify unit explicitly) */
int flag; /* options for this system */
int length; /* to quickly find the last item */
} bUnitCollection;
@@ -74,14 +105,14 @@ static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0, sizeof(buDum
/* Lengths */
static struct bUnitDef buMetricLenDef[] = {
- {"kilometer", "kilometers", "km", NULL, "Kilometers", 1000.0, 0.0, B_UNIT_DEF_NONE},
- {"hectometer", "hectometers", "hm", NULL, "100 Meters", 100.0, 0.0, B_UNIT_DEF_SUPPRESS},
- {"dekameter", "dekameters", "dkm",NULL, "10 Meters", 10.0, 0.0, B_UNIT_DEF_SUPPRESS},
- {"meter", "meters", "m", NULL, "Meters", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */
- {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", 0.1, 0.0, B_UNIT_DEF_SUPPRESS},
- {"centimeter", "centimeters", "cm", NULL, "Centimeters", 0.01, 0.0, B_UNIT_DEF_NONE},
- {"millimeter", "millimeters", "mm", NULL, "Millimeters", 0.001, 0.0, B_UNIT_DEF_NONE},
- {"micrometer", "micrometers", "µm", "um", "Micrometers", 0.000001, 0.0, B_UNIT_DEF_NONE}, // micron too?
+ {"kilometer", "kilometers", "km", NULL, "Kilometers", UN_SC_KM, 0.0, B_UNIT_DEF_NONE},
+ {"hectometer", "hectometers", "hm", NULL, "100 Meters", UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"dekameter", "dekameters", "dam",NULL, "10 Meters", UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"meter", "meters", "m", NULL, "Meters", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"centimeter", "centimeters", "cm", NULL, "Centimeters", UN_SC_CM, 0.0, B_UNIT_DEF_NONE},
+ {"millimeter", "millimeters", "mm", NULL, "Millimeters", UN_SC_MM, 0.0, B_UNIT_DEF_NONE},
+ {"micrometer", "micrometers", "µm", "um", "Micrometers", UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, // micron too?
/* These get displayed because of float precision problems in the transform header,
* could work around, but for now probably people wont use these */
@@ -94,17 +125,121 @@ static struct bUnitDef buMetricLenDef[] = {
static struct bUnitCollection buMetricLenCollecton = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef)/sizeof(bUnitDef)};
static struct bUnitDef buImperialLenDef[] = {
- {"mile", "miles", "mi", "m", "Miles", 1609.344, 0.0, B_UNIT_DEF_NONE},
- {"furlong", "furlongs", "fur", NULL, "Furlongs",201.168, 0.0, B_UNIT_DEF_SUPPRESS},
- {"chain", "chains", "ch", NULL, "Chains", 0.9144*22.0, 0.0, B_UNIT_DEF_SUPPRESS},
- {"yard", "yards", "yd", NULL, "Yards", 0.9144, 0.0, B_UNIT_DEF_NONE},
- {"foot", "feet", "'", "ft", "Feet", 0.3048, 0.0, B_UNIT_DEF_NONE},
- {"inch", "inches", "\"", "in", "Inches", 0.0254, 0.0, B_UNIT_DEF_NONE}, /* base unit */
- {"thou", "thous", "mil", NULL, "Thous", 0.0000254, 0.0, B_UNIT_DEF_NONE},
+ {"mile", "miles", "mi", "m", "Miles", UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
+ {"furlong", "furlongs", "fur", NULL, "Furlongs",UN_SC_FUR, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"chain", "chains", "ch", NULL, "Chains", UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"yard", "yards", "yd", NULL, "Yards", UN_SC_YD, 0.0, B_UNIT_DEF_NONE},
+ {"foot", "feet", "'", "ft", "Feet", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"inch", "inches", "\"", "in", "Inches", UN_SC_IN, 0.0, B_UNIT_DEF_NONE},
+ {"thou", "thous", "mil", NULL, "Thous", UN_SC_MIL, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef)/sizeof(bUnitDef)};
+/* Areas */
+static struct bUnitDef buMetricAreaDef[] = {
+ {"square kilometer", "square kilometers", "km²", "km2", "Square Kilometers", UN_SC_KM*UN_SC_KM, 0.0, B_UNIT_DEF_NONE},
+ {"square hectometer","square hectometers", "hm²", "hm2", "Square Hectometers", UN_SC_HM*UN_SC_HM, 0.0, B_UNIT_DEF_NONE}, /* hectare */
+ {"square dekameter", "square dekameters", "dam²","dam2", "Square Dekameters", UN_SC_DAM*UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, /* are */
+ {"square meter", "square meters", "m²", "m2", "Square Meters", UN_SC_M*UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"square decimetre", "square decimetres", "dm²", "dm2", "Square Decimetres", UN_SC_DM*UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"square centimeter", "square centimeters", "cm²", "cm2", "Square Centimeters", UN_SC_CM*UN_SC_CM, 0.0, B_UNIT_DEF_NONE},
+ {"square millimeter", "square millimeters", "mm²", "mm2", "Square Millimeters", UN_SC_MM*UN_SC_MM, 0.0, B_UNIT_DEF_NONE},
+ {"square micrometer", "square micrometers", "µm²", "um2", "Square Micrometers", UN_SC_UM*UN_SC_UM, 0.0, B_UNIT_DEF_NONE},
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buMetricAreaCollecton = {buMetricAreaDef, 3, 0, sizeof(buMetricAreaDef)/sizeof(bUnitDef)};
+
+static struct bUnitDef buImperialAreaDef[] = {
+ {"square mile", "square miles", "sq mi", "sq m","Square Miles", UN_SC_MI*UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
+ {"square furlong", "square furlongs", "sq fur",NULL, "Square Furlongs", UN_SC_FUR*UN_SC_FUR, 0.0,B_UNIT_DEF_SUPPRESS},
+ {"square chain", "square chains", "sq ch", NULL, "Square Chains", UN_SC_CH*UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"square yard", "square yards", "sq yd", NULL, "Square Yards", UN_SC_YD*UN_SC_YD, 0.0, B_UNIT_DEF_NONE},
+ {"square foot", "square feet", "sq ft", NULL, "Square Feet", UN_SC_FT*UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"square inch", "square inches", "sq in", NULL, "Square Inches", UN_SC_IN*UN_SC_IN, 0.0, B_UNIT_DEF_NONE},
+ {"square thou", "square thous", "sq mil",NULL, "Square Thous", UN_SC_MIL*UN_SC_MIL, 0.0, B_UNIT_DEF_NONE},
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buImperialAreaCollecton = {buImperialAreaDef, 4, 0, sizeof(buImperialAreaDef)/sizeof(bUnitDef)};
+
+/* Volumes */
+static struct bUnitDef buMetricVolDef[] = {
+ {"cubic kilometer", "cubic kilometers", "km³", "km3", "Cubic Kilometers", UN_SC_KM*UN_SC_KM*UN_SC_KM, 0.0, B_UNIT_DEF_NONE},
+ {"cubic hectometer","cubic hectometers", "hm³", "hm3", "Cubic Hectometers", UN_SC_HM*UN_SC_HM*UN_SC_HM, 0.0, B_UNIT_DEF_NONE},
+ {"cubic dekameter", "cubic dekameters", "dam³","dam3", "Cubic Dekameters", UN_SC_DAM*UN_SC_DAM*UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"cubic meter", "cubic meters", "m³", "m3", "Cubic Meters", UN_SC_M*UN_SC_M*UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"cubic decimetre", "cubic decimetres", "dm³", "dm3", "Cubic Decimetres", UN_SC_DM*UN_SC_DM*UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"cubic centimeter", "cubic centimeters", "cm³", "cm3", "Cubic Centimeters", UN_SC_CM*UN_SC_CM*UN_SC_CM, 0.0, B_UNIT_DEF_NONE},
+ {"cubic millimeter", "cubic millimeters", "mm³", "mm3", "Cubic Millimeters", UN_SC_MM*UN_SC_MM*UN_SC_MM, 0.0, B_UNIT_DEF_NONE},
+ {"cubic micrometer", "cubic micrometers", "µm³", "um3", "Cubic Micrometers", UN_SC_UM*UN_SC_UM*UN_SC_UM, 0.0, B_UNIT_DEF_NONE},
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buMetricVolCollecton = {buMetricVolDef, 3, 0, sizeof(buMetricVolDef)/sizeof(bUnitDef)};
+
+static struct bUnitDef buImperialVolDef[] = {
+ {"cubic mile", "cubic miles", "cu mi", "cu m","Cubic Miles", UN_SC_MI*UN_SC_MI*UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
+ {"cubic furlong", "cubic furlongs", "cu fur",NULL, "Cubic Furlongs", UN_SC_FUR*UN_SC_FUR*UN_SC_FUR, 0.0,B_UNIT_DEF_SUPPRESS},
+ {"cubic chain", "cubic chains", "cu ch", NULL, "Cubic Chains", UN_SC_CH*UN_SC_CH*UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"cubic yard", "cubic yards", "cu yd", NULL, "Cubic Yards", UN_SC_YD*UN_SC_YD*UN_SC_YD, 0.0, B_UNIT_DEF_NONE},
+ {"cubic foot", "cubic feet", "cu ft", NULL, "Cubic Feet", UN_SC_FT*UN_SC_FT*UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"cubic inch", "cubic inches", "cu in", NULL, "Cubic Inches", UN_SC_IN*UN_SC_IN*UN_SC_IN, 0.0, B_UNIT_DEF_NONE},
+ {"cubic thou", "cubic thous", "cu mil",NULL, "Cubic Thous", UN_SC_MIL*UN_SC_MIL*UN_SC_MIL, 0.0, B_UNIT_DEF_NONE},
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buImperialVolCollecton = {buImperialVolDef, 4, 0, sizeof(buImperialVolDef)/sizeof(bUnitDef)};
+
+/* Mass */
+static struct bUnitDef buMetricMassDef[] = {
+ {"ton", "tonnes", "ton", "t", "1000 Kilograms", UN_SC_MTON, 0.0, B_UNIT_DEF_NONE},
+ {"quintal", "quintals", "ql", "q", "100 Kilograms", UN_SC_QL, 0.0, B_UNIT_DEF_NONE},
+ {"kilogram", "kilograms", "kg", NULL, "Kilograms", UN_SC_KG, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"hectogram", "hectograms", "hg", NULL, "Hectograms", UN_SC_HG, 0.0, B_UNIT_DEF_NONE},
+ {"dekagram", "dekagrams", "dag",NULL, "10 Grams", UN_SC_DAG, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"gram", "grams", "g", NULL, "Grams", UN_SC_G, 0.0, B_UNIT_DEF_NONE},
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buMetricMassCollecton = {buMetricMassDef, 2, 0, sizeof(buMetricMassDef)/sizeof(bUnitDef)};
+
+static struct bUnitDef buImperialMassDef[] = {
+ {"ton", "tonnes", "ton", "t", "Tonnes", UN_SC_ITON, 0.0, B_UNIT_DEF_NONE},
+ {"centum weight", "centum weights", "cwt", NULL, "Centum weights", UN_SC_CWT, 0.0, B_UNIT_DEF_NONE},
+ {"stone", "stones", "st", NULL, "Stones", UN_SC_ST, 0.0, B_UNIT_DEF_NONE},
+ {"pound", "pounds", "lb", NULL, "Pounds", UN_SC_LB, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"ounce", "ounces", "oz", NULL, "Ounces", UN_SC_OZ, 0.0, B_UNIT_DEF_NONE},
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buImperialMassCollecton = {buImperialMassDef, 3, 0, sizeof(buImperialMassDef)/sizeof(bUnitDef)};
+
+/* Even if user scales the system to a point where km^3 is used, velocity and
+ * acceleration aren't scaled: that's why we have so few units for them */
+
+/* Velocity */
+static struct bUnitDef buMetricVelDef[] = {
+ {"meter per second", "meters per second", "m/s", NULL, "Meters per second", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"kilometer per hour", "kilometers per hour", "km/h", NULL, "Kilometers per hour", UN_SC_KM/3600.0f, 0.0, B_UNIT_DEF_SUPPRESS},
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buMetricVelCollecton = {buMetricVelDef, 0, 0, sizeof(buMetricVelDef)/sizeof(bUnitDef)};
+
+static struct bUnitDef buImperialVelDef[] = {
+ {"foot per second", "feet per second", "ft/s", "fps", "Feet per second", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"mile per hour", "miles per hour", "mph", NULL, "Miles per hour", UN_SC_MI/3600.0f, 0.0,B_UNIT_DEF_SUPPRESS},
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buImperialVelCollecton = {buImperialVelDef, 0, 0, sizeof(buImperialVelDef)/sizeof(bUnitDef)};
+
+/* Acceleration */
+static struct bUnitDef buMetricAclDef[] = {
+ {"meter per second squared", "meters per second squared", "m/s²", "m/s2", "Meters per second squared", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buMetricAclCollecton = {buMetricAclDef, 0, 0, sizeof(buMetricAclDef)/sizeof(bUnitDef)};
+
+static struct bUnitDef buImperialAclDef[] = {
+ {"foot per second squared", "feet per second squared", "ft/s²", "ft/s2", "Feet per second squared", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buImperialAclCollecton = {buImperialAclDef, 0, 0, sizeof(buImperialAclDef)/sizeof(bUnitDef)};
/* Time */
static struct bUnitDef buNaturalTimeDef[] = {
@@ -114,7 +249,7 @@ static struct bUnitDef buNaturalTimeDef[] = {
{"minute", "minutes", "min", "m", "Minutes", 60.0, 0.0, B_UNIT_DEF_NONE},
{"second", "seconds", "sec", "s", "Seconds", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{"millisecond", "milliseconds", "ms", NULL, "Milliseconds", 0.001, 0.0 , B_UNIT_DEF_NONE},
- {"microsecond", "microseconds", "us", NULL, "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE},
+ {"microsecond", "microseconds", "µs", "us", "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef)/sizeof(bUnitDef)};
@@ -122,21 +257,26 @@ static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0,
static struct bUnitDef buNaturalRotDef[] = {
{"degree", "degrees", "°", NULL, "Degrees", M_PI/180.0, 0.0, B_UNIT_DEF_NONE},
+// {"radian", "radians", "r", NULL, "Radians", 1.0, 0.0, B_UNIT_DEF_NONE},
+// {"turn", "turns", "t", NULL, "Turns", 1.0/(M_PI*2.0), 0.0,B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
static struct bUnitCollection buNaturalRotCollection = {buNaturalRotDef, 0, 0, sizeof(buNaturalRotDef)/sizeof(bUnitDef)};
-#define UNIT_SYSTEM_MAX 3
-static struct bUnitCollection *bUnitSystems[][8] = {
- {0,0,0,0,0,&buNaturalRotCollection,&buNaturalTimeCollecton,0},
- {0,&buMetricLenCollecton, 0,0,0, &buNaturalRotCollection, &buNaturalTimeCollecton,0}, /* metric */
- {0,&buImperialLenCollecton, 0,0,0,&buNaturalRotCollection, &buNaturalTimeCollecton,0}, /* imperial */
- {0,0,0,0,0,0,0,0}
+#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / 9) / sizeof(void *)) - 1)
+static struct bUnitCollection *bUnitSystems[][9] = {
+ {NULL, NULL, NULL, NULL, NULL, &buNaturalRotCollection, &buNaturalTimeCollecton, NULL, NULL},
+ {NULL, &buMetricLenCollecton, &buMetricAreaCollecton, &buMetricVolCollecton, &buMetricMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buMetricVelCollecton, &buMetricAclCollecton}, /* metric */
+ {NULL, &buImperialLenCollecton, &buImperialAreaCollecton, &buImperialVolCollecton, &buImperialMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buImperialVelCollecton, &buImperialAclCollecton}, /* imperial */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};
+
+
/* internal, has some option not exposed */
static bUnitCollection *unit_get_system(int system, int type)
{
+ assert((system > -1) && (system < UNIT_SYSTEM_TOT) && (type > -1) && (type < B_UNIT_TYPE_TOT));
return bUnitSystems[system][type]; /* select system to use, metric/imperial/other? */
}
@@ -199,7 +339,8 @@ static int unit_as_string(char *str, int len_max, double value, int prec, bUnitC
/* Convert to a string */
{
- char conv_str[6] = {'%', '.', '0'+prec, 'l', 'f', '\0'}; /* "%.2lf" when prec is 2, must be under 10 */
+ char conv_str[6] = {'%', '.', '0', 'l', 'f', '\0'}; /* "%.2lf" when prec is 2, must be under 10 */
+ conv_str[2] += prec;
len= snprintf(str, len_max, conv_str, (float)value_conv);
if(len >= len_max)
@@ -256,9 +397,9 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system,
if(usys==NULL || usys->units[0].name==NULL)
usys= &buDummyCollecton;
-
- if(split) {
- int i;
+
+ /* split output makes sense only for length, mass and time */
+ if(split && (type==B_UNIT_LENGTH || type==B_UNIT_MASS || type==B_UNIT_TIME)) {
bUnitDef *unit_a, *unit_b;
double value_a, value_b;
@@ -266,7 +407,7 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system,
/* check the 2 is a smaller unit */
if(unit_b > unit_a) {
- i= unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0');
+ int i= unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0');
/* is there enough space for at least 1 char of the next unit? */
if(i+2 < len_max) {
@@ -283,7 +424,7 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system,
}
-static char *unit_find_str(char *str, char *substr)
+static char *unit_find_str(char *str, const char *substr)
{
char *str_found;
@@ -338,7 +479,7 @@ static int ch_is_op(char op)
}
}
-static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit, char *replace_str)
+static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit, const char *replace_str)
{
char *str_found;
@@ -443,10 +584,6 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre
for(unit= usys->units; unit->name; unit++) {
-
- if(unit->flag & B_UNIT_DEF_SUPPRESS)
- continue;
-
/* incase there are multiple instances */
while(unit_replace(str, len_max, str_tmp, scale_pref, unit))
change= 1;
@@ -458,18 +595,15 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre
bUnitCollection *usys_iter;
int system_iter;
- for(system_iter= 0; system_iter<UNIT_SYSTEM_MAX; system_iter++) {
+ for(system_iter= 0; system_iter<UNIT_SYSTEM_TOT; system_iter++) {
if (system_iter != system) {
usys_iter= unit_get_system(system_iter, type);
if (usys_iter) {
for(unit= usys_iter->units; unit->name; unit++) {
-
- if((unit->flag & B_UNIT_DEF_SUPPRESS) == 0) {
- int ofs = 0;
- /* incase there are multiple instances */
- while((ofs=unit_replace(str+ofs, len_max-ofs, str_tmp, scale_pref, unit)))
- change= 1;
- }
+ int ofs = 0;
+ /* incase there are multiple instances */
+ while((ofs=unit_replace(str+ofs, len_max-ofs, str_tmp, scale_pref, unit)))
+ change= 1;
}
}
}
@@ -482,10 +616,6 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre
if(str_prev) {
/* see which units the original value had */
for(unit= usys->units; unit->name; unit++) {
-
- if(unit->flag & B_UNIT_DEF_SUPPRESS)
- continue;
-
if (unit_find(str_prev, unit))
break;
}
@@ -543,6 +673,49 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre
return change;
}
+/* 45µm --> 45um */
+void bUnit_ToUnitAltName(char *str, int len_max, char *orig_str, int system, int type)
+{
+ bUnitCollection *usys = unit_get_system(system, type);
+
+ bUnitDef *unit;
+ bUnitDef *unit_def= unit_default(usys);
+
+ /* find and substitute all units */
+ for(unit= usys->units; unit->name; unit++) {
+ if(len_max > 0 && (unit->name_alt || unit == unit_def))
+ {
+ char *found= NULL;
+
+ found= unit_find_str(orig_str, unit->name_short);
+ if(found) {
+ int offset= (int)(found - orig_str);
+ int len_name= 0;
+
+ /* copy everything before the unit */
+ offset= (offset<len_max? offset: len_max);
+ strncpy(str, orig_str, offset);
+
+ str+= offset;
+ orig_str+= offset + strlen(unit->name_short);
+ len_max-= offset;
+
+ /* print the alt_name */
+ if(unit->name_alt)
+ len_name= snprintf(str, len_max, "%s", unit->name_alt);
+ else
+ len_name= 0;
+
+ len_name= (len_name<len_max? len_name: len_max);
+ str+= len_name;
+ len_max-= len_name;
+ }
+ }
+ }
+
+ /* finally copy the rest of the string */
+ strncpy(str, orig_str, len_max);
+}
double bUnit_ClosestScalar(double value, int system, int type)
{
@@ -566,6 +739,12 @@ double bUnit_BaseScalar(int system, int type)
}
/* external access */
+int bUnit_IsValid(int system, int type)
+{
+ return !(system < 0 || system > UNIT_SYSTEM_TOT || type < 0 || type > B_UNIT_TYPE_TOT);
+}
+
+
void bUnit_GetSystem(void **usys_pt, int *len, int system, int type)
{
bUnitCollection *usys = unit_get_system(system, type);
@@ -579,11 +758,16 @@ void bUnit_GetSystem(void **usys_pt, int *len, int system, int type)
*len= usys->length;
}
-char *bUnit_GetName(void *usys_pt, int index)
+int bUnit_GetBaseUnit(void *usys_pt)
+{
+ return ((bUnitCollection *)usys_pt)->base_unit;
+}
+
+const char *bUnit_GetName(void *usys_pt, int index)
{
return ((bUnitCollection *)usys_pt)->units[index].name;
}
-char *bUnit_GetNameDisplay(void *usys_pt, int index)
+const char *bUnit_GetNameDisplay(void *usys_pt, int index)
{
return ((bUnitCollection *)usys_pt)->units[index].name_display;
}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 42df92443f3..5412e44f0eb 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -38,6 +38,7 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
+#include "BKE_world.h"
#include "BKE_library.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
@@ -63,7 +64,7 @@ void free_world(World *wrld)
}
-World *add_world(char *name)
+World *add_world(const char *name)
{
Main *bmain= G.main;
World *wrld;
@@ -136,11 +137,11 @@ void make_local_world(World *wrld)
* - mixed: make copy
*/
- if(wrld->id.lib==0) return;
+ if(wrld->id.lib==NULL) return;
if(wrld->id.us==1) {
- wrld->id.lib= 0;
+ wrld->id.lib= NULL;
wrld->id.flag= LIB_LOCAL;
- new_id(0, (ID *)wrld, 0);
+ new_id(NULL, (ID *)wrld, NULL);
return;
}
@@ -156,7 +157,7 @@ void make_local_world(World *wrld)
if(local && lib==0) {
wrld->id.lib= 0;
wrld->id.flag= LIB_LOCAL;
- new_id(0, (ID *)wrld, 0);
+ new_id(NULL, (ID *)wrld, NULL);
}
else if(local && lib) {
wrldn= copy_world(wrld);
@@ -165,7 +166,7 @@ void make_local_world(World *wrld)
sce= bmain->scene.first;
while(sce) {
if(sce->world==wrld) {
- if(sce->id.lib==0) {
+ if(sce->id.lib==NULL) {
sce->world= wrldn;
wrldn->id.us++;
wrld->id.us--;
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index 00614ef0f4f..1c1febf2609 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -1,4 +1,4 @@
-/**
+/*
* Functions for writing avi-format files.
* Added interface for generic movie support (ton)
*
@@ -38,10 +38,12 @@
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_report.h"
-#include "BKE_utildefines.h"
+
#include "BKE_writeavi.h"
#include "AVI_avi.h"
@@ -119,7 +121,7 @@ static void filepath_avi (char *string, RenderData *rd)
if (string==NULL) return;
strcpy(string, rd->pic);
- BLI_path_abs(string, G.sce);
+ BLI_path_abs(string, G.main->name);
BLI_make_existing_file(string);
@@ -137,6 +139,8 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL
int quality;
double framerate;
+ (void)scene; /* unused */
+
filepath_avi(name, rd);
sframe = (rd->sfra);
@@ -175,7 +179,7 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL
return 1;
}
-static int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports)
+static int append_avi(RenderData *UNUSED(rd), int frame, int *pixels, int rectx, int recty, ReportList *UNUSED(reports))
{
unsigned int *rt1, *rt2, *rectot;
int x, y;
@@ -210,7 +214,7 @@ static int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int rec
return 1;
}
-void end_avi(void)
+static void end_avi(void)
{
if (avi == NULL) return;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 8ebf98ef930..f3b759113ff 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -1,4 +1,6 @@
/*
+ * $Id$
+ *
* ffmpeg-write support
*
* Partial Copyright (c) 2006 Peter Schlaile
@@ -19,7 +21,7 @@
#include <string.h>
#include <stdio.h>
-#if defined(_WIN32) && defined(_DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+#if defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__)
/* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */
#if _MSC_VER < 1400
#include <stdint.h>
@@ -69,7 +71,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-extern void do_init_ffmpeg();
+extern void do_init_ffmpeg(void);
static int ffmpeg_type = 0;
static int ffmpeg_codec = CODEC_ID_MPEG4;
@@ -160,7 +162,7 @@ static int write_audio_frame(void)
pkt.stream_index = audio_stream->index;
pkt.flags |= PKT_FLAG_KEY;
if (av_interleaved_write_frame(outfile, &pkt) != 0) {
- // XXX error("Error writing audio packet");
+ fprintf(stderr, "Error writing audio packet!\n");
return -1;
}
return 0;
@@ -290,7 +292,9 @@ static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports
packet.data = video_buffer;
packet.size = outsize;
ret = av_interleaved_write_frame(outfile, &packet);
- } else ret = 0;
+ } else {
+ ret = 0;
+ }
if (ret != 0) {
success= 0;
@@ -515,6 +519,7 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
if (codec_id == CODEC_ID_XVID) {
/* arghhhh ... */
c->pix_fmt = PIX_FMT_YUV420P;
+ c->codec_tag = (('D'<<24) + ('I'<<16) + ('V'<<8) + 'X');
}
if (codec_id == CODEC_ID_H264) {
@@ -777,6 +782,69 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
return 1;
}
+/**
+ * Writes any delayed frames in the encoder. This function is called before
+ * closing the encoder.
+ *
+ * <p>
+ * Since an encoder may use both past and future frames to predict
+ * inter-frames (H.264 B-frames, for example), it can output the frames
+ * in a different order from the one it was given.
+ * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write
+ * them in the order 1, 4, 2, 3 - first the two frames used for predition,
+ * and then the bidirectionally-predicted frames. What this means in practice
+ * is that the encoder may not immediately produce one output frame for each
+ * input frame. These delayed frames must be flushed before we close the
+ * stream. We do this by calling avcodec_encode_video with NULL for the last
+ * parameter.
+ * </p>
+ */
+void flush_ffmpeg(void)
+{
+ int outsize = 0;
+ int ret = 0;
+
+ AVCodecContext* c = get_codec_from_stream(video_stream);
+ /* get the delayed frames */
+ while (1) {
+ AVPacket packet;
+ av_init_packet(&packet);
+
+ outsize = avcodec_encode_video(c, video_buffer, video_buffersize, NULL);
+ if (outsize < 0) {
+ fprintf(stderr, "Error encoding delayed frame %d\n", outsize);
+ break;
+ }
+ if (outsize == 0) {
+ break;
+ }
+ if (c->coded_frame->pts != AV_NOPTS_VALUE) {
+#ifdef FFMPEG_CODEC_TIME_BASE
+ packet.pts = av_rescale_q(c->coded_frame->pts,
+ c->time_base,
+ video_stream->time_base);
+#else
+ packet.pts = c->coded_frame->pts;
+#endif
+ fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
+ } else {
+ fprintf(stderr, "Video Frame PTS: not set\n");
+ }
+ if (c->coded_frame->key_frame) {
+ packet.flags |= PKT_FLAG_KEY;
+ }
+ packet.stream_index = video_stream->index;
+ packet.data = video_buffer;
+ packet.size = outsize;
+ ret = av_interleaved_write_frame(outfile, &packet);
+ if (ret != 0) {
+ fprintf(stderr, "Error writing delayed frame %d\n", ret);
+ break;
+ }
+ }
+ avcodec_flush_buffers(get_codec_from_stream(video_stream));
+}
+
/* **********************************************************************
* public interface
********************************************************************** */
@@ -791,7 +859,7 @@ void filepath_ffmpeg(char* string, RenderData* rd) {
if (!string || !exts) return;
strcpy(string, rd->pic);
- BLI_path_abs(string, G.sce);
+ BLI_path_abs(string, G.main->name);
BLI_make_existing_file(string);
@@ -887,10 +955,9 @@ int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty,
return success;
}
-
void end_ffmpeg(void)
{
- int i;
+ unsigned int i;
fprintf(stderr, "Closing ffmpeg...\n");
@@ -904,6 +971,11 @@ void end_ffmpeg(void)
audio_mixdown_device = 0;
}
+ if (video_stream && get_codec_from_stream(video_stream)) {
+ fprintf(stderr, "Flushing delayed frames...\n");
+ flush_ffmpeg ();
+ }
+
if (outfile) {
av_write_trailer(outfile);
}
@@ -912,8 +984,8 @@ void end_ffmpeg(void)
if (video_stream && get_codec_from_stream(video_stream)) {
avcodec_close(get_codec_from_stream(video_stream));
- video_stream = 0;
printf("zero video stream %p\n", video_stream);
+ video_stream = 0;
}
@@ -988,6 +1060,8 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int
IDPropertyTemplate val;
int idp_type;
char name[256];
+
+ val.i = 0;
avcodec_get_context_defaults(&c);
@@ -995,8 +1069,6 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int
parent = c.av_class->option + parent_index;
if (!rd->ffcodecdata.properties) {
- IDPropertyTemplate val;
-
rd->ffcodecdata.properties
= IDP_New(IDP_GROUP, val, "ffmpeg");
}
@@ -1005,8 +1077,6 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int
rd->ffcodecdata.properties, (char*) type);
if (!group) {
- IDPropertyTemplate val;
-
group = IDP_New(IDP_GROUP, val, (char*) type);
IDP_AddToGroup(rd->ffcodecdata.properties, group);
}
@@ -1194,20 +1264,47 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
rd->ffcodecdata.mux_packet_size = 2048;
rd->ffcodecdata.mux_rate = 10080000;
+ /*
+ * All options here are for x264, but must be set via ffmpeg.
+ * The names are therefore different - Search for "x264 to FFmpeg option mapping"
+ * to get a list.
+ */
+
+ /*
+ * Use CABAC coder. Using "coder:1", which should be equivalent,
+ * crashes Blender for some reason. Either way - this is no big deal.
+ */
ffmpeg_property_add_string(rd, "video", "coder:vlc");
+
+ /*
+ * The other options were taken from the libx264-default.preset
+ * included in the ffmpeg distribution.
+ */
ffmpeg_property_add_string(rd, "video", "flags:loop");
ffmpeg_property_add_string(rd, "video", "cmp:chroma");
ffmpeg_property_add_string(rd, "video", "partitions:parti4x4");
ffmpeg_property_add_string(rd, "video", "partitions:partp8x8");
ffmpeg_property_add_string(rd, "video", "partitions:partb8x8");
ffmpeg_property_add_string(rd, "video", "me:hex");
- ffmpeg_property_add_string(rd, "video", "subq:5");
+ ffmpeg_property_add_string(rd, "video", "subq:6");
ffmpeg_property_add_string(rd, "video", "me_range:16");
+ ffmpeg_property_add_string(rd, "video", "qdiff:4");
ffmpeg_property_add_string(rd, "video", "keyint_min:25");
ffmpeg_property_add_string(rd, "video", "sc_threshold:40");
ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71");
ffmpeg_property_add_string(rd, "video", "b_strategy:1");
-
+ ffmpeg_property_add_string(rd, "video", "bf:3");
+ ffmpeg_property_add_string(rd, "video", "refs:2");
+ ffmpeg_property_add_string(rd, "video", "qcomp:0.6");
+ ffmpeg_property_add_string(rd, "video", "directpred:3");
+ ffmpeg_property_add_string(rd, "video", "trellis:0");
+ ffmpeg_property_add_string(rd, "video", "flags2:wpred");
+ ffmpeg_property_add_string(rd, "video", "flags2:dct8x8");
+ ffmpeg_property_add_string(rd, "video", "flags2:fastpskip");
+ ffmpeg_property_add_string(rd, "video", "wpredp:2");
+
+ // This makes x264 output lossless. Will be a separate option later.
+ //ffmpeg_property_add_string(rd, "video", "cqp:0");
break;
case FFMPEG_PRESET_THEORA:
diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c
index b0c05c31fa1..3cb3d7e038b 100644
--- a/source/blender/blenkernel/intern/writeframeserver.c
+++ b/source/blender/blenkernel/intern/writeframeserver.c
@@ -47,10 +47,12 @@
#include "DNA_userdef_types.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_writeframeserver.h"
#include "BKE_global.h"
#include "BKE_report.h"
-
#include "DNA_scene_types.h"
static int sock;
@@ -61,31 +63,31 @@ static int render_height;
#if defined(_WIN32)
-static int startup_socket_system()
+static int startup_socket_system(void)
{
WSADATA wsa;
return (WSAStartup(MAKEWORD(2,0),&wsa) == 0);
}
-static void shutdown_socket_system()
+static void shutdown_socket_system(void)
{
WSACleanup();
}
-static int select_was_interrupted_by_signal()
+static int select_was_interrupted_by_signal(void)
{
return (WSAGetLastError() == WSAEINTR);
}
#else
-static int startup_socket_system()
+static int startup_socket_system(void)
{
return 1;
}
-static void shutdown_socket_system()
+static void shutdown_socket_system(void)
{
}
-static int select_was_interrupted_by_signal()
+static int select_was_interrupted_by_signal(void)
{
return (errno == EINTR);
}
@@ -96,10 +98,12 @@ static int closesocket(int fd)
}
#endif
-int start_frameserver(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
+int start_frameserver(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports)
{
struct sockaddr_in addr;
int arg = 1;
+
+ (void)scene; /* unused */
if (!startup_socket_system()) {
BKE_report(reports, RPT_ERROR, "Can't startup socket system");
@@ -243,7 +247,7 @@ static int handle_request(RenderData *rd, char * req)
return -1;
}
-int frameserver_loop(RenderData *rd, ReportList *reports)
+int frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
{
fd_set readfds;
struct timeval tv;
@@ -350,7 +354,7 @@ static void serve_ppm(int *pixels, int rectx, int recty)
connsock = -1;
}
-int append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports)
+int append_frameserver(RenderData *UNUSED(rd), int frame, int *pixels, int rectx, int recty, ReportList *UNUSED(reports))
{
fprintf(stderr, "Serving frame: %d\n", frame);
if (write_ppm) {
@@ -364,7 +368,7 @@ int append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int re
return 0;
}
-void end_frameserver()
+void end_frameserver(void)
{
if (connsock != -1) {
closesocket(connsock);