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:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h2
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h98
-rw-r--r--source/blender/blenkernel/BKE_texture.h2
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c122
-rw-r--r--source/blender/blenkernel/intern/anim.c12
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c577
-rw-r--r--source/blender/blenkernel/intern/collision.c221
-rw-r--r--source/blender/blenkernel/intern/customdata.c31
-rw-r--r--source/blender/blenkernel/intern/modifier.c39
-rw-r--r--source/blender/blenkernel/intern/particle.c3
-rw-r--r--source/blender/blenkernel/intern/particle_system.c18
-rw-r--r--source/blender/blenkernel/intern/softbody.c837
-rw-r--r--source/blender/blenkernel/intern/texture.c33
15 files changed, 1648 insertions, 353 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index f61b300f708..7dc10c53e22 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -437,5 +437,7 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb);
/* determines required DerivedMesh data according to view and edit modes */
CustomDataMask get_viewedit_datamask();
+void DM_add_tangent_layer(DerivedMesh *dm);
+
#endif
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index f76cdbc64b7..d951c8401e3 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -41,7 +41,7 @@ struct ListBase;
struct MemFile;
#define BLENDER_VERSION 246
-#define BLENDER_SUBVERSION 0
+#define BLENDER_SUBVERSION 1
#define BLENDER_MINVERSION 245
#define BLENDER_MINSUBVERSION 15
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
new file mode 100644
index 00000000000..dd9ea61f24b
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -0,0 +1,98 @@
+/**
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): André Pinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef BKE_BVHUTILS_H
+#define BKE_BVHUTILS_H
+
+#include "BLI_kdopbvh.h"
+
+/*
+ * This header encapsulates necessary code to buld a BVH
+ */
+
+struct DerivedMesh;
+struct MVert;
+struct MFace;
+
+/*
+ * struct that kepts basic information about a BVHTree build from a mesh
+ */
+typedef struct BVHTreeFromMesh
+{
+ struct BVHTree *tree;
+
+ /* default callbacks to bvh nearest and raycast */
+ BVHTree_NearestPointCallback nearest_callback;
+ BVHTree_RayCastCallback raycast_callback;
+
+ /* Mesh represented on this BVHTree */
+ struct DerivedMesh *mesh;
+
+ /* Vertex array, so that callbacks have instante access to data */
+ struct MVert *vert;
+ struct MFace *face;
+
+ /* radius for raycast */
+ float sphere_radius;
+
+} BVHTreeFromMesh;
+
+/*
+ * Builds a bvh tree where nodes are the vertexs of the given mesh.
+ * Configures BVHTreeFromMesh.
+ *
+ * The tree is build in mesh space coordinates, this means special care must be made on queries
+ * so that the coordinates and rays are first translated on the mesh local coordinates.
+ * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becames possible to reuse
+ * a BVHTree.
+ *
+ * free_bvhtree_from_mesh should be called when the tree is no longer needed.
+ */
+void bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+
+/*
+ * Builds a bvh tree where nodes are the faces of the given mesh.
+ * Configures BVHTreeFromMesh.
+ *
+ * The tree is build in mesh space coordinates, this means special care must be made on queries
+ * so that the coordinates and rays are first translated on the mesh local coordinates.
+ * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becames possible to reuse
+ * a BVHTree.
+ *
+ * free_bvhtree_from_mesh should be called when the tree is no longer needed.
+ */
+void bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+
+/*
+ * Frees data allocated by a call to bvhtree_from_mesh_*.
+ */
+void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data);
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 78a8f60caeb..c162a04e055 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -62,6 +62,7 @@ struct Tex *copy_texture(struct Tex *tex);
void make_local_texture(struct Tex *tex);
void autotexname(struct Tex *tex);
struct Tex *give_current_texture(struct Object *ob, int act);
+struct Tex *give_current_world_texture(void);
struct TexMapping *add_mapping(void);
void init_mapping(struct TexMapping *texmap);
@@ -72,6 +73,7 @@ void BKE_free_envmap(struct EnvMap *env);
struct EnvMap *BKE_add_envmap(void);
struct EnvMap *BKE_copy_envmap(struct EnvMap *env);
+int BKE_texture_dependsOnTime(const struct Tex *texture);
#endif
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index 3ad11a61de3..561d8d7c2a6 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -117,10 +117,14 @@ float BPY_pydriver_eval(struct IpoDriver *driver)
{
return 0;
}
+
+/*
int EXPP_dict_set_item_str(struct PyObject *dict, char *key, struct PyObject *value)
{
return 0;
}
+*/
+
void Node_SetStack(struct BPy_Node *self, struct bNodeStack **stack, int type){}
void InitNode(struct BPy_Node *self, struct bNode *node){}
void Node_SetShi(struct BPy_Node *self, struct ShadeInput *shi){}
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index bc55332a450..01381ac542b 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -59,6 +59,7 @@
#include "BLI_edgehash.h"
#include "BLI_editVert.h"
#include "BLI_linklist.h"
+#include "BLI_memarena.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_customdata.h"
@@ -2759,6 +2760,127 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo
return numleft;
}
+void DM_add_tangent_layer(DerivedMesh *dm)
+{
+ /* mesh vars */
+ MTFace *mtface, *tf;
+ MFace *mface, *mf;
+ MVert *mvert, *v1, *v2, *v3, *v4;
+ MemArena *arena= NULL;
+ VertexTangent **vtangents= NULL;
+ float (*orco)[3]= NULL, (*tangent)[3];
+ float *uv1, *uv2, *uv3, *uv4, *vtang;
+ float fno[3], tang[3], uv[4][2];
+ int i, j, len, mf_vi[4], totvert, totface;
+
+ if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
+ return;
+
+ /* check we have all the needed layers */
+ totvert= dm->getNumVerts(dm);
+ totface= dm->getNumFaces(dm);
+
+ mvert= dm->getVertArray(dm);
+ mface= dm->getFaceArray(dm);
+ mtface= dm->getFaceDataArray(dm, CD_MTFACE);
+
+ if(!mtface) {
+ orco= dm->getVertDataArray(dm, CD_ORCO);
+ if(!orco)
+ return;
+ }
+
+ /* create tangent layer */
+ DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
+ tangent= DM_get_face_data_layer(dm, CD_TANGENT);
+
+ /* allocate some space */
+ arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+ 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];
+ CalcNormFloat4(v4->co, v3->co, v2->co, v1->co, fno);
+ }
+ else {
+ v4= NULL;
+ CalcNormFloat(v3->co, v2->co, v1->co, fno);
+ }
+
+ 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];
+ spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
+ spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
+ spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
+ if(v4)
+ spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
+ }
+
+ 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(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) {
+ 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];
+ spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
+ spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
+ spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
+ if(len==4)
+ spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
+ }
+
+ 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]);
+
+ VECCOPY(tangent[j], vtang);
+ Normalize(tangent[j]);
+ }
+ }
+
+ BLI_memarena_free(arena);
+ MEM_freeN(vtangents);
+}
+
+
/* ************************* fluidsim bobj file handling **************************** */
#ifndef DISABLE_ELBEEM
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 1f8dd74a6eb..1592c3e5504 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -734,9 +734,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_
ParticleCacheKey *cache;
ParticleSystemModifierData *psmd;
float ctime, pa_time, scale = 1.0f;
- float tmat[4][4], mat[4][4], obrotmat[4][4], pamat[4][4], size=0.0;
+ float tmat[4][4], mat[4][4], pamat[4][4], size=0.0;
float (*obmat)[4], (*oldobmat)[4];
- float xvec[3] = {-1.0, 0.0, 0.0}, q[4];
int lay, a, b, k, step_nbr = 0, counter, hair = 0;
int totpart, totchild, totgroup=0, pa_num;
@@ -898,14 +897,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_
/* to give ipos in object correct offset */
where_is_object_time(ob, ctime-pa_time);
- if(!hair) {
- vectoquat(xvec, ob->trackflag, ob->upflag, q);
- QuatToMat4(q, obrotmat);
- obrotmat[3][3]= 1.0f;
- Mat4MulMat4(mat, obrotmat, pamat);
- }
- else
- Mat4CpyMat4(mat, pamat);
+ Mat4CpyMat4(mat, pamat);
Mat4MulMat4(tmat, obmat, mat);
Mat4MulFloat3((float *)tmat, size*scale);
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
new file mode 100644
index 00000000000..042e2afad53
--- /dev/null
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -0,0 +1,577 @@
+/**
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): André Pinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "BKE_bvhutils.h"
+
+#include "DNA_object_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_utildefines.h"
+#include "BKE_deform.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+
+#include "BLI_arithb.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)
+{
+ float dist;
+
+ if(RayIntersectsTriangle((float*)ray->origin, (float*)ray->direction, (float*)v0, (float*)v1, (float*)v2, &dist, NULL))
+ return dist;
+
+ return FLT_MAX;
+}
+
+static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, const float m_dist, const float *v0, const float *v1, const float *v2)
+{
+
+ float idist;
+ float p1[3];
+ float plane_normal[3], hit_point[3];
+
+ CalcNormFloat((float*)v0, (float*)v1, (float*)v2, plane_normal);
+
+ VECADDFAC( p1, ray->origin, ray->direction, m_dist);
+ if(SweepingSphereIntersectsTriangleUV((float*)ray->origin, p1, radius, (float*)v0, (float*)v1, (float*)v2, &idist, hit_point))
+ {
+ return idist * m_dist;
+ }
+
+ return FLT_MAX;
+}
+
+
+/*
+ * Function adapted from David Eberly's distance tools (LGPL)
+ * http://www.geometrictools.com/LibFoundation/Distance/Distance.html
+ */
+static float nearest_point_in_tri_surface(const float *v0,const float *v1,const float *v2,const float *p, int *v, int *e, float *d, float *nearest )
+{
+ float diff[3];
+ float e0[3];
+ float e1[3];
+ float A00;
+ float A01;
+ float A11;
+ float B0;
+ float B1;
+ float C;
+ float Det;
+ float S;
+ float T;
+ float sqrDist;
+ int lv = -1, le = -1;
+
+ VECSUB(diff, v0, p);
+ VECSUB(e0, v1, v0);
+ VECSUB(e1, v2, v0);
+
+ A00 = INPR ( e0, e0 );
+ A01 = INPR( e0, e1 );
+ A11 = INPR ( e1, e1 );
+ B0 = INPR( diff, e0 );
+ B1 = INPR( diff, e1 );
+ C = INPR( diff, diff );
+ Det = fabs( A00 * A11 - A01 * A01 );
+ S = A01 * B1 - A11 * B0;
+ T = A01 * B0 - A00 * B1;
+
+ if ( S + T <= Det )
+ {
+ if ( S < 0.0f )
+ {
+ if ( T < 0.0f ) // Region 4
+ {
+ if ( B0 < 0.0f )
+ {
+ T = 0.0f;
+ if ( -B0 >= A00 )
+ {
+ S = (float)1.0;
+ sqrDist = A00 + 2.0f * B0 + C;
+ lv = 1;
+ }
+ else
+ {
+ if(fabs(A00) > FLT_EPSILON)
+ S = -B0/A00;
+ else
+ S = 0.0f;
+ sqrDist = B0 * S + C;
+ le = 0;
+ }
+ }
+ else
+ {
+ S = 0.0f;
+ if ( B1 >= 0.0f )
+ {
+ T = 0.0f;
+ sqrDist = C;
+ lv = 0;
+ }
+ else if ( -B1 >= A11 )
+ {
+ T = 1.0f;
+ sqrDist = A11 + 2.0f * B1 + C;
+ lv = 2;
+ }
+ else
+ {
+ if(fabs(A11) > FLT_EPSILON)
+ T = -B1 / A11;
+ else
+ T = 0.0f;
+ sqrDist = B1 * T + C;
+ le = 1;
+ }
+ }
+ }
+ else // Region 3
+ {
+ S = 0.0f;
+ if ( B1 >= 0.0f )
+ {
+ T = 0.0f;
+ sqrDist = C;
+ lv = 0;
+ }
+ else if ( -B1 >= A11 )
+ {
+ T = 1.0f;
+ sqrDist = A11 + 2.0f * B1 + C;
+ lv = 2;
+ }
+ else
+ {
+ if(fabs(A11) > FLT_EPSILON)
+ T = -B1 / A11;
+ else
+ T = 0.0;
+ sqrDist = B1 * T + C;
+ le = 1;
+ }
+ }
+ }
+ else if ( T < 0.0f ) // Region 5
+ {
+ T = 0.0f;
+ if ( B0 >= 0.0f )
+ {
+ S = 0.0f;
+ sqrDist = C;
+ lv = 0;
+ }
+ else if ( -B0 >= A00 )
+ {
+ S = 1.0f;
+ sqrDist = A00 + 2.0f * B0 + C;
+ lv = 1;
+ }
+ else
+ {
+ if(fabs(A00) > FLT_EPSILON)
+ S = -B0 / A00;
+ else
+ S = 0.0f;
+ sqrDist = B0 * S + C;
+ le = 0;
+ }
+ }
+ else // Region 0
+ {
+ // Minimum at interior lv
+ float invDet;
+ if(fabs(Det) > FLT_EPSILON)
+ invDet = 1.0f / Det;
+ else
+ invDet = 0.0f;
+ S *= invDet;
+ T *= invDet;
+ sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0) +
+ T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
+ }
+ }
+ else
+ {
+ float tmp0, tmp1, numer, denom;
+
+ if ( S < 0.0f ) // Region 2
+ {
+ tmp0 = A01 + B0;
+ tmp1 = A11 + B1;
+ if ( tmp1 > tmp0 )
+ {
+ numer = tmp1 - tmp0;
+ denom = A00 - 2.0f * A01 + A11;
+ if ( numer >= denom )
+ {
+ S = 1.0f;
+ T = 0.0f;
+ sqrDist = A00 + 2.0f * B0 + C;
+ lv = 1;
+ }
+ else
+ {
+ if(fabs(denom) > FLT_EPSILON)
+ S = numer / denom;
+ else
+ S = 0.0f;
+ T = 1.0f - S;
+ sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
+ T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
+ le = 2;
+ }
+ }
+ else
+ {
+ S = 0.0f;
+ if ( tmp1 <= 0.0f )
+ {
+ T = 1.0f;
+ sqrDist = A11 + 2.0f * B1 + C;
+ lv = 2;
+ }
+ else if ( B1 >= 0.0f )
+ {
+ T = 0.0f;
+ sqrDist = C;
+ lv = 0;
+ }
+ else
+ {
+ if(fabs(A11) > FLT_EPSILON)
+ T = -B1 / A11;
+ else
+ T = 0.0f;
+ sqrDist = B1 * T + C;
+ le = 1;
+ }
+ }
+ }
+ else if ( T < 0.0f ) // Region 6
+ {
+ tmp0 = A01 + B1;
+ tmp1 = A00 + B0;
+ if ( tmp1 > tmp0 )
+ {
+ numer = tmp1 - tmp0;
+ denom = A00 - 2.0f * A01 + A11;
+ if ( numer >= denom )
+ {
+ T = 1.0f;
+ S = 0.0f;
+ sqrDist = A11 + 2.0f * B1 + C;
+ lv = 2;
+ }
+ else
+ {
+ if(fabs(denom) > FLT_EPSILON)
+ T = numer / denom;
+ else
+ T = 0.0f;
+ S = 1.0f - T;
+ sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
+ T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
+ le = 2;
+ }
+ }
+ else
+ {
+ T = 0.0f;
+ if ( tmp1 <= 0.0f )
+ {
+ S = 1.0f;
+ sqrDist = A00 + 2.0f * B0 + C;
+ lv = 1;
+ }
+ else if ( B0 >= 0.0f )
+ {
+ S = 0.0f;
+ sqrDist = C;
+ lv = 0;
+ }
+ else
+ {
+ if(fabs(A00) > FLT_EPSILON)
+ S = -B0 / A00;
+ else
+ S = 0.0f;
+ sqrDist = B0 * S + C;
+ le = 0;
+ }
+ }
+ }
+ else // Region 1
+ {
+ numer = A11 + B1 - A01 - B0;
+ if ( numer <= 0.0f )
+ {
+ S = 0.0f;
+ T = 1.0f;
+ sqrDist = A11 + 2.0f * B1 + C;
+ lv = 2;
+ }
+ else
+ {
+ denom = A00 - 2.0f * A01 + A11;
+ if ( numer >= denom )
+ {
+ S = 1.0f;
+ T = 0.0f;
+ sqrDist = A00 + 2.0f * B0 + C;
+ lv = 1;
+ }
+ else
+ {
+ if(fabs(denom) > FLT_EPSILON)
+ S = numer / denom;
+ else
+ S = 0.0f;
+ T = 1.0f - S;
+ sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
+ T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
+ le = 2;
+ }
+ }
+ }
+ }
+
+ // Account for numerical round-off error
+ if ( sqrDist < FLT_EPSILON )
+ sqrDist = 0.0f;
+
+ {
+ float w[3], x[3], y[3], z[3];
+ VECCOPY(w, v0);
+ VECCOPY(x, e0);
+ VecMulf(x, S);
+ VECCOPY(y, e1);
+ VecMulf(y, T);
+ VECADD(z, w, x);
+ VECADD(z, z, y);
+ VECSUB(d, p, z);
+ VECCOPY(nearest, z);
+ // d = p - ( v0 + S * e0 + T * e1 );
+ }
+ *v = lv;
+ *e = le;
+
+ return sqrDist;
+}
+
+
+/*
+ * BVH from meshs callbacks
+ */
+
+// Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
+// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
+static void mesh_faces_nearest_point(void *userdata, int index, const float *co, BVHTreeNearest *nearest)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
+ MVert *vert = data->vert;
+ MFace *face = data->face + index;
+
+ float *t0, *t1, *t2, *t3;
+ t0 = vert[ face->v1 ].co;
+ t1 = vert[ face->v2 ].co;
+ t2 = vert[ face->v3 ].co;
+ t3 = face->v4 ? vert[ face->v4].co : NULL;
+
+
+ do
+ {
+ float nearest_tmp[3], col_normal[3], dist;
+ int vertex, edge;
+
+ dist = nearest_point_in_tri_surface(t0, t1, t2, co, &vertex, &edge, col_normal, nearest_tmp);
+ if(dist < nearest->dist)
+ {
+ nearest->index = index;
+ nearest->dist = dist;
+ VECCOPY(nearest->co, nearest_tmp);
+ VECCOPY(nearest->no, col_normal);
+ }
+
+ t1 = t2;
+ t2 = t3;
+ t3 = NULL;
+
+ } while(t2);
+}
+
+// Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
+// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
+static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
+ MVert *vert = data->vert;
+ MFace *face = data->face + index;
+
+ float *t0, *t1, *t2, *t3;
+ t0 = vert[ face->v1 ].co;
+ t1 = vert[ face->v2 ].co;
+ t2 = vert[ face->v3 ].co;
+ t3 = face->v4 ? vert[ face->v4].co : NULL;
+
+
+ do
+ {
+ float dist;
+ if(data->sphere_radius == 0.0f)
+ dist = ray_tri_intersection(ray, hit->dist, t0, t1, t2);
+ else
+ dist = sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);
+
+ if(dist >= 0 && dist < hit->dist)
+ {
+ hit->index = index;
+ hit->dist = dist;
+ VECADDFAC(hit->co, ray->origin, ray->direction, dist);
+
+ CalcNormFloat(t0, t1, t2, hit->no);
+ }
+
+ t1 = t2;
+ t2 = t3;
+ t3 = NULL;
+
+ } while(t2);
+}
+
+/*
+ * BVH builders
+ */
+// Builds a bvh tree.. where nodes are the vertexs of the given mesh
+void bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
+{
+ int i;
+ int numVerts= mesh->getNumVerts(mesh);
+ MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
+ BVHTree *tree = NULL;
+
+ memset(data, 0, sizeof(*data));
+
+ if(vert == NULL)
+ {
+ printf("bvhtree cant be build: cant get a vertex array");
+ return;
+ }
+
+ tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);
+ if(tree != NULL)
+ {
+ for(i = 0; i < numVerts; i++)
+ BLI_bvhtree_insert(tree, i, vert[i].co, 1);
+
+ BLI_bvhtree_balance(tree);
+
+ data->tree = tree;
+
+ //a NULL nearest callback works fine
+ //remeber the min distance to point is the same as the min distance to BV of point
+ data->nearest_callback = NULL;
+ data->raycast_callback = NULL;
+
+ data->mesh = mesh;
+ data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
+ data->face = mesh->getFaceDataArray(mesh, CD_MFACE);
+
+ data->sphere_radius = epsilon;
+ }
+}
+
+// Builds a bvh tree.. where nodes are the faces of the given mesh.
+void bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
+{
+ int i;
+ int numFaces= mesh->getNumFaces(mesh);
+ MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
+ MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
+ BVHTree *tree = NULL;
+
+ memset(data, 0, sizeof(*data));
+
+ if(vert == NULL && face == NULL)
+ {
+ printf("bvhtree cant be build: cant get a vertex/face array");
+ return;
+ }
+
+ /* Create a bvh-tree of the given target */
+ 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);
+ }
+ BLI_bvhtree_balance(tree);
+
+ data->tree = tree;
+ data->nearest_callback = mesh_faces_nearest_point;
+ data->raycast_callback = mesh_faces_spherecast;
+
+ data->mesh = mesh;
+ data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
+ data->face = mesh->getFaceDataArray(mesh, CD_MFACE);
+
+ data->sphere_radius = epsilon;
+ }
+}
+
+// Frees data allocated by a call to bvhtree_from_mesh_*.
+void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
+{
+ if(data->tree)
+ {
+ BLI_bvhtree_free(data->tree);
+ memset( data, 0, sizeof(data) );
+ }
+}
+
+
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 6dfb77504fb..cfcab54058d 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -1291,116 +1291,6 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col
return 1;
}
-int cloth_do_selfcollisions(ClothModifierData * clmd)
-{
- int ret2 = 0, l;
- Cloth *cloth = clmd->clothObject;
-
- if ( clmd->clothObject->bvhselftree )
- {
- for(l = 0; l < clmd->coll_parms->self_loop_count; l++)
- {
- BVHTreeOverlap *overlap = NULL;
- ClothVertex *verts = clmd->clothObject->verts; // needed for openMP
- int k;
- int ret = 0, result = 0;
-
- // search for overlapping collision pairs
- overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result );
-
-// #pragma omp parallel for private(k, i, j) schedule(static)
- for ( k = 0; k < result; k++ )
- {
- float temp[3];
- float length = 0;
- float mindistance;
- int i, j;
-
- i = overlap[k].indexA;
- j = overlap[k].indexB;
-
- mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
-
- if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
- {
- if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
- && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
- {
- continue;
- }
- }
-
- VECSUB ( temp, verts[i].tx, verts[j].tx );
-
- if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
-
- // check for adjacent points (i must be smaller j)
- if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) )
- {
- continue;
- }
-
- length = Normalize ( temp );
-
- if ( length < mindistance )
- {
- float correction = mindistance - length;
-
- if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
- {
- VecMulf ( temp, -correction );
- VECADD ( verts[j].tx, verts[j].tx, temp );
- }
- else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
- {
- VecMulf ( temp, correction );
- VECADD ( verts[i].tx, verts[i].tx, temp );
- }
- else
- {
- VecMulf ( temp, -correction*0.5 );
- VECADD ( verts[j].tx, verts[j].tx, temp );
-
- VECSUB ( verts[i].tx, verts[i].tx, temp );
- }
- ret = 1;
- ret2 += ret;
- }
- else
- {
- // check for approximated time collisions
- }
- }
-
- if ( overlap )
- MEM_freeN ( overlap );
-
- if(!ret)
- break;
-
- }
- ////////////////////////////////////////////////////////////
-
- ////////////////////////////////////////////////////////////
- // SELFCOLLISIONS: update velocities
- ////////////////////////////////////////////////////////////
- if ( ret2 )
- {
- int i;
- ClothVertex *verts = clmd->clothObject->verts; // needed for openMP
-
- for ( i = 0; i < cloth->numverts; i++ )
- {
- if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
- {
- VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold );
- }
- }
- }
- ////////////////////////////////////////////////////////////
- }
- return ret2;
-}
// return all collision objects in scene
// collision object will exclude self
@@ -1547,7 +1437,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f
{
Cloth *cloth=NULL;
BVHTree *cloth_bvh=NULL;
- long i=0, numfaces = 0, numverts = 0;
+ 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;
@@ -1647,21 +1537,122 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f
VECADD ( verts[i].tx, verts[i].txold, verts[i].tv );
}
////////////////////////////////////////////////////////////
-
+
////////////////////////////////////////////////////////////
// Test on *simple* selfcollisions
////////////////////////////////////////////////////////////
if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF )
{
- ret2 += cloth_do_selfcollisions(clmd);
+ for(l = 0; l < clmd->coll_parms->self_loop_count; l++)
+ {
+ // TODO: add coll quality rounds again
+ BVHTreeOverlap *overlap = NULL;
+ int result = 0;
+
+ // collisions = 1;
+ verts = cloth->verts; // needed for openMP
+
+ numfaces = clmd->clothObject->numfaces;
+ numverts = clmd->clothObject->numverts;
+
+ verts = cloth->verts;
+
+ if ( cloth->bvhselftree )
+ {
+ // search for overlapping collision pairs
+ overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result );
+
+ // #pragma omp parallel for private(k, i, j) schedule(static)
+ for ( k = 0; k < result; k++ )
+ {
+ float temp[3];
+ float length = 0;
+ float mindistance;
+
+ i = overlap[k].indexA;
+ j = overlap[k].indexB;
+
+ mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
+
+ if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+ {
+ if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+ && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
+ {
+ continue;
+ }
+ }
+
+ VECSUB ( temp, verts[i].tx, verts[j].tx );
+
+ if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
+
+ // check for adjacent points (i must be smaller j)
+ if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) )
+ {
+ continue;
+ }
+
+ length = Normalize ( temp );
+
+ if ( length < mindistance )
+ {
+ float correction = mindistance - length;
+
+ if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+ {
+ VecMulf ( temp, -correction );
+ VECADD ( verts[j].tx, verts[j].tx, temp );
+ }
+ else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
+ {
+ VecMulf ( temp, correction );
+ VECADD ( verts[i].tx, verts[i].tx, temp );
+ }
+ else
+ {
+ VecMulf ( temp, -correction*0.5 );
+ VECADD ( verts[j].tx, verts[j].tx, temp );
+
+ VECSUB ( verts[i].tx, verts[i].tx, temp );
+ }
+ ret = 1;
+ ret2 += ret;
+ }
+ else
+ {
+ // check for approximated time collisions
+ }
+ }
+
+ if ( overlap )
+ MEM_freeN ( overlap );
+
+ }
+ }
+ ////////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////////////////////////
+ // SELFCOLLISIONS: update velocities
+ ////////////////////////////////////////////////////////////
+ if ( ret2 )
+ {
+ for ( i = 0; i < cloth->numverts; i++ )
+ {
+ if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
+ {
+ VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold );
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////
}
- ////////////////////////////////////////////////////////////
}
while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
if(collobjs)
- + MEM_freeN(collobjs);
+ MEM_freeN(collobjs);
return MIN2 ( ret, 1 );
}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 1e7bdea9e8e..744b1c97638 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -265,14 +265,34 @@ static void layerSwap_tface(void *data, int *corner_indices)
{
MTFace *tf = data;
float uv[4][2];
+ const static short pin_flags[4] =
+ { TF_PIN1, TF_PIN2, TF_PIN3, TF_PIN4 };
+ const static char sel_flags[4] =
+ { TF_SEL1, TF_SEL2, TF_SEL3, TF_SEL4 };
+ short unwrap = tf->unwrap & ~(TF_PIN1 | TF_PIN2 | TF_PIN3 | TF_PIN4);
+ char flag = tf->flag & ~(TF_SEL1 | TF_SEL2 | TF_SEL3 | TF_SEL4);
int j;
for(j = 0; j < 4; ++j) {
- uv[j][0] = tf->uv[corner_indices[j]][0];
- uv[j][1] = tf->uv[corner_indices[j]][1];
+ int source_index = corner_indices[j];
+
+ uv[j][0] = tf->uv[source_index][0];
+ uv[j][1] = tf->uv[source_index][1];
+
+ // swap pinning flags around
+ if(tf->unwrap & pin_flags[source_index]) {
+ unwrap |= pin_flags[j];
+ }
+
+ // swap selection flags around
+ if(tf->flag & sel_flags[source_index]) {
+ flag |= sel_flags[j];
+ }
}
memcpy(tf->uv, uv, sizeof(tf->uv));
+ tf->unwrap = unwrap;
+ tf->flag = flag;
}
static void layerDefault_tface(void *data, int count)
@@ -566,6 +586,7 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
{sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL},
{sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
+ {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
layerFree_mdisps, NULL, NULL, NULL}
};
@@ -573,8 +594,8 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
"CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
- "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly",
- "CDMLoopUV", "CDMloopCol", "CDMDisps"};
+ "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV",
+ "CDMloopCol", "CDTangent", "CDMDisps"};
const CustomDataMask CD_MASK_BAREMESH =
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
@@ -588,7 +609,7 @@ const CustomDataMask CD_MASK_EDITMESH =
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
- CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO;
+ CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT;
const CustomDataMask CD_MASK_BMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
const CustomDataMask CD_MASK_FACECORNERS =
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index c64605ab0d9..a0ea2bd58a5 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -98,6 +98,7 @@
#include "BKE_material.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
+#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "depsgraph_private.h"
#include "BKE_bmesh.h"
@@ -1131,8 +1132,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
mface[numFaces].v1 = vert_map[mface[numFaces].v1];
mface[numFaces].v2 = vert_map[mface[numFaces].v2];
mface[numFaces].v3 = vert_map[mface[numFaces].v3];
- if(mface[numFaces].v4)
+ if(mface[numFaces].v4) {
mface[numFaces].v4 = vert_map[mface[numFaces].v4];
+
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 4);
+ }
+ else
+ {
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 3);
+ }
+
origindex[numFaces] = ORIGINDEX_NONE;
numFaces++;
@@ -1222,8 +1233,17 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
mface[numFaces].v1 = vert_map[mface[numFaces].v1];
mface[numFaces].v2 = vert_map[mface[numFaces].v2];
mface[numFaces].v3 = vert_map[mface[numFaces].v3];
- if(mface[numFaces].v4)
+ if(mface[numFaces].v4) {
mface[numFaces].v4 = vert_map[mface[numFaces].v4];
+
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 4);
+ }
+ else
+ {
+ test_index_face(&mface[numFaces], &result->faceData,
+ numFaces, 3);
+ }
origindex[numFaces] = ORIGINDEX_NONE;
numFaces++;
@@ -2981,6 +3001,20 @@ CustomDataMask displaceModifier_requiredDataMask(ModifierData *md)
return dataMask;
}
+static int displaceModifier_dependsOnTime(ModifierData *md)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData *)md;
+
+ if(dmd->texture)
+ {
+ return BKE_texture_dependsOnTime(dmd->texture);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob,
ObjectWalkFunc walk, void *userData)
{
@@ -7372,6 +7406,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->initData = displaceModifier_initData;
mti->copyData = displaceModifier_copyData;
mti->requiredDataMask = displaceModifier_requiredDataMask;
+ mti->dependsOnTime = displaceModifier_dependsOnTime;
mti->foreachObjectLink = displaceModifier_foreachObjectLink;
mti->foreachIDLink = displaceModifier_foreachIDLink;
mti->updateDepgraph = displaceModifier_updateDepgraph;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 24a3d348ae7..643f90637ad 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -3744,6 +3744,9 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey
/* TODO: pa_clump vgroup */
do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0);
+
+ if(psys->lattice)
+ calc_latt_deform(state->co,1.0f);
}
else{
if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 7dca87d5c13..d1c0cdec71d 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4653,7 +4653,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
PTCacheID pid;
int totpart, oldtotpart, totchild, oldtotchild, p;
float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0;
- int init= 0, distr= 0, alloc= 0, usecache= 0;
+ int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0;
int framenr, framedelta, startframe, endframe;
part= psys->part;
@@ -4720,6 +4720,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
totchild = get_psys_tot_child(psys);
if(oldtotpart != totpart || (psys->part->childtype && oldtotchild != totchild)) {
+ only_children_changed = (oldtotpart == totpart);
realloc_particles(ob, psys, totpart);
alloc = 1;
distr= 1;
@@ -4740,14 +4741,17 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE))
/* don't generate children while growing hair - waste of time */
- psys_free_children(psys);
- else if(get_psys_tot_child(psys))
- distribute_particles(ob, psys, PART_FROM_CHILD);
+ psys_free_children(psys);
+ else if(get_psys_tot_child(psys))
+ distribute_particles(ob, psys, PART_FROM_CHILD);
}
- initialize_all_particles(ob, psys, psmd);
- if(alloc)
- reset_all_particles(ob, psys, psmd, 0.0, cfra, oldtotpart);
+ if(only_children_changed==0) {
+ initialize_all_particles(ob, psys, psmd);
+
+ if(alloc)
+ reset_all_particles(ob, psys, psmd, 0.0, cfra, oldtotpart);
+ }
/* flag for possible explode modifiers after this system */
psmd->flag |= eParticleSystemFlag_Pars;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index d5b5ab6d63e..d465c058d30 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -69,6 +69,8 @@ variables on the UI for now
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_ghash.h"
+#include "BLI_threads.h"
+
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_global.h"
@@ -118,6 +120,20 @@ typedef struct SBScratch {
float aabbmin[3],aabbmax[3];
}SBScratch;
+typedef struct SB_thread_context{
+ Object *ob;
+ float forcetime;
+ float timenow;
+ int ifirst;
+ int ilast;
+ ListBase *do_effector;
+ int do_deflector;
+ float fieldfactor;
+ float windfactor;
+ int nr;
+ int tot;
+}SB_thread_context;
+
#define NLF_BUILD 1
#define NLF_SOLVE 2
@@ -1514,17 +1530,15 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp
-void scan_for_ext_spring_forces(Object *ob,float timenow)
+void _scan_for_ext_spring_forces(Object *ob,float timenow,int ifirst,int ilast, struct ListBase *do_effector)
{
SoftBody *sb = ob->soft;
- ListBase *do_effector;
int a;
float damp;
float feedback[3];
- do_effector= pdInitEffectors(ob,NULL);
if (sb && sb->totspring){
- for(a=0; a<sb->totspring; a++) {
+ for(a=ifirst; a<ilast; a++) {
BodySpring *bs = &sb->bspring[a];
bs->ext_force[0]=bs->ext_force[1]=bs->ext_force[2]=0.0f;
feedback[0]=feedback[1]=feedback[2]=0.0f;
@@ -1584,9 +1598,88 @@ void scan_for_ext_spring_forces(Object *ob,float timenow)
}
}
}
- if(do_effector)
- pdEndEffectors(do_effector);
}
+
+
+void scan_for_ext_spring_forces(Object *ob,float timenow)
+{
+ SoftBody *sb = ob->soft;
+ ListBase *do_effector= NULL;
+ do_effector= pdInitEffectors(ob,NULL);
+ if (sb){
+ _scan_for_ext_spring_forces(ob,timenow,0,sb->totspring,do_effector);
+ }
+ if(do_effector)
+ pdEndEffectors(do_effector);
+}
+
+void *exec_scan_for_ext_spring_forces(void *data)
+{
+ SB_thread_context *pctx = (SB_thread_context*)data;
+ _scan_for_ext_spring_forces(pctx->ob,pctx->timenow,pctx->ifirst,pctx->ilast,pctx->do_effector);
+ return 0;
+}
+
+void sb_sfesf_threads_run(struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func())
+{
+ ListBase *do_effector = NULL;
+ ListBase threads;
+ SB_thread_context *sb_threads;
+ int i, totthread,left,dec;
+ int lowsprings =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
+
+ do_effector= pdInitEffectors(ob,NULL);
+
+ /* figure the number of threads while preventing pretty pointless threading overhead */
+ if(totsprings < lowsprings) {totthread=1;}
+ else{
+ if(G.scene->r.mode & R_FIXED_THREADS)
+ totthread= G.scene->r.threads;
+ else
+ totthread= BLI_system_thread_count();
+ }
+ /*left to do--> what if we got zillions of CPUs running but 'totsprings' tasks to spread*/
+
+ sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBSpringsThread");
+ memset(sb_threads, 0, sizeof(SB_thread_context)*totthread);
+ left = totsprings;
+ dec = totsprings/totthread +1;
+ for(i=0; i<totthread; i++) {
+ sb_threads[i].ob = ob;
+ sb_threads[i].forcetime = 0.0; // not used here
+ sb_threads[i].timenow = timenow;
+ sb_threads[i].ilast = left;
+ left = left - dec;
+ if (left >0){
+ sb_threads[i].ifirst = left;
+ }
+ else
+ sb_threads[i].ifirst = 0;
+ sb_threads[i].do_effector = do_effector;
+ sb_threads[i].do_deflector = 0;// not used here
+ sb_threads[i].fieldfactor = 0.0f;// not used here
+ sb_threads[i].windfactor = 0.0f;// not used here
+ sb_threads[i].nr= i;
+ sb_threads[i].tot= totthread;
+ }
+ if(totthread > 1) {
+ BLI_init_threads(&threads, exec_scan_for_ext_spring_forces, totthread);
+
+ for(i=0; i<totthread; i++)
+ BLI_insert_thread(&threads, &sb_threads[i]);
+
+ BLI_end_threads(&threads);
+ }
+ else
+ exec_scan_for_ext_spring_forces(&sb_threads[0]);
+ /* clean up */
+ MEM_freeN(sb_threads);
+
+ if(do_effector)
+ pdEndEffectors(do_effector);
+}
+
+
/* --- the spring external section*/
int choose_winner(float*w, float* pos,float*a,float*b,float*c,float*ca,float*cb,float*cc)
@@ -2023,109 +2116,72 @@ static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float fo
}
-static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags)
+/* 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 */
+int _softbody_calc_forces_slice_in_a_thread(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)
{
-/* rule we never alter free variables :bp->vec bp->pos in here !
- * this will ruin adaptive stepsize AKA heun! (BM)
- */
+ float iks;
+ int bb,do_selfcollision,do_springcollision,do_aero;
+ int number_of_points_here = ilast - ifirst;
SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp;
- BodyPoint *bproot;
- BodySpring *bs;
- ListBase *do_effector;
- float iks, ks, kd, gravity;
- float fieldfactor = 1000.0f, windfactor = 250.0f;
- float tune = sb->ballstiff;
- int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero;
-
-
-/* jacobian
- NLboolean success;
-
- if(nl_flags){
- nlBegin(NL_SYSTEM);
- nlBegin(NL_MATRIX);
- }
-*/
-
-
- gravity = sb->grav * sb_grav_force_scale(ob);
-
+ /* intitialize */
+ if (sb) {
/* check conditions for various options */
- do_deflector= query_external_colliders(ob);
+ /* +++ could be done on object level to squeeze out the last bits of it */
do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
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 */
- bproot= sb->bpoint; /* need this for proper spring addressing */
-
- if (do_springcollision || do_aero) scan_for_ext_spring_forces(ob,timenow);
- /* after spring scan because it uses Effoctors too */
- do_effector= pdInitEffectors(ob,NULL);
+ /* --- could be done on object level to squeeze out the last bits of it */
+ }
+ else {
+ printf("Error expected a SB here \n");
+ return (999);
+ }
- if (do_deflector) {
- float defforce[3];
- do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
+/* debugerin */
+ if (sb->totpoint < ifirst) {
+ printf("Aye 998");
+ return (998);
}
+/* debugerin */
- for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+
+ bp = &sb->bpoint[ifirst];
+ for(bb=number_of_points_here; bb>0; bb--, bp++) {
/* clear forces accumulator */
bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
- if(nl_flags & NLF_BUILD){
- //int ia =3*(sb->totpoint-a);
- //int op =3*sb->totpoint;
- /* dF/dV = v */
- /* jacobioan
- nlMatrixAdd(op+ia,ia,-forcetime);
- nlMatrixAdd(op+ia+1,ia+1,-forcetime);
- nlMatrixAdd(op+ia+2,ia+2,-forcetime);
-
- nlMatrixAdd(ia,ia,1);
- nlMatrixAdd(ia+1,ia+1,1);
- nlMatrixAdd(ia+2,ia+2,1);
-
- nlMatrixAdd(op+ia,op+ia,1);
- nlMatrixAdd(op+ia+1,op+ia+1,1);
- nlMatrixAdd(op+ia+2,op+ia+2,1);
- */
-
-
- }
-
/* naive ball self collision */
/* needs to be done if goal snaps or not */
if(do_selfcollision){
int attached;
BodyPoint *obp;
+ BodySpring *bs;
int c,b;
float velcenter[3],dvel[3],def[3];
float distance;
float compare;
+ float bstune = sb->ballstiff;
- for(c=sb->totpoint, obp= sb->bpoint; c>=a; c--, obp++) {
-
- //if ((bp->octantflag & obp->octantflag) == 0) continue;
-
+ for(c=sb->totpoint, obp= sb->bpoint; c>=ifirst+bb; c--, obp++) {
compare = (obp->colball + bp->colball);
VecSubf(def, bp->pos, obp->pos);
-
/* rather check the AABBoxes before ever calulating the real distance */
/* mathematically it is completly nuts, but performace is pretty much (3) times faster */
if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
-
distance = Normalize(def);
if (distance < compare ){
/* exclude body points attached with a spring */
attached = 0;
for(b=obp->nofsprings;b>0;b--){
bs = sb->bspring + obp->springs[b-1];
- if (( sb->totpoint-a == bs->v2) || ( sb->totpoint-a == bs->v1)){
+ if (( ilast-bb == bs->v2) || ( ilast-bb == bs->v1)){
attached=1;
continue;}
}
if (!attached){
- float f = tune/(distance) + tune/(compare*compare)*distance - 2.0f*tune/compare ;
+ float f = bstune/(distance) + bstune/(compare*compare)*distance - 2.0f*bstune/compare ;
VecMidf(velcenter, bp->vec, obp->vec);
VecSubf(dvel,velcenter,bp->vec);
@@ -2134,38 +2190,12 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
Vec3PlusStVec(bp->force,sb->balldamp,dvel);
- if(nl_flags & NLF_BUILD){
- //int ia =3*(sb->totpoint-a);
- //int ic =3*(sb->totpoint-c);
- //int op =3*sb->totpoint;
- //float mvel = forcetime*sb->nodemass*sb->balldamp;
- //float mpos = forcetime*tune*(1.0f-sb->balldamp);
- /*some quick and dirty entries to the jacobian*/
- //dfdx_goal(ia,ia,op,mpos);
- //dfdv_goal(ia,ia,mvel);
- /* exploit force(a,b) == -force(b,a) part1/2 */
- //dfdx_goal(ic,ic,op,mpos);
- //dfdv_goal(ic,ic,mvel);
-
-
- /*TODO sit down an X-out the true jacobian entries*/
- /*well does not make to much sense because the eigenvalues
- of the jacobian go negative; and negative eigenvalues
- on a complex iterative system z(n+1)=A * z(n)
- give imaginary roots in the charcateristic polynom
- --> solutions that to z(t)=u(t)* exp ( i omega t) --> oscilations we don't want here
- where u(t) is a unknown amplitude function (worst case rising fast)
- */
- }
-
/* exploit force(a,b) == -force(b,a) part2/2 */
VecSubf(dvel,velcenter,obp->vec);
VecMulf(dvel,sb->nodemass);
Vec3PlusStVec(obp->force,sb->balldamp,dvel);
Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
-
-
}
}
}
@@ -2179,20 +2209,13 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
/* do goal stuff */
if(ob->softflag & OB_SB_GOAL) {
/* true elastic goal */
+ float ks,kd;
VecSubf(auxvect,bp->pos,bp->origT);
ks = 1.0f/(1.0f- bp->goal*sb->goalspring)-1.0f ;
bp->force[0]+= -ks*(auxvect[0]);
bp->force[1]+= -ks*(auxvect[1]);
bp->force[2]+= -ks*(auxvect[2]);
- if(nl_flags & NLF_BUILD){
- //int ia =3*(sb->totpoint-a);
- //int op =3*(sb->totpoint);
- /* depending on my pos */
- //dfdx_goal(ia,ia,op,ks*forcetime);
- }
-
-
/* calulate damping forces generated by goals*/
VecSubf(velgoal,bp->origS, bp->origE);
kd = sb->goalfrict * sb_fric_force_scale(ob) ;
@@ -2202,13 +2225,6 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
bp->force[0]-= kd * (auxvect[0]);
bp->force[1]-= kd * (auxvect[1]);
bp->force[2]-= kd * (auxvect[2]);
- if(nl_flags & NLF_BUILD){
- //int ia =3*(sb->totpoint-a);
- Normalize(auxvect);
- /* depending on my vel */
- //dfdv_goal(ia,ia,kd*forcetime);
- }
-
}
else {
bp->force[0]-= kd * (velgoal[0] - bp->vec[0]);
@@ -2218,14 +2234,15 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
}
/* done goal stuff */
-
/* gravitation */
+ if (sb){
+ float gravity = sb->grav * sb_grav_force_scale(ob);
bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */
- //bp->force[1]-= gravity*sb->nodemass; /* individual mass of node here */
-
+ }
/* particle field & vortex */
if(do_effector) {
+ float kd;
float force[3]= {0.0f, 0.0f, 0.0f};
float speed[3]= {0.0f, 0.0f, 0.0f};
float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
@@ -2246,21 +2263,12 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
}
else {
/* BP friction in media (not) moving*/
- kd= sb->mediafrict* sb_fric_force_scale(ob);
+ float kd = sb->mediafrict* sb_fric_force_scale(ob);
/* assume it to be proportional to actual velocity */
bp->force[0]-= bp->vec[0]*kd;
bp->force[1]-= bp->vec[1]*kd;
bp->force[2]-= bp->vec[2]*kd;
/* friction in media done */
- if(nl_flags & NLF_BUILD){
- //int ia =3*(sb->totpoint-a);
- /* da/dv = */
-
-// nlMatrixAdd(ia,ia,forcetime*kd);
-// nlMatrixAdd(ia+1,ia+1,forcetime*kd);
-// nlMatrixAdd(ia+2,ia+2,forcetime*kd);
- }
-
}
/* +++cached collision targets */
bp->choke = 0.0f;
@@ -2268,44 +2276,25 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
bp->flag &= ~SBF_DOFUZZY;
if(do_deflector) {
float cfforce[3],defforce[3] ={0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}, facenormal[3], cf = 1.0f,intrusion;
- kd = 1.0f;
+ float kd = 1.0f;
if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){
- if ((!nl_flags)&&(intrusion < 0.0f)){
- /*bjornmose: uugh.. what an evil hack
- violation of the 'don't touch bp->pos in here' rule
- but works nice, like this-->
- we predict the solution beeing out of the collider
- in heun step No1 and leave the heun step No2 adapt to it
- so we kind of introduced a implicit solver for this case
- */
- Vec3PlusStVec(bp->pos,-intrusion,facenormal);
-
- sb->scratch->flag |= SBF_DOFUZZY;
- bp->flag |= SBF_DOFUZZY;
- bp->choke = sb->choke*0.01f;
- }
- else{
+
VECSUB(cfforce,bp->vec,vel);
Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
- }
- Vec3PlusStVec(bp->force,kd,defforce);
- if (nl_flags & NLF_BUILD){
- // int ia =3*(sb->totpoint-a);
- // int op =3*sb->totpoint;
- //dfdx_goal(ia,ia,op,mpos); // don't do unless you know
- //dfdv_goal(ia,ia,-cf);
-
- }
-
+
+ Vec3PlusStVec(bp->force,kd,defforce);
}
}
/* ---cached collision targets */
/* +++springs */
+ iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
if(ob->softflag & OB_SB_EDGES) {
if (sb->bspring){ /* spring list exists at all ? */
+ int b;
+ BodySpring *bs;
for(b=bp->nofsprings;b>0;b--){
bs = sb->bspring + bp->springs[b-1];
if (do_springcollision || do_aero){
@@ -2315,90 +2304,513 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
}
// sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags)
- sb_spring_force(ob,sb->totpoint-a,bs,iks,forcetime,nl_flags);
+ sb_spring_force(ob,ilast-bb,bs,iks,forcetime,0);
}/* loop springs */
}/* existing spring list */
}/*any edges*/
/* ---springs */
}/*omit on snap */
}/*loop all bp's*/
+return 0; /*done fine*/
+}
+
+void *exec_softbody_calc_forces(void *data)
+{
+ SB_thread_context *pctx = (SB_thread_context*)data;
+ _softbody_calc_forces_slice_in_a_thread(pctx->ob,pctx->forcetime,pctx->timenow,pctx->ifirst,pctx->ilast,NULL,pctx->do_effector,pctx->do_deflector,pctx->fieldfactor,pctx->windfactor);
+ return 0;
+}
+
+void sb_cf_threads_run(struct Object *ob, float forcetime, float timenow,int totpoint,int *ptr_to_break_func(),struct ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor)
+{
+ ListBase threads;
+ SB_thread_context *sb_threads;
+ int i, totthread,left,dec;
+ int lowpoints =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
+
+ /* figure the number of threads while preventing pretty pointless threading overhead */
+ if(totpoint < lowpoints) {totthread=1;}
+ else{
+ if(G.scene->r.mode & R_FIXED_THREADS)
+ totthread= G.scene->r.threads;
+ else
+ totthread= BLI_system_thread_count();
+ }
+ /*left to do--> what if we got zillions of CPUs running but 'totpoint' tasks to spread*/
+
+ sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBThread");
+ memset(sb_threads, 0, sizeof(SB_thread_context)*totthread);
+ left = totpoint;
+ dec = totpoint/totthread +1;
+ for(i=0; i<totthread; i++) {
+ sb_threads[i].ob = ob;
+ sb_threads[i].forcetime = forcetime;
+ sb_threads[i].timenow = timenow;
+ sb_threads[i].ilast = left;
+ left = left - dec;
+ if (left >0){
+ sb_threads[i].ifirst = left;
+ }
+ else
+ sb_threads[i].ifirst = 0;
+ sb_threads[i].do_effector = do_effector;
+ sb_threads[i].do_deflector = do_deflector;
+ sb_threads[i].fieldfactor = fieldfactor;
+ sb_threads[i].windfactor = windfactor;
+ sb_threads[i].nr= i;
+ sb_threads[i].tot= totthread;
+ }
+
+
+ if(totthread > 1) {
+ BLI_init_threads(&threads, exec_softbody_calc_forces, totthread);
+
+ for(i=0; i<totthread; i++)
+ BLI_insert_thread(&threads, &sb_threads[i]);
+
+ BLI_end_threads(&threads);
+ }
+ else
+ exec_softbody_calc_forces(&sb_threads[0]);
+ /* clean up */
+ MEM_freeN(sb_threads);
+}
+
+static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, int nl_flags)
+{
+/* rule we never alter free variables :bp->vec bp->pos in here !
+ * this will ruin adaptive stepsize AKA heun! (BM)
+ */
+ SoftBody *sb= ob->soft; /* is supposed to be there */
+ BodyPoint *bproot;
+ ListBase *do_effector;
+ float iks, gravity;
+ float fieldfactor = 1000.0f, windfactor = 250.0f;
+ int do_deflector,do_selfcollision,do_springcollision,do_aero;
+
+ gravity = sb->grav * sb_grav_force_scale(ob);
+
+ /* check conditions for various options */
+ do_deflector= query_external_colliders(ob);
+ do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
+ 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 */
+ bproot= sb->bpoint; /* need this for proper spring addressing */
+
+ if (do_springcollision || do_aero)
+ sb_sfesf_threads_run(ob,timenow,sb->totspring,NULL);
+
+ /* after spring scan because it uses Effoctors too */
+ do_effector= pdInitEffectors(ob,NULL);
+ if (do_deflector) {
+ float defforce[3];
+ do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
+ }
+
+ sb_cf_threads_run(ob,forcetime,timenow,sb->totpoint,NULL,do_effector,do_deflector,fieldfactor,windfactor);
/* finally add forces caused by face collision */
if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow);
/* finish matrix and solve */
-#if (0) // remove onl linking for now .. still i am not sure .. the jacobian can be usefull .. so keep that BM
- if(nl_flags & NLF_SOLVE){
- //double sct,sst=PIL_check_seconds_timer();
- for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- int iv =3*(sb->totpoint-a);
- int ip =3*(2*sb->totpoint-a);
- int n;
- for (n=0;n<3;n++) {nlRightHandSideSet(0, iv+n, bp->force[0+n]);}
- for (n=0;n<3;n++) {nlRightHandSideSet(0, ip+n, bp->vec[0+n]);}
+ if(do_effector) pdEndEffectors(do_effector);
+}
+
+
+
+
+static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags)
+{
+ /* redirection to the new threaded Version */
+ if (G.rt !=16){
+ softbody_calc_forcesEx(ob, forcetime, timenow, nl_flags);
+ return;
+ }
+ else{
+ /* so the following will die */
+ /* |||||||||||||||||||||||||| */
+ /* VVVVVVVVVVVVVVVVVVVVVVVVVV */
+
+ /* rule we never alter free variables :bp->vec bp->pos in here !
+ * this will ruin adaptive stepsize AKA heun! (BM)
+ */
+ SoftBody *sb= ob->soft; /* is supposed to be there */
+ BodyPoint *bp;
+ BodyPoint *bproot;
+ BodySpring *bs;
+ ListBase *do_effector;
+ float iks, ks, kd, gravity;
+ float fieldfactor = 1000.0f, windfactor = 250.0f;
+ float tune = sb->ballstiff;
+ int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero;
+
+
+ /* jacobian
+ NLboolean success;
+
+ if(nl_flags){
+ nlBegin(NL_SYSTEM);
+ nlBegin(NL_MATRIX);
}
- nlEnd(NL_MATRIX);
- nlEnd(NL_SYSTEM);
+ */
+
+
+ gravity = sb->grav * sb_grav_force_scale(ob);
+
+ /* check conditions for various options */
+ do_deflector= query_external_colliders(ob);
+ do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
+ 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 */
+ bproot= sb->bpoint; /* need this for proper spring addressing */
- if ((G.rt >0) && (nl_flags & NLF_BUILD))
- {
- printf("####MEE#####\n");
- nlPrintMatrix();
+ if (do_springcollision || do_aero) scan_for_ext_spring_forces(ob,timenow);
+ /* after spring scan because it uses Effoctors too */
+ do_effector= pdInitEffectors(ob,NULL);
+
+ if (do_deflector) {
+ float defforce[3];
+ do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
}
- success= nlSolveAdvanced(NULL, 1);
+ for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ /* clear forces accumulator */
+ bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
+ if(nl_flags & NLF_BUILD){
+ //int ia =3*(sb->totpoint-a);
+ //int op =3*sb->totpoint;
+ /* dF/dV = v */
+ /* jacobioan
+ nlMatrixAdd(op+ia,ia,-forcetime);
+ nlMatrixAdd(op+ia+1,ia+1,-forcetime);
+ nlMatrixAdd(op+ia+2,ia+2,-forcetime);
+
+ nlMatrixAdd(ia,ia,1);
+ nlMatrixAdd(ia+1,ia+1,1);
+ nlMatrixAdd(ia+2,ia+2,1);
+
+ nlMatrixAdd(op+ia,op+ia,1);
+ nlMatrixAdd(op+ia+1,op+ia+1,1);
+ nlMatrixAdd(op+ia+2,op+ia+2,1);
+ */
- // nlPrintMatrix(); /* for debug purpose .. anyhow cropping B vector looks like working */
- if(success){
- float f;
- int index =0;
- /* for debug purpose .. anyhow cropping B vector looks like working */
- if (G.rt >0)
- for(a=2*sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- f=nlGetVariable(0,index);
- printf("(%f ",f);index++;
- f=nlGetVariable(0,index);
- printf("%f ",f);index++;
- f=nlGetVariable(0,index);
- printf("%f)",f);index++;
+
+ }
+
+ /* naive ball self collision */
+ /* needs to be done if goal snaps or not */
+ if(do_selfcollision){
+ int attached;
+ BodyPoint *obp;
+ int c,b;
+ float velcenter[3],dvel[3],def[3];
+ float distance;
+ float compare;
+
+ for(c=sb->totpoint, obp= sb->bpoint; c>=a; c--, obp++) {
+
+ //if ((bp->octantflag & obp->octantflag) == 0) continue;
+
+ compare = (obp->colball + bp->colball);
+ VecSubf(def, bp->pos, obp->pos);
+
+ /* rather check the AABBoxes before ever calulating the real distance */
+ /* mathematically it is completly nuts, but performace is pretty much (3) times faster */
+ if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
+
+ distance = Normalize(def);
+ if (distance < compare ){
+ /* exclude body points attached with a spring */
+ attached = 0;
+ for(b=obp->nofsprings;b>0;b--){
+ bs = sb->bspring + obp->springs[b-1];
+ if (( sb->totpoint-a == bs->v2) || ( sb->totpoint-a == bs->v1)){
+ attached=1;
+ continue;}
+ }
+ if (!attached){
+ float f = tune/(distance) + tune/(compare*compare)*distance - 2.0f*tune/compare ;
+
+ VecMidf(velcenter, bp->vec, obp->vec);
+ VecSubf(dvel,velcenter,bp->vec);
+ VecMulf(dvel,sb->nodemass);
+
+ Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
+ Vec3PlusStVec(bp->force,sb->balldamp,dvel);
+
+ if(nl_flags & NLF_BUILD){
+ //int ia =3*(sb->totpoint-a);
+ //int ic =3*(sb->totpoint-c);
+ //int op =3*sb->totpoint;
+ //float mvel = forcetime*sb->nodemass*sb->balldamp;
+ //float mpos = forcetime*tune*(1.0f-sb->balldamp);
+ /*some quick and dirty entries to the jacobian*/
+ //dfdx_goal(ia,ia,op,mpos);
+ //dfdv_goal(ia,ia,mvel);
+ /* exploit force(a,b) == -force(b,a) part1/2 */
+ //dfdx_goal(ic,ic,op,mpos);
+ //dfdv_goal(ic,ic,mvel);
+
+
+ /*TODO sit down an X-out the true jacobian entries*/
+ /*well does not make to much sense because the eigenvalues
+ of the jacobian go negative; and negative eigenvalues
+ on a complex iterative system z(n+1)=A * z(n)
+ give imaginary roots in the charcateristic polynom
+ --> solutions that to z(t)=u(t)* exp ( i omega t) --> oscilations we don't want here
+ where u(t) is a unknown amplitude function (worst case rising fast)
+ */
+ }
+
+ /* exploit force(a,b) == -force(b,a) part2/2 */
+ VecSubf(dvel,velcenter,obp->vec);
+ VecMulf(dvel,sb->nodemass);
+
+ Vec3PlusStVec(obp->force,sb->balldamp,dvel);
+ Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
+
+
+ }
+ }
}
+ }
+ /* naive ball self collision done */
- index =0;
- for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ if(bp->goal < SOFTGOALSNAP){ /* ommit this bp when it snaps */
+ float auxvect[3];
+ float velgoal[3];
+
+ /* do goal stuff */
+ if(ob->softflag & OB_SB_GOAL) {
+ /* true elastic goal */
+ VecSubf(auxvect,bp->pos,bp->origT);
+ ks = 1.0f/(1.0f- bp->goal*sb->goalspring)-1.0f ;
+ bp->force[0]+= -ks*(auxvect[0]);
+ bp->force[1]+= -ks*(auxvect[1]);
+ bp->force[2]+= -ks*(auxvect[2]);
+
+ if(nl_flags & NLF_BUILD){
+ //int ia =3*(sb->totpoint-a);
+ //int op =3*(sb->totpoint);
+ /* depending on my pos */
+ //dfdx_goal(ia,ia,op,ks*forcetime);
+ }
+
+
+ /* calulate damping forces generated by goals*/
+ VecSubf(velgoal,bp->origS, bp->origE);
+ kd = sb->goalfrict * sb_fric_force_scale(ob) ;
+ VecAddf(auxvect,velgoal,bp->vec);
+
+ if (forcetime > 0.0 ) { /* make sure friction does not become rocket motor on time reversal */
+ bp->force[0]-= kd * (auxvect[0]);
+ bp->force[1]-= kd * (auxvect[1]);
+ bp->force[2]-= kd * (auxvect[2]);
+ if(nl_flags & NLF_BUILD){
+ //int ia =3*(sb->totpoint-a);
+ Normalize(auxvect);
+ /* depending on my vel */
+ //dfdv_goal(ia,ia,kd*forcetime);
+ }
+
+ }
+ else {
+ bp->force[0]-= kd * (velgoal[0] - bp->vec[0]);
+ bp->force[1]-= kd * (velgoal[1] - bp->vec[1]);
+ bp->force[2]-= kd * (velgoal[2] - bp->vec[2]);
+ }
+ }
+ /* done goal stuff */
+
+
+ /* gravitation */
+ bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */
+ //bp->force[1]-= gravity*sb->nodemass; /* individual mass of node here */
+
+
+ /* particle field & vortex */
+ if(do_effector) {
+ float force[3]= {0.0f, 0.0f, 0.0f};
+ float speed[3]= {0.0f, 0.0f, 0.0f};
+ float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
+
+ pdDoEffectors(do_effector, bp->pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);
+
+ /* apply forcefield*/
+ VecMulf(force,fieldfactor* eval_sb_fric_force_scale);
+ VECADD(bp->force, bp->force, force);
+
+ /* BP friction in moving media */
+ kd= sb->mediafrict* eval_sb_fric_force_scale;
+ bp->force[0] -= kd * (bp->vec[0] + windfactor*speed[0]/eval_sb_fric_force_scale);
+ bp->force[1] -= kd * (bp->vec[1] + windfactor*speed[1]/eval_sb_fric_force_scale);
+ bp->force[2] -= kd * (bp->vec[2] + windfactor*speed[2]/eval_sb_fric_force_scale);
+ /* now we'll have nice centrifugal effect for vortex */
+
+ }
+ else {
+ /* BP friction in media (not) moving*/
+ kd= sb->mediafrict* sb_fric_force_scale(ob);
+ /* assume it to be proportional to actual velocity */
+ bp->force[0]-= bp->vec[0]*kd;
+ bp->force[1]-= bp->vec[1]*kd;
+ bp->force[2]-= bp->vec[2]*kd;
+ /* friction in media done */
+ if(nl_flags & NLF_BUILD){
+ //int ia =3*(sb->totpoint-a);
+ /* da/dv = */
+
+ // nlMatrixAdd(ia,ia,forcetime*kd);
+ // nlMatrixAdd(ia+1,ia+1,forcetime*kd);
+ // nlMatrixAdd(ia+2,ia+2,forcetime*kd);
+ }
+
+ }
+ /* +++cached collision targets */
+ bp->choke = 0.0f;
+ bp->choke2 = 0.0f;
+ bp->flag &= ~SBF_DOFUZZY;
+ if(do_deflector) {
+ float cfforce[3],defforce[3] ={0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}, facenormal[3], cf = 1.0f,intrusion;
+ kd = 1.0f;
+
+ if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){
+ if ((!nl_flags)&&(intrusion < 0.0f)){
+ /*bjornmose: uugh.. what an evil hack
+ violation of the 'don't touch bp->pos in here' rule
+ but works nice, like this-->
+ we predict the solution beeing out of the collider
+ in heun step No1 and leave the heun step No2 adapt to it
+ so we kind of introduced a implicit solver for this case
+ */
+ Vec3PlusStVec(bp->pos,-intrusion,facenormal);
+
+ sb->scratch->flag |= SBF_DOFUZZY;
+ bp->flag |= SBF_DOFUZZY;
+ bp->choke = sb->choke*0.01f;
+ }
+ else{
+ VECSUB(cfforce,bp->vec,vel);
+ Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
+ }
+ Vec3PlusStVec(bp->force,kd,defforce);
+ if (nl_flags & NLF_BUILD){
+ // int ia =3*(sb->totpoint-a);
+ // int op =3*sb->totpoint;
+ //dfdx_goal(ia,ia,op,mpos); // don't do unless you know
+ //dfdv_goal(ia,ia,-cf);
+
+ }
+
+ }
+
+ }
+ /* ---cached collision targets */
+
+ /* +++springs */
+ if(ob->softflag & OB_SB_EDGES) {
+ if (sb->bspring){ /* spring list exists at all ? */
+ for(b=bp->nofsprings;b>0;b--){
+ bs = sb->bspring + bp->springs[b-1];
+ if (do_springcollision || do_aero){
+ VecAddf(bp->force,bp->force,bs->ext_force);
+ if (bs->flag & BSF_INTERSECT)
+ bp->choke = bs->cf;
+
+ }
+ // sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags)
+ // rather remove nl_falgs from code .. will make things a lot cleaner
+ sb_spring_force(ob,sb->totpoint-a,bs,iks,forcetime,0);
+ }/* loop springs */
+ }/* existing spring list */
+ }/*any edges*/
+ /* ---springs */
+ }/*omit on snap */
+ }/*loop all bp's*/
+
+
+ /* finally add forces caused by face collision */
+ if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow);
+
+ /* finish matrix and solve */
+#if (0) // remove onl linking for now .. still i am not sure .. the jacobian can be usefull .. so keep that BM
+ if(nl_flags & NLF_SOLVE){
+ //double sct,sst=PIL_check_seconds_timer();
+ for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ int iv =3*(sb->totpoint-a);
+ int ip =3*(2*sb->totpoint-a);
+ int n;
+ for (n=0;n<3;n++) {nlRightHandSideSet(0, iv+n, bp->force[0+n]);}
+ for (n=0;n<3;n++) {nlRightHandSideSet(0, ip+n, bp->vec[0+n]);}
+ }
+ nlEnd(NL_MATRIX);
+ nlEnd(NL_SYSTEM);
+
+ if ((G.rt == 32) && (nl_flags & NLF_BUILD))
+ {
+ printf("####MEE#####\n");
+ nlPrintMatrix();
+ }
+
+ success= nlSolveAdvanced(NULL, 1);
+
+ // nlPrintMatrix(); /* for debug purpose .. anyhow cropping B vector looks like working */
+ if(success){
+ float f;
+ int index =0;
+ /* for debug purpose .. anyhow cropping B vector looks like working */
+ if (G.rt ==32)
+ for(a=2*sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ f=nlGetVariable(0,index);
+ printf("(%f ",f);index++;
+ f=nlGetVariable(0,index);
+ printf("%f ",f);index++;
+ f=nlGetVariable(0,index);
+ printf("%f)",f);index++;
+ }
+
+ index =0;
+ for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ f=nlGetVariable(0,index);
+ bp->impdv[0] = f; index++;
+ f=nlGetVariable(0,index);
+ bp->impdv[1] = f; index++;
+ f=nlGetVariable(0,index);
+ bp->impdv[2] = f; index++;
+ }
+ /*
+ for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
f=nlGetVariable(0,index);
- bp->impdv[0] = f; index++;
+ bp->impdx[0] = f; index++;
f=nlGetVariable(0,index);
- bp->impdv[1] = f; index++;
+ bp->impdx[1] = f; index++;
f=nlGetVariable(0,index);
- bp->impdv[2] = f; index++;
- }
- /*
+ bp->impdx[2] = f; index++;
+ }
+ */
+ }
+ else{
+ printf("Matrix inversion failed \n");
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- f=nlGetVariable(0,index);
- bp->impdx[0] = f; index++;
- f=nlGetVariable(0,index);
- bp->impdx[1] = f; index++;
- f=nlGetVariable(0,index);
- bp->impdx[2] = f; index++;
+ VECCOPY(bp->impdv,bp->force);
}
- */
- }
- else{
- printf("Matrix inversion failed \n");
- for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- VECCOPY(bp->impdv,bp->force);
+
}
+ //sct=PIL_check_seconds_timer();
+ //if (sct-sst > 0.01f) printf(" implicit solver time %f %s \r",sct-sst,ob->id.name);
}
-
- //sct=PIL_check_seconds_timer();
- //if (sct-sst > 0.01f) printf(" implicit solver time %f %s \r",sct-sst,ob->id.name);
- }
- /* cleanup */
+ /* cleanup */
#endif
- if(do_effector) pdEndEffectors(do_effector);
+ if(do_effector) pdEndEffectors(do_effector);
+ }
}
+
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err, int mid_flags)
{
/* time evolution */
@@ -2458,7 +2870,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
/* x(t + dt) = x(t) + v(t~) * dt */
VecMulf(dx,forcetime);
- /* the freezer */
+ /* the freezer coming sooner or later */
/*
if ((Inpf(dx,dx)<freezeloc )&&(Inpf(bp->force,bp->force)<freezeforce )){
bp->frozen /=2;
@@ -3529,6 +3941,7 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime)
* we don't want to lock up the system if physics fail
*/
int loops =0 ;
+
SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */
if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops;
@@ -3546,13 +3959,13 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime)
sb->scratch->flag &= ~SBF_DOFUZZY;
/* do predictive euler step */
softbody_calc_forces(ob, forcetime,timedone/dtime,0);
- softbody_apply_forces(ob, forcetime, 1, NULL,mid_flags);
+ softbody_apply_forces(ob, forcetime, 1, NULL,mid_flags);
/* crop new slope values to do averaged slope step */
softbody_calc_forces(ob, forcetime,timedone/dtime,0);
- softbody_apply_forces(ob, forcetime, 2, &err,mid_flags);
+ softbody_apply_forces(ob, forcetime, 2, &err,mid_flags);
softbody_apply_goalsnap(ob);
if (err > SoftHeunTol) { /* error needs to be scaled to some quantity */
@@ -3603,7 +4016,7 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime)
// if(G.f & G_DEBUG){
if(sb->solverflags & SBSO_MONITOR ){
if (loops > HEUNWARNLIMIT) /* monitor high loop counts */
- printf("\r needed %d steps/frame ",loops);
+ printf("\r needed %d steps/frame",loops);
}
}
@@ -3627,7 +4040,7 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime)
if(sb->solverflags & SBSO_MONITOR ){
sct=PIL_check_seconds_timer();
- if (sct-sst > 0.5f) printf(" solver time %f %s \r",sct-sst,ob->id.name);
+ if (sct-sst > 0.5f) printf(" solver time %f sec %s \n",sct-sst,ob->id.name);
}
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 37804bf68ac..936381c85cc 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -53,6 +53,7 @@
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -544,6 +545,8 @@ Tex *copy_texture(Tex *tex)
if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima);
else texn->ima= 0;
+ id_us_plus((ID *)texn->ipo);
+
if(texn->plugin) {
texn->plugin= MEM_dupallocN(texn->plugin);
open_plugin_tex(texn->plugin);
@@ -731,7 +734,7 @@ Tex *give_current_texture(Object *ob, int act)
bNode *node;
if(ob==0) return 0;
- if(ob->totcol==0) return 0;
+ if(ob->totcol==0 && !(ob->type==OB_LAMP)) return 0;
if(ob->type==OB_LAMP) {
la=(Lamp *)ob->data;
@@ -775,6 +778,18 @@ Tex *give_current_texture(Object *ob, int act)
return tex;
}
+Tex *give_current_world_texture(void)
+{
+ MTex *mtex = 0;
+ Tex *tex = 0;
+
+ if(!(G.scene->world)) return 0;
+
+ mtex= G.scene->world->mtex[(int)(G.scene->world->texact)];
+ if(mtex) tex= mtex->tex;
+
+ return tex;
+}
/* ------------------------------------------------------------------------- */
@@ -832,3 +847,19 @@ void BKE_free_envmap(EnvMap *env)
}
/* ------------------------------------------------------------------------- */
+int BKE_texture_dependsOnTime(const struct Tex *texture)
+{
+ if(texture->plugin) {
+ // assume all plugins depend on time
+ return 1;
+ } else if( texture->ima &&
+ ELEM(texture->ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ return 1;
+ } else if(texture->ipo) {
+ // assume any ipo means the texture is animated
+ return 1;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */