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
path: root/source
diff options
context:
space:
mode:
authorAndre Susano Pinto <andresusanopinto@gmail.com>2008-08-22 02:57:25 +0400
committerAndre Susano Pinto <andresusanopinto@gmail.com>2008-08-22 02:57:25 +0400
commitf4ae23f3794605f5b7c0a5b90d982d6dfd20d492 (patch)
tree0f1c725f89be062437f0114d5ef1a2fe501fd600 /source
parenta06321d55c2f25440120ac2fdead20639863a608 (diff)
svn merge -r 16174:16215 https://svn.blender.org/svnroot/bf-blender/trunk/blender
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_collision.h11
-rw-r--r--source/blender/blenkernel/BKE_effect.h2
-rw-r--r--source/blender/blenkernel/intern/collision.c68
-rw-r--r--source/blender/blenkernel/intern/effect.c133
-rw-r--r--source/blender/blenkernel/intern/implicit.c2
-rw-r--r--source/blender/blenkernel/intern/ipo.c8
-rw-r--r--source/blender/blenkernel/intern/modifier.c2
-rw-r--r--source/blender/blenkernel/intern/particle.c9
-rw-r--r--source/blender/blenkernel/intern/particle_system.c83
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/include/BIF_resources.h4
-rw-r--r--source/blender/makesdna/DNA_ipo_types.h8
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h3
-rw-r--r--source/blender/makesdna/DNA_object_force.h4
-rw-r--r--source/blender/makesdna/DNA_particle_types.h3
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h5
-rw-r--r--source/blender/python/api2_2x/Material.c92
-rw-r--r--source/blender/python/api2_2x/Mesh.c4
-rw-r--r--source/blender/python/api2_2x/Object.c37
-rw-r--r--source/blender/python/api2_2x/doc/Material.py19
-rw-r--r--source/blender/python/api2_2x/doc/Object.py8
-rw-r--r--source/blender/src/buttons_object.c110
-rw-r--r--source/blender/src/drawipo.c52
-rw-r--r--source/blender/src/editipo.c19
-rw-r--r--source/blender/src/editipo_lib.c3
-rw-r--r--source/blender/src/resources.c19
-rw-r--r--source/blender/src/space.c3
-rw-r--r--source/blender/src/usiblender.c10
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp31
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp49
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.h31
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp19
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp339
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp31
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h6
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp294
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h69
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp5
-rw-r--r--source/gameengine/Physics/Bullet/SConscript2
-rw-r--r--source/gameengine/Physics/common/PHY_DynamicTypes.h12
43 files changed, 1066 insertions, 551 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index e1eb6718a30..e403fc33e06 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 247
-#define BLENDER_SUBVERSION 0
+#define BLENDER_SUBVERSION 1
#define BLENDER_MINVERSION 245
#define BLENDER_MINSUBVERSION 15
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 2966d932a49..c483148e4de 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -119,8 +119,10 @@ FaceCollPair;
/////////////////////////////////////////////////
// used in modifier.c from collision.c
/////////////////////////////////////////////////
+
BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon );
void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving );
+
/////////////////////////////////////////////////
LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr );
@@ -134,6 +136,15 @@ void collisions_compute_barycentric ( float pv[3], float p1[3], float p2[3], flo
void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 );
/////////////////////////////////////////////////
+// used in effect.c
+/////////////////////////////////////////////////
+CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj);
+
+/////////////////////////////////////////////////
+
+
+
+/////////////////////////////////////////////////
#endif
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index 3b4c3198179..6475f7a71ac 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -66,7 +66,7 @@ void pdEndEffectors(struct ListBase *lb);
void pdDoEffectors(struct ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags);
/* required for particle_system.c */
-void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise);
+void do_physical_effector(Object *ob, float *opco, short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, float charge, float pa_size);
float effector_falloff(struct PartDeflect *pd, float *eff_velocity, float *vec_to_part);
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index cfcab54058d..b5e09d551f0 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -31,10 +31,11 @@
#include "BKE_cloth.h"
-#include "DNA_group_types.h"
-#include "DNA_object_types.h"
#include "DNA_cloth_types.h"
+#include "DNA_group_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
#include "DNA_scene_types.h"
#include "BKE_DerivedMesh.h"
@@ -1307,9 +1308,34 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
for ( base = G.scene->base.first; base; base = base->next )
{
coll_ob = base->object;
- collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
-
- if ( !collmd )
+
+ if(coll_ob->pd && coll_ob->pd->deflect)
+ {
+ collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+ }
+
+ if ( collmd )
+ {
+ if(coll_ob == self)
+ continue;
+
+ if(numobj >= maxobj)
+ {
+ // realloc
+ int oldmax = maxobj;
+ CollisionModifierData **tmp;
+ maxobj *= 2;
+ tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
+ memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax);
+ MEM_freeN(objs);
+ objs = tmp;
+
+ }
+
+ objs[numobj] = collmd;
+ numobj++;
+ }
+ else
{
if ( coll_ob->dup_group )
{
@@ -1319,8 +1345,12 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
for ( go= group->gobject.first; go; go= go->next )
{
coll_ob = go->ob;
-
- collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+ collmd = NULL;
+
+ if(coll_ob->pd && coll_ob->pd->deflect)
+ {
+ collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+ }
if ( !collmd )
continue;
@@ -1347,27 +1377,6 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
numobj++;
}
}
- }
- else
- {
- if(coll_ob == self)
- continue;
-
- if(numobj >= maxobj)
- {
- // realloc
- int oldmax = maxobj;
- CollisionModifierData **tmp;
- maxobj *= 2;
- tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
- memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax);
- MEM_freeN(objs);
- objs = tmp;
-
- }
-
- objs[numobj] = collmd;
- numobj++;
}
}
*numcollobj = numobj;
@@ -1484,6 +1493,9 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f
BVHTreeOverlap *overlap = NULL;
int result = 0;
+ if(!collmd->bvhtree)
+ continue;
+
/* move object to position (step) in time */
collision_move_object ( collmd, step + dt, step );
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 7620edac126..0842e55a0ea 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -59,6 +59,7 @@
#include "BKE_armature.h"
#include "BKE_bad_level_calls.h"
#include "BKE_blender.h"
+#include "BKE_collision.h"
#include "BKE_constraint.h"
#include "BKE_deform.h"
#include "BKE_depsgraph.h"
@@ -228,6 +229,60 @@ void pdEndEffectors(ListBase *lb)
/* Effectors */
/************************************************/
+// triangle - ray callback function
+static void eff_tri_ray_hit(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ // whenever we hit a bounding box, we don't check further
+ hit->dist = -1;
+ hit->index = 1;
+}
+
+// get visibility of a wind ray
+static float eff_calc_visibility(Object *ob, float *co, float *dir)
+{
+ CollisionModifierData **collobjs = NULL;
+ int numcollobj = 0, i;
+ float norm[3], len = 0.0;
+ float visibility = 1.0;
+
+ collobjs = get_collisionobjects(ob, &numcollobj);
+
+ if(!collobjs)
+ return 0;
+
+ VECCOPY(norm, dir);
+ VecMulf(norm, -1.0);
+ len = Normalize(norm);
+
+ // check all collision objects
+ for(i = 0; i < numcollobj; i++)
+ {
+ CollisionModifierData *collmd = collobjs[i];
+
+ if(collmd->bvhtree)
+ {
+ BVHTreeRayHit hit;
+
+ hit.index = -1;
+ hit.dist = len + FLT_EPSILON;
+
+ // check if the way is blocked
+ if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, &hit, eff_tri_ray_hit, NULL)>=0)
+ {
+ // visibility is only between 0 and 1, calculated from 1-absorption
+ visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01)));
+
+ if(visibility <= 0.0f)
+ break;
+ }
+ }
+ }
+
+ MEM_freeN(collobjs);
+
+ return visibility;
+}
+
// noise function for wind e.g.
static float wind_func(struct RNG *rng, float strength)
{
@@ -277,7 +332,10 @@ float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part)
{
float eff_dir[3], temp[3];
float falloff=1.0, fac, r_fac;
-
+
+ if(pd->forcefield==PFIELD_LENNARDJ)
+ return falloff; /* Lennard-Jones field has it's own falloff built in */
+
VecCopyf(eff_dir,eff_velocity);
Normalize(eff_dir);
@@ -314,12 +372,18 @@ float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part)
return falloff;
}
-void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise)
+void do_physical_effector(Object *ob, float *opco, short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, float charge, float pa_size)
{
float mag_vec[3]={0,0,0};
float temp[3], temp2[3];
float eff_vel[3];
- float wind = 0;
+ float noise = 0, visibility;
+
+ // calculate visibility
+ visibility = eff_calc_visibility(ob, opco, vec_to_part);
+ if(visibility <= 0.0)
+ return;
+ falloff *= visibility;
VecCopyf(eff_vel,eff_velocity);
Normalize(eff_vel);
@@ -328,11 +392,11 @@ void do_physical_effector(short type, float force_val, float distance, float fal
case PFIELD_WIND:
VECCOPY(mag_vec,eff_vel);
- // add wind noise here
- if(noise> 0.0f)
- wind = wind_func(rng, noise);
-
- VecMulf(mag_vec,(force_val+wind)*falloff);
+ // add wind noise here, only if we have wind
+ if((noise_factor > 0.0f) && (force_val > FLT_EPSILON))
+ noise = wind_func(rng, noise_factor);
+
+ VecMulf(mag_vec,(force_val+noise)*falloff);
VecAddf(field,field,mag_vec);
break;
@@ -381,19 +445,46 @@ void do_physical_effector(short type, float force_val, float distance, float fal
VecMulf(mag_vec,damp*1.9f*(float)sqrt(force_val));
VecSubf(field,field,mag_vec);
break;
- case PFIELD_NUCLEAR:
- /*pow here is root of cosine expression below*/
- //rad=(float)pow(2.0,-1.0/power)*distance/size;
- //VECCOPY(mag_vec,vec_to_part);
- //Normalize(mag_vec);
- //VecMulf(mag_vec,(float)cos(3.0*M_PI/2.0*(1.0-1.0/(pow(rad,power)+1.0)))/(rad+0.2f));
- //VECADDFAC(field,field,mag_vec,force_val);
+ case PFIELD_CHARGE:
+ if(planar)
+ Projf(mag_vec,vec_to_part,eff_vel);
+ else
+ VecCopyf(mag_vec,vec_to_part);
+
+ VecMulf(mag_vec,charge*force_val*falloff);
+ VecAddf(field,field,mag_vec);
break;
- }
-}
+ case PFIELD_LENNARDJ:
+ {
+ float fac;
+
+ if(planar) {
+ Projf(mag_vec,vec_to_part,eff_vel);
+ distance = VecLength(mag_vec);
+ }
+ else
+ VecCopyf(mag_vec,vec_to_part);
+
+ /* at this distance the field is 60 times weaker than maximum */
+ if(distance > 2.22 * (size+pa_size))
+ break;
+ fac = pow((size+pa_size)/distance,6.0);
+
+ fac = - fac * (1.0 - fac) / distance;
+ /* limit the repulsive term drastically to avoid huge forces */
+ fac = ((fac>2.0) ? 2.0 : fac);
+ /* 0.003715 is the fac value at 2.22 times (size+pa_size),
+ substracted to avoid discontinuity at the border
+ */
+ VecMulf(mag_vec, force_val * (fac-0.0037315));
+ VecAddf(field,field,mag_vec);
+ break;
+ }
+ }
+}
/* -------- pdDoEffectors() --------
generic force/speed system, now used for particles and softbodies
@@ -451,16 +542,16 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float
VecSubf(vec_to_part, opco, ob->obmat[3]);
distance = VecLength(vec_to_part);
- falloff=effector_falloff(pd,ob->obmat[2],vec_to_part);
-
+ falloff=effector_falloff(pd,ob->obmat[2],vec_to_part);
+
if(falloff<=0.0f)
; /* don't do anything */
else {
float field[3]={0,0,0}, tmp[3];
VECCOPY(field, force);
- do_physical_effector(pd->forcefield,pd->f_strength,distance,
+ do_physical_effector(ob, opco, pd->forcefield,pd->f_strength,distance,
falloff,pd->f_dist,pd->f_damp,ob->obmat[2],vec_to_part,
- speed,force,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise);
+ speed,force,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise, 0.0f, 0.0f);
// for softbody backward compatibility
if(flags & PE_WIND_AS_SPEED){
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 0375ab22909..93e35a4db06 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1451,7 +1451,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec
float triunnormal[3]={0,0,0}; // not-normalized-triangle normal
float tmp[3]={0,0,0};
float factor = (mfaces[i].v4) ? 0.25 : 1.0 / 3.0;
- factor *= 0.05;
+ factor *= 0.02;
// calculate face normal
if(mfaces[i].v4)
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index fe92edfbbd5..4af25ee99e7 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -182,7 +182,7 @@ int part_ar[PART_TOTIPO]= {
PART_EMIT_FREQ, PART_EMIT_LIFE, PART_EMIT_VEL, PART_EMIT_AVE, PART_EMIT_SIZE,
PART_AVE, PART_SIZE, PART_DRAG, PART_BROWN, PART_DAMP, PART_LENGTH, PART_CLUMP,
PART_GRAV_X, PART_GRAV_Y, PART_GRAV_Z, PART_KINK_AMP, PART_KINK_FREQ, PART_KINK_SHAPE,
- PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD
+ PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD, PART_PD2_FSTR, PART_PD2_FFALL, PART_PD2_FMAXD
};
@@ -1614,6 +1614,12 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
poin= (part->pd?(&(part->pd->f_power)):NULL); break;
case PART_PD_FMAXD:
poin= (part->pd?(&(part->pd->maxdist)):NULL); break;
+ case PART_PD2_FSTR:
+ poin= (part->pd2?(&(part->pd2->f_strength)):NULL); break;
+ case PART_PD2_FFALL:
+ poin= (part->pd2?(&(part->pd2->f_power)):NULL); break;
+ case PART_PD2_FMAXD:
+ poin= (part->pd2?(&(part->pd2->maxdist)):NULL); break;
}
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index d08f30ff995..f33f33d9d46 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -5496,7 +5496,7 @@ static void collisionModifier_deformVerts(
numverts = dm->getNumVerts ( dm );
- if(current_time > collmd->time)
+ if((current_time > collmd->time)|| (BKE_ptcache_get_continue_physics()))
{
// check if mesh has changed
if(collmd->x && (numverts != collmd->numverts))
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 643f90637ad..2f4696fc442 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -320,8 +320,14 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
/************************************************/
void psys_free_settings(ParticleSettings *part)
{
- if(part->pd)
+ if(part->pd) {
MEM_freeN(part->pd);
+ part->pd = NULL;
+ }
+ if(part->pd2) {
+ MEM_freeN(part->pd2);
+ part->pd2 = NULL;
+ }
}
void free_hair(ParticleSystem *psys, int softbody)
@@ -3015,6 +3021,7 @@ ParticleSettings *psys_copy_settings(ParticleSettings *part)
partn= copy_libblock(part);
if(partn->pd) partn->pd= MEM_dupallocN(part->pd);
+ if(partn->pd2) partn->pd2= MEM_dupallocN(part->pd2);
return partn;
}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 60fdbca2021..ef8373ee977 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -60,6 +60,7 @@
#include "BKE_bad_level_calls.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_displist.h"
+#include "BKE_effect.h"
#include "BKE_particle.h"
#include "BKE_global.h"
#include "BKE_utildefines.h"
@@ -2205,6 +2206,9 @@ static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra)
return 1;
}
+/************************************************/
+/* Effectors */
+/************************************************/
static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, short object, float *pa_co, float obmat[4][4], float force_val, float falloff, float *field)
{
TexResult result[4];
@@ -2322,10 +2326,11 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy
for(i=0; epsys; epsys=epsys->next,i++){
type=0;
- if(epsys!=psys){
+ if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){
epart=epsys->part;
- if(epsys->part->pd && epsys->part->pd->forcefield)
+ if((epsys->part->pd && epsys->part->pd->forcefield)
+ || (epsys->part->pd2 && epsys->part->pd2->forcefield))
type=PSYS_EC_PARTICLE;
if(epart->type==PART_REACTOR) {
@@ -2574,35 +2579,31 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
ListBase *lb=&psys->effectors;
ParticleEffectorCache *ec;
float distance, vec_to_part[3];
- float falloff;
+ float falloff, charge = 0.0f;
int p;
/* check all effector objects for interaction */
if(lb->first){
+ if(psys->part->pd && psys->part->pd->forcefield==PFIELD_CHARGE){
+ /* Only the charge of the effected particle is used for
+ interaction, not fall-offs. If the fall-offs aren't the
+ same this will be unphysical, but for animation this
+ could be the wanted behavior. If you want physical
+ correctness the fall-off should be spherical 2.0 anyways.
+ */
+ charge = psys->part->pd->f_strength;
+ }
+ if(psys->part->pd2 && psys->part->pd2->forcefield==PFIELD_CHARGE){
+ charge += psys->part->pd2->f_strength;
+ }
for(ec = lb->first; ec; ec= ec->next){
eob= ec->ob;
if(ec->type & PSYS_EC_EFFECTOR){
pd=eob->pd;
if(psys->part->type!=PART_HAIR && psys->part->integrator)
where_is_object_time(eob,cfra);
- /* Get IPO force strength and fall off values here */
- //if (has_ipo_code(eob->ipo, OB_PD_FSTR))
- // force_val = IPO_GetFloatValue(eob->ipo, OB_PD_FSTR, cfra);
- //else
- // force_val = pd->f_strength;
-
- //if (has_ipo_code(eob->ipo, OB_PD_FFALL))
- // ffall_val = IPO_GetFloatValue(eob->ipo, OB_PD_FFALL, cfra);
- //else
- // ffall_val = pd->f_power;
-
- //if (has_ipo_code(eob->ipo, OB_PD_FMAXD))
- // maxdist = IPO_GetFloatValue(eob->ipo, OB_PD_FMAXD, cfra);
- //else
- // maxdist = pd->maxdist;
/* use center of object for distance calculus */
- //obloc= eob->obmat[3];
VecSubf(vec_to_part, state->co, eob->obmat[3]);
distance = VecLength(vec_to_part);
@@ -2615,22 +2616,22 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
pd->flag & PFIELD_TEX_OBJECT, (pd->flag & PFIELD_TEX_ROOTCO) ? rootco : state->co, eob->obmat,
pd->f_strength, falloff, force_field);
} else {
- do_physical_effector(pd->forcefield,pd->f_strength,distance,
- falloff,pd->f_dist,pd->f_damp,eob->obmat[2],vec_to_part,
- pa->state.vel,force_field,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise);
+ do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance,
+ falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part,
+ pa->state.vel,force_field,pd->flag&PFIELD_PLANAR,pd->rng,pd->f_noise,charge,pa->size);
}
}
if(ec->type & PSYS_EC_PARTICLE){
- int totepart;
+ int totepart, i;
epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr);
epart= epsys->part;
- pd= epart->pd;
+ pd=epart->pd;
totepart= epsys->totpart;
if(totepart <= 0)
continue;
- if(pd->forcefield==PFIELD_HARMONIC){
+ if(pd && pd->forcefield==PFIELD_HARMONIC){
/* every particle is mapped to only one harmonic effector particle */
p= pa_no%epsys->totpart;
totepart= p+1;
@@ -2642,31 +2643,27 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
epsys->lattice=psys_get_lattice(ob,psys);
for(; p<totepart; p++){
+ /* particle skips itself as effector */
+ if(epsys==psys && p == pa_no) continue;
+
epa = epsys->particles + p;
estate.time=-1.0;
if(psys_get_particle_state(eob,epsys,p,&estate,0)){
VECSUB(vec_to_part, state->co, estate.co);
distance = VecLength(vec_to_part);
-
- //if(pd->forcefield==PFIELD_HARMONIC){
- // //if(cfra < epa->time + radius){ /* radius is fade-in in ui */
- // // eforce*=(cfra-epa->time)/radius;
- // //}
- //}
- //else{
- // /* Limit minimum distance to effector particle so that */
- // /* the force is not too big */
- // if (distance < 0.001) distance = 0.001f;
- //}
- falloff=effector_falloff(pd,estate.vel,vec_to_part);
+ for(i=0, pd = epart->pd; i<2; i++,pd = epart->pd2) {
+ if(pd==NULL || pd->forcefield==0) continue;
- if(falloff<=0.0f)
- ; /* don't do anything */
- else
- do_physical_effector(pd->forcefield,pd->f_strength,distance,
- falloff,epart->size,pd->f_damp,estate.vel,vec_to_part,
- state->vel,force_field,0, pd->rng, pd->f_noise);
+ falloff=effector_falloff(pd,estate.vel,vec_to_part);
+
+ if(falloff<=0.0f)
+ ; /* don't do anything */
+ else
+ do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance,
+ falloff,epart->size,pd->f_damp,estate.vel,vec_to_part,
+ state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size);
+ }
}
else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){
/* first step after key release */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9d7a0302d45..35ca42a4949 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2589,6 +2589,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
{
part->pd= newdataadr(fd, part->pd);
+ part->pd2= newdataadr(fd, part->pd2);
}
static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles)
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index b462233528a..d596f57990f 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -535,6 +535,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
writestruct(wd, ID_PA, "ParticleSettings", 1, part);
if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
writestruct(wd, DATA, "PartDeflect", 1, part->pd);
+ writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
}
part= part->id.next;
}
diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h
index df514190270..0d27804dd1a 100644
--- a/source/blender/include/BIF_resources.h
+++ b/source/blender/include/BIF_resources.h
@@ -524,6 +524,10 @@ enum {
TH_EDGE_SHARP,
TH_EDITMESH_ACTIVE,
+
+ TH_HANDLE_VERTEX,
+ TH_HANDLE_VERTEX_SELECT,
+ TH_HANDLE_VERTEX_SIZE,
};
/* XXX WARNING: previous is saved in file, so do not change order! */
diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h
index 03ffef3cd55..1e30f3f7640 100644
--- a/source/blender/makesdna/DNA_ipo_types.h
+++ b/source/blender/makesdna/DNA_ipo_types.h
@@ -354,8 +354,8 @@ typedef short IPO_Channel;
/* ******************** */
/* particle ipos */
-#define PART_TOTIPO 22
-#define PART_TOTNAM 22
+#define PART_TOTIPO 25
+#define PART_TOTNAM 25
#define PART_EMIT_FREQ 1
#define PART_EMIT_LIFE 2
@@ -385,6 +385,10 @@ typedef short IPO_Channel;
#define PART_PD_FFALL 21
#define PART_PD_FMAXD 22
+#define PART_PD2_FSTR 23
+#define PART_PD2_FFALL 24
+#define PART_PD2_FMAXD 25
+
/* these are IpoCurve specific */
/* **************** IPO ********************* */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 9ce04c1c272..0f820e88541 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -392,7 +392,8 @@ typedef struct CollisionModifierData {
unsigned int numverts;
unsigned int numfaces;
- int pad;
+ short absorption; /* used for forces, in % */
+ short pad;
float time; /* cfra time of modifier */
struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
} CollisionModifierData;
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 5f6ae7c7f06..5900e16d5e8 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -156,8 +156,8 @@ typedef struct SoftBody {
#define PFIELD_GUIDE 5
#define PFIELD_TEXTURE 6
#define PFIELD_HARMONIC 7
-#define PFIELD_NUCLEAR 8
-#define PFIELD_MDIPOLE 9
+#define PFIELD_CHARGE 8
+#define PFIELD_LENNARDJ 9
/* pd->flag: various settings */
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 4f62cd084cc..363f0075e23 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -166,6 +166,7 @@ typedef struct ParticleSettings {
struct Object *bb_ob;
struct Ipo *ipo;
struct PartDeflect *pd;
+ struct PartDeflect *pd2;
} ParticleSettings;
typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in copy_particlesystem */
@@ -264,6 +265,8 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
#define PART_CHILD_RENDER (1<<29)
#define PART_CHILD_GUIDE (1<<30)
+#define PART_SELF_EFFECT (1<<22)
+
/* part->rotfrom */
#define PART_ROT_KEYS 0 /* interpolate directly from keys */
#define PART_ROT_ZINCR 1 /* same as zdir but done incrementally from previous position */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index cd1c047dac9..856324695a9 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -101,6 +101,11 @@ typedef struct ThemeSpace {
char movie[4], image[4], scene[4], audio[4]; // for sequence editor
char effect[4], plugin[4], transition[4], meta[4];
char editmesh_active[4];
+
+ char handle_vertex[4];
+ char handle_vertex_select[4];
+ char handle_vertex_size;
+ char hpad[7];
} ThemeSpace;
diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c
index ccd24a437b5..20747a167e6 100644
--- a/source/blender/python/api2_2x/Material.c
+++ b/source/blender/python/api2_2x/Material.c
@@ -554,6 +554,7 @@ static int Material_setSssTexScatter( BPy_Material * self, PyObject * value );
static int Material_setSssFront( BPy_Material * self, PyObject * value );
static int Material_setSssBack( BPy_Material * self, PyObject * value );
static int Material_setSssBack( BPy_Material * self, PyObject * value );
+static int Material_setTexChannel( BPy_Material * self, PyObject * value );
static PyObject *Material_getColorComponent( BPy_Material * self,
void * closure );
@@ -633,6 +634,7 @@ static PyObject *Material_getSssBack( BPy_Material * self );
static PyObject *Material_getFilter( BPy_Material * self );
static PyObject *Material_getTranslucency( BPy_Material * self );
static PyObject *Material_getTextures( BPy_Material * self );
+static PyObject *Material_getTexChannel( BPy_Material * self );
static PyObject *Material_clearIpo( BPy_Material * self );
static PyObject *Material_setTexture( BPy_Material * self, PyObject * args );
@@ -1140,7 +1142,11 @@ static PyGetSetDef BPy_Material_getseters[] = {
NULL},
{"lightGroup",
(getter)Material_getLightGroup, (setter)Material_setLightGroup,
- "Set the light group for this material",
+ "The light group for this material",
+ NULL},
+ {"enabledTextures",
+ (getter)Material_getTexChannel, (setter)Material_setTexChannel,
+ "Enabled texture channels for this material",
NULL},
{"R",
(getter)Material_getColorComponent, (setter)Material_setColorComponent,
@@ -1517,6 +1523,36 @@ static PyObject *Material_getLightGroup( BPy_Material * self )
return Group_CreatePyObject( self->material->group );
}
+static PyObject *Material_getTexChannel( BPy_Material * self )
+{
+ int i;
+ short mask = 1;
+ PyObject *list = PyList_New(0);
+ if( !list )
+ return EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "PyList_New() failed" );
+
+ for( i = 0, mask = 1; i < MAX_MTEX ; ++i, mask <<= 1 ) {
+ if( self->material->mtex[i] && (mask & self->material->septex) == 0 ) {
+ PyObject * val = PyInt_FromLong(i);
+ if( !val ) {
+ Py_DECREF( list );
+ return EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "PyInt_FromLong() failed" );
+ }
+ if( PyList_Append( list, val ) < 0 ) {
+ Py_DECREF( val );
+ Py_DECREF( list );
+ return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "PyList_Append() failed" );
+ }
+ Py_DECREF( val );
+ }
+ }
+
+ return list;
+}
+
static PyObject *Material_getHaloSize( BPy_Material * self )
{
return PyFloat_FromDouble( ( double ) self->material->hasize );
@@ -1982,6 +2018,57 @@ static int Material_setLightGroup( BPy_Material * self, PyObject * value )
return GenericLib_assignData(value, (void **) &self->material->group, NULL, 1, ID_GR, 0);
}
+static int Material_setTexChannel( BPy_Material * self, PyObject * value )
+{
+ int i, mask;
+ short septex = 0;
+ int result = 1;
+
+ /* fail if input is not a standard sequence */
+ if( !PyList_Check( value ) && !PyTuple_Check( value ) )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected tuple or list of integers" );
+
+ /* get a fast sequence; in Python 2.5, this just return the original
+ * list or tuple and INCREFs it, so we must DECREF */
+ value = PySequence_Fast( value, "" );
+
+ /* set the disable bit for each existing texture */
+ for( i= 0, mask= 1; i < MAX_MTEX; ++i, mask <<= 1 )
+ if( self->material->mtex[i] != NULL )
+ septex |= mask;
+
+ /* check the list, and build new septex value */
+ for( i= PySequence_Size(value)-1; i >= 0; --i ) {
+ long ival;
+ PyObject *item = PySequence_Fast_GET_ITEM( value, i );
+ if( !PyInt_Check( item ) ) {
+ PyErr_SetString ( PyExc_TypeError,
+ "expected tuple or list of integers" );
+ goto exit;
+ }
+ ival= PyInt_AsLong( item );
+ if(ival < 0 || ival > MAX_MTEX) {
+ PyErr_SetString( PyExc_ValueError,
+ "channel value out of range" );
+ goto exit;
+ }
+ ival&= (1<<MAX_MTEX)-1;
+ if( self->material->mtex[(int)ival] == NULL ) {
+ PyErr_SetString( PyExc_ValueError,
+ "channels must have a texture assigned" );
+ goto exit;
+ }
+ septex&= ~(1<<ival);
+ }
+ self->material->septex= septex;
+ result = 0;
+
+exit:
+ Py_DECREF(value);
+ return result;
+}
+
static int Material_setAdd( BPy_Material * self, PyObject * value )
{
return EXPP_setFloatClamped ( value, &self->material->add,
@@ -2313,9 +2400,6 @@ static int Material_setSssBack( BPy_Material * self, PyObject * value )
EXPP_MAT_SSS_BACK_MAX);
}
-
-
-
static PyObject *Material_setTexture( BPy_Material * self, PyObject * args )
{
int texnum;
diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c
index 9f68287d658..b3e8fefdb7b 100644
--- a/source/blender/python/api2_2x/Mesh.c
+++ b/source/blender/python/api2_2x/Mesh.c
@@ -5381,11 +5381,11 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args )
if( PySequence_Size( args ) != 2 ||
!PyArg_ParseTuple( args, "iO", &edge_also, &args ) )
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected and int and a sequence of ints or MFaces" );
+ "expected an int and a sequence of ints or MFaces" );
if( !PyList_Check( args ) && !PyTuple_Check( args ) )
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected and int and a sequence of ints or MFaces" );
+ "expected an int and a sequence of ints or MFaces" );
/* see how many args we need to parse */
len = PySequence_Size( args );
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index 45cce46d389..dc70921492c 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -204,6 +204,7 @@ enum obj_consts {
EXPP_OBJ_ATTR_SB_INSPRING,
EXPP_OBJ_ATTR_SB_INFRICT,
+ EXPP_OBJ_ATTR_EMPTY_DRAWTYPE
};
#define EXPP_OBJECT_DRAWSIZEMIN 0.01f
@@ -2431,6 +2432,12 @@ static int Object_setDrawType( BPy_Object * self, PyObject * value )
OB_BOUNDBOX, OB_TEXTURE, 'b' );
}
+static int Object_setEmptyShape( BPy_Object * self, PyObject * value )
+{
+ return EXPP_setIValueRange( value, &self->object->empty_drawtype,
+ OB_ARROWS, OB_EMPTY_CONE, 'b' );
+}
+
static int Object_setEuler( BPy_Object * self, PyObject * args )
{
float rot1, rot2, rot3;
@@ -3758,6 +3765,9 @@ static PyObject *getIntAttr( BPy_Object *self, void *type )
case EXPP_OBJ_ATTR_DRAWTYPE:
param = object->dt;
break;
+ case EXPP_OBJ_ATTR_EMPTY_DRAWTYPE:
+ param = object->empty_drawtype;
+ break;
case EXPP_OBJ_ATTR_PARENT_TYPE:
param = object->partype;
break;
@@ -4938,6 +4948,10 @@ static PyGetSetDef BPy_Object_getseters[] = {
(getter)getIntAttr, (setter)Object_setDrawType,
"The object's drawing type",
(void *)EXPP_OBJ_ATTR_DRAWTYPE},
+ {"emptyShape",
+ (getter)getIntAttr, (setter)Object_setEmptyShape,
+ "The empty's drawing shape",
+ (void *)EXPP_OBJ_ATTR_EMPTY_DRAWTYPE},
{"parentType",
(getter)getIntAttr, (setter)NULL,
"The object's parent type",
@@ -5538,6 +5552,24 @@ static PyObject *M_Object_IpoKeyTypesDict( void )
return M;
}
+static PyObject *M_Object_EmptyShapesDict( void )
+{
+ PyObject *M = PyConstant_New( );
+
+ if( M ) {
+ BPy_constant *d = ( BPy_constant * ) M;
+ PyConstant_Insert( d, "ARROWS", PyInt_FromLong( OB_ARROWS ) );
+ PyConstant_Insert( d, "AXES", PyInt_FromLong( OB_PLAINAXES ) );
+ PyConstant_Insert( d, "CIRCLE", PyInt_FromLong( OB_CIRCLE ) );
+ PyConstant_Insert( d, "ARROW", PyInt_FromLong( OB_SINGLE_ARROW ) );
+ PyConstant_Insert( d, "CUBE", PyInt_FromLong( OB_CUBE ) );
+ PyConstant_Insert( d, "SPHERE", PyInt_FromLong( OB_EMPTY_SPHERE ) );
+ PyConstant_Insert( d, "CONE", PyInt_FromLong( OB_EMPTY_CONE ) );
+ }
+ return M;
+}
+
+
/*****************************************************************************/
/* Function: initObject */
/*****************************************************************************/
@@ -5552,6 +5584,7 @@ PyObject *Object_Init( void )
PyObject *RBFlagsDict = M_Object_RBFlagsDict( );
PyObject *RBShapesDict = M_Object_RBShapeBoundDict( );
PyObject *IpoKeyTypesDict = M_Object_IpoKeyTypesDict( );
+ PyObject *EmptyShapesDict = M_Object_EmptyShapesDict( );
PyType_Ready( &Object_Type ) ;
@@ -5596,7 +5629,9 @@ PyObject *Object_Init( void )
if( RBShapesDict )
PyModule_AddObject( module, "RBShapes", RBShapesDict );
if( IpoKeyTypesDict )
- PyModule_AddObject( module, "IpoKeyTypes", IpoKeyTypesDict );
+ PyModule_AddObject( module, "IpoKeyTypes", IpoKeyTypesDict );
+ if( EmptyShapesDict )
+ PyModule_AddObject( module, "EmptyShapes", EmptyShapesDict );
/*Add SUBMODULES to the module*/
dict = PyModule_GetDict( module ); /*borrowed*/
diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py
index a3496164cd1..02f7edd77f5 100644
--- a/source/blender/python/api2_2x/doc/Material.py
+++ b/source/blender/python/api2_2x/doc/Material.py
@@ -323,6 +323,21 @@ class Material:
each color a list of 5 floats [0 - 1], [r,g,b,a,pos].
The colorband can have between 1 and 31 colors.
@type colorbandSpecular: list
+ @type enabledTextures: list of integers
+ @ivar enabledTextures: The texture channels enabled in this material.
+ The attribute returns is list of integers in the range [0, 9], each
+ number representing the respective enabled MTex entry (see
+ L{getTextures()<getTextures>}). Enabling is done by assigning
+ a list of ints or an empty list. Attempting to enable a channel
+ which does not have a texture assigned to it will result in a
+ ValueError exception.
+ Example::
+ mat.enabledTextures = [] # no texture channels are enabled
+ mat.enabledTextures = [0, 6] # texture channels 0 and 6 are enabled
+ ch = mat.enabledTextures
+ ch.append(4)
+ mat.enabledTextures = ch
+ print mat.enabledTextures # will print: [0, 4, 6]
@ivar enableSSS: If True, subsurface scattering will be rendered on this material.
@type enableSSS: bool
@@ -1010,7 +1025,7 @@ class Material:
def setTexture(index, texture, texco, mapto):
"""
- Assign a Blender Texture object to slot number 'number'.
+ Assign a Blender Texture object to channel number 'number'.
@type index: int
@param index: material's texture index in [0, 9].
@type texture: Blender Texture
@@ -1033,7 +1048,7 @@ class Material:
Get this Material's Texture list.
@rtype: list of MTex
@return: a list of Blender MTex objects. None is returned for each empty
- texture slot.
+ texture channel.
"""
def getScriptLinks (event):
diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py
index 2e4850aeb14..07942d58093 100644
--- a/source/blender/python/api2_2x/doc/Object.py
+++ b/source/blender/python/api2_2x/doc/Object.py
@@ -117,6 +117,10 @@ Example::
attribute. Only one type can be selected at a time. Values are
BOX, SPHERE, CYLINDER, CONE, and POLYHEDERON
+@type EmptyShapes: readonly dictionary
+@var EmptyShapes: Constant dict used for with L{Object.emptyShape} attribute.
+ Only one type can be selected at a time. Values are
+ ARROW, ARROWS, AXES, CIRCLE, CONE, CUBE AND SPHERE
"""
def New (type, name='type'):
@@ -347,7 +351,7 @@ class Object:
ob.layers = [] # object won't be visible
ob.layers = [1, 4] # object visible only in layers 1 and 4
ls = o.layers
- ls.append([10])
+ ls.append(10)
o.layers = ls
print ob.layers # will print: [1, 4, 10]
B{Note}: changes will only be visible after the screen (at least
@@ -525,6 +529,8 @@ class Object:
@ivar drawType: The object's drawing type.
See L{DrawTypes} constant dict for values.
@type drawType: int
+ @ivar emptyShape: The empty drawing shape.
+ See L{EmptyShapes} constant dict for values.
@ivar parentType: The object's parent type. Read-only.
See L{ParentTypes} constant dict for values.
@type parentType: int
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 132bae8b7b8..78f19ad0608 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -3320,6 +3320,8 @@ static void object_panel_collision(Object *ob)
uiDefBut(block, LABEL, 0, "",160,160,150,2, NULL, 0.0, 0, 0, 0, "");
if(pd->deflect) {
+ CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType ( ob, eModifierType_Collision );
+
uiDefBut(block, LABEL, 0, "Particle Interaction", 10,135,310,20, NULL, 0.0, 0, 0, 0, "");
uiBlockBeginAlign(block);
@@ -3335,12 +3337,18 @@ static void object_panel_collision(Object *ob)
uiDefBut(block, LABEL, 0, "Soft Body and Cloth Interaction", 10,65,310,20, NULL, 0.0, 0, 0, 0, "");
uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:", 10,45,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during collision");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "Inner:", 10,25,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "Outer:", 10, 5,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Inner:", 10,45,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Outer:", 160, 45,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness");
uiBlockEndAlign(block);
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:", 10,25,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during collision");
- uiDefButBitS(block, TOG, OB_SB_COLLFINAL, B_FIELD_CHANGE, "Ev.M.Stack", 170,45,150,20, &ob->softflag, 0, 0, 0, 0, "Pick collision object from modifier stack (softbody only)");
+ uiDefButBitS(block, TOG, OB_SB_COLLFINAL, B_FIELD_CHANGE, "Ev.M.Stack", 160,25,150,20, &ob->softflag, 0, 0, 0, 0, "Pick collision object from modifier stack (softbody only)");
+
+ // collision options
+ if(collmd)
+ {
+ uiDefButS(block, NUM, B_FIELD_CHANGE, "Absorption: ", 10,0,150,20, &collmd->absorption, 0.0, 100, 1, 2, "How much of effector force gets lost during collision with this object (in percent).");
+ }
}
}
}
@@ -3350,6 +3358,7 @@ static void object_panel_fields(Object *ob)
uiBut *but;
int particles=0;
static short actpsys=-1;
+ static char slot=0;
block= uiNewBlock(&curarea->uiblocks, "object_panel_fields", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Fields", "Physics", 0, 0, 318, 204)==0) return;
@@ -3371,7 +3380,7 @@ static void object_panel_fields(Object *ob)
char *tipstr="Choose field type";
uiBlockBeginAlign(block);
-
+
if(ob->particlesystem.first) {
ParticleSystem *psys;
char *menustr2= psys_menu_string(ob,1);
@@ -3383,8 +3392,16 @@ static void object_panel_fields(Object *ob)
if(psys->part->pd==NULL)
psys->part->pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
- pd= psys->part->pd;
+ if(psys->part->pd2==NULL)
+ psys->part->pd2= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
+
+ pd= ((slot==1) ? psys->part->pd2 : psys->part->pd);
particles=1;
+
+ uiDefButC(block, ROW, B_REDR, "", 10, 163, 14, 14, &slot, 3.0, 0, 0, 0, "Edit first particle effector slot");
+ uiDefButC(block, ROW, B_REDR, "", 24, 163, 14, 14, &slot, 3.0, 1, 0, 0, "Edit second particle effector slot");
+ uiBlockEndAlign(block);
+ uiBlockBeginAlign(block);
}
else
actpsys= -1; /* -1 = object */
@@ -3397,8 +3414,8 @@ static void object_panel_fields(Object *ob)
/* setup menu button */
if(particles){
- sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d",
- PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC);
+ sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Charge%%x%d|Lennard-Jones%%x%d",
+ PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_CHARGE, PFIELD_LENNARDJ);
if(pd->forcefield==PFIELD_FORCE) tipstr= "Particle attracts or repels particles (On shared object layers)";
else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of particle Z axis (On shared object layers)";
@@ -3406,11 +3423,11 @@ static void object_panel_fields(Object *ob)
}
else{
if(ob->type==OB_CURVE)
- sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Curve Guide%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d",
- PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_GUIDE, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE);
+ sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Curve Guide%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d",
+ PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_GUIDE, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
else
- sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d",
- PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE);
+ sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d",
+ PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
if(pd->forcefield==PFIELD_FORCE) tipstr= "Object center attracts or repels particles (On shared object layers)";
else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of Object Z axis (On shared object layers)";
@@ -3425,8 +3442,6 @@ static void object_panel_fields(Object *ob)
uiBlockEndAlign(block);
uiDefBut(block, LABEL, 0, "",160,180,150,2, NULL, 0.0, 0, 0, 0, "");
-
- MEM_freeN(menustr);
if(pd->forcefield) {
uiBlockBeginAlign(block);
@@ -3492,40 +3507,49 @@ static void object_panel_fields(Object *ob)
uiBlockEndAlign(block);
}
else{
- uiDefButS(block, MENU, B_FIELD_DEP, "Fall-off%t|Cone%x2|Tube%x1|Sphere%x0", 160,180,140,20, &pd->falloff, 0.0, 0.0, 0, 0, "Fall-off shape");
- if(pd->falloff==PFIELD_FALL_TUBE)
- uiDefBut(block, LABEL, 0, "Longitudinal", 160,160,140,20, NULL, 0.0, 0, 0, 0, "");
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, PFIELD_POSZ, B_FIELD_CHANGE, "Pos", 160,140,40,20, &pd->flag, 0.0, 0, 0, 0, "Effect only in direction of positive Z axis");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 200,140,100,20, &pd->f_power, 0, 10, 10, 0, "Falloff power (real gravitational falloff = 2)");
- uiDefButBitS(block, TOG, PFIELD_USEMAX, B_FIELD_CHANGE, "Use", 160,120,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ", 200,120,100,20, &pd->maxdist, 0, 1000.0, 10, 0, "Maximum distance for the field to work");
- uiDefButBitS(block, TOG, PFIELD_USEMIN, B_FIELD_CHANGE, "Use", 160,100,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum distance for the field's fall-off");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ", 200,100,100,20, &pd->mindist, 0, 1000.0, 10, 0, "Minimum distance for the field's fall-off");
- uiBlockEndAlign(block);
-
- if(pd->falloff==PFIELD_FALL_TUBE){
- uiDefBut(block, LABEL, 0, "Radial", 160,80,70,20, NULL, 0.0, 0, 0, 0, "");
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
- uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum radial distance for the field to work");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ", 200,40,100,20, &pd->maxrad, 0, 1000.0, 10, 0, "Maximum radial distance for the field to work");
- uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum radial distance for the field's fall-off");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ", 200,20,100,20, &pd->minrad, 0, 1000.0, 10, 0, "Minimum radial distance for the field's fall-off");
- uiBlockEndAlign(block);
+ if(pd->forcefield==PFIELD_LENNARDJ) {
+ uiDefBut(block, LABEL, 0, "Fall-off determined", 160,140,140,20, NULL, 0.0, 0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, "by particle sizes", 160,120,140,20, NULL, 0.0, 0, 0, 0, "");
}
- else if(pd->falloff==PFIELD_FALL_CONE){
- uiDefBut(block, LABEL, 0, "Angular", 160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+ else {
+ uiDefButS(block, MENU, B_FIELD_DEP, "Fall-off%t|Cone%x2|Tube%x1|Sphere%x0", 160,180,140,20, &pd->falloff, 0.0, 0.0, 0, 0, "Fall-off shape");
+ if(pd->falloff==PFIELD_FALL_TUBE)
+ uiDefBut(block, LABEL, 0, "Longitudinal", 160,160,140,20, NULL, 0.0, 0, 0, 0, "");
uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
- uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum angle for the field to work");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxAngle: ", 200,40,100,20, &pd->maxrad, 0, 89.0, 10, 0, "Maximum angle for the field to work (in radians)");
- uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum angle for the field's fall-off");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "MinAngle: ", 200,20,100,20, &pd->minrad, 0, 89.0, 10, 0, "Minimum angle for the field's fall-off (in radians)");
+ uiDefButBitS(block, TOG, PFIELD_POSZ, B_FIELD_CHANGE, "Pos", 160,140,40,20, &pd->flag, 0.0, 0, 0, 0, "Effect only in direction of positive Z axis");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 200,140,100,20, &pd->f_power, 0, 10, 10, 0, "Falloff power (real gravitational falloff = 2)");
+ uiDefButBitS(block, TOG, PFIELD_USEMAX, B_FIELD_CHANGE, "Use", 160,120,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ", 200,120,100,20, &pd->maxdist, 0, 1000.0, 10, 0, "Maximum distance for the field to work");
+ uiDefButBitS(block, TOG, PFIELD_USEMIN, B_FIELD_CHANGE, "Use", 160,100,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum distance for the field's fall-off");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ", 200,100,100,20, &pd->mindist, 0, 1000.0, 10, 0, "Minimum distance for the field's fall-off");
uiBlockEndAlign(block);
+
+ if(pd->falloff==PFIELD_FALL_TUBE){
+ uiDefBut(block, LABEL, 0, "Radial", 160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
+ uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum radial distance for the field to work");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ", 200,40,100,20, &pd->maxrad, 0, 1000.0, 10, 0, "Maximum radial distance for the field to work");
+ uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum radial distance for the field's fall-off");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ", 200,20,100,20, &pd->minrad, 0, 1000.0, 10, 0, "Minimum radial distance for the field's fall-off");
+ uiBlockEndAlign(block);
+ }
+ else if(pd->falloff==PFIELD_FALL_CONE){
+ uiDefBut(block, LABEL, 0, "Angular", 160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
+ uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum angle for the field to work");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxAngle: ", 200,40,100,20, &pd->maxrad, 0, 89.0, 10, 0, "Maximum angle for the field to work (in radians)");
+ uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum angle for the field's fall-off");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "MinAngle: ", 200,20,100,20, &pd->minrad, 0, 89.0, 10, 0, "Minimum angle for the field's fall-off (in radians)");
+ uiBlockEndAlign(block);
+ }
}
}
+
}
+
+ MEM_freeN(menustr);
}
}
@@ -4372,6 +4396,8 @@ static void object_panel_particle_extra(Object *ob)
uiDefButBitI(block, TOG, PART_CHILD_EFFECT, B_PART_RECALC, "Children", butx+(butw*3)/5,buty,(butw*2)/5,buth, &part->flag, 0, 0, 0, 0, "Apply effectors to children");
uiBlockEndAlign(block);
}
+ else if(part->phystype == PART_PHYS_NEWTON)
+ uiDefButBitI(block, TOG, PART_SELF_EFFECT, B_PART_RECALC, "Self Effect", butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Particle effectors effect themselves");
else
buty-=buth;
diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c
index 0e7476bbe82..71854570c8c 100644
--- a/source/blender/src/drawipo.c
+++ b/source/blender/src/drawipo.c
@@ -1212,16 +1212,9 @@ static void draw_ipovertices(int sel)
/*}*/
} else { /* normal non bit curves */
if(ei->flag & IPO_EDIT) {
- if(ei->icu->ipo==IPO_BEZ) {
- /* Draw the editmode hendels for a bezier curve */
- if( (bezt->f1 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[0][0] < G.v2d->cur.xmax)*/
- bglVertex3fv(bezt->vec[0]);
-
- if( (bezt->f3 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[2][0] < G.v2d->cur.xmax)*/
- bglVertex3fv(bezt->vec[2]);
-
- }
-
+ /* Only the vertex of the line, the
+ * handler are draw below.
+ */
if( (bezt->f2 & SELECT) == sel) /* && G.v2d->cur.xmin < bezt->vec[1][0] < G.v2d->cur.xmax)*/
bglVertex3fv(bezt->vec[1]);
@@ -1237,6 +1230,45 @@ static void draw_ipovertices(int sel)
bezt++;
}
bglEnd();
+
+ if (ei->flag & IPO_EDIT) {
+ /* Now draw the two vertex of the handler,
+ * need split it because we can't call glPointSize
+ * in the middle of a glBegin/glEnd also the
+ * bug comment before.
+ */
+ a= ei->icu->totvert;
+ bezt= ei->icu->bezt;
+
+ glPointSize(BIF_GetThemeValuef(TH_HANDLE_VERTEX_SIZE));
+
+ if(sel) BIF_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+ else BIF_ThemeColor(TH_HANDLE_VERTEX);
+
+ bglBegin(GL_POINTS);
+
+ while(a--) {
+ if (ei->disptype!=IPO_DISPBITS) {
+ if(ei->flag & IPO_EDIT) {
+ if(ei->icu->ipo==IPO_BEZ) {
+ /* Draw the editmode hendels for a bezier curve */
+ if( (bezt->f1 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[0][0] < G.v2d->cur.xmax)*/
+ bglVertex3fv(bezt->vec[0]);
+
+ if( (bezt->f3 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[2][0] < G.v2d->cur.xmax)*/
+ bglVertex3fv(bezt->vec[2]);
+ }
+ }
+ }
+ bezt++;
+ }
+ bglEnd();
+
+ /* The color are always reset (see the while)
+ * but the point size not so we reset now.
+ */
+ glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
+ }
}
}
diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c
index 63c301658f2..cd6aefdb87c 100644
--- a/source/blender/src/editipo.c
+++ b/source/blender/src/editipo.c
@@ -462,24 +462,7 @@ static void make_part_editipo(SpaceIpo *si)
name = getname_part_ei(part_ar[a]);
strcpy(ei->name, name);
ei->adrcode= part_ar[a];
-
- //if(ei->adrcode & MA_MAP1) {
- // ei->adrcode-= MA_MAP1;
- // ei->adrcode |= texchannel_to_adrcode(si->channel);
- //}
- //else {
- // if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
- //}
-
ei->col= ipo_rainbow(a, PART_TOTIPO);
-
- //len= strlen(ei->name);
- //if(len) {
- // if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
- // else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
- // else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
- //}
-
ei->icu= find_ipocurve(si->ipo, ei->adrcode);
if(ei->icu) {
ei->flag= ei->icu->flag;
@@ -6011,4 +5994,4 @@ void move_to_frame(void)
}
}
BIF_undo_push("Set frame to selected Ipo vertex");
-} \ No newline at end of file
+}
diff --git a/source/blender/src/editipo_lib.c b/source/blender/src/editipo_lib.c
index 7b3d439833e..e1e286e10cf 100644
--- a/source/blender/src/editipo_lib.c
+++ b/source/blender/src/editipo_lib.c
@@ -103,7 +103,8 @@ char *ic_name_empty[1] ={ "" };
char *fluidsim_ic_names[FLUIDSIM_TOTNAM] = { "Fac-Visc", "Fac-Time", "GravX","GravY","GravZ", "VelX","VelY","VelZ", "Active" };
char *part_ic_names[PART_TOTNAM] = { "E_Freq", "E_Life", "E_Speed", "E_Angular", "E_Size",
"Angular", "Size", "Drag", "Brown", "Damp", "Length", "Clump",
-"GravX", "GravY", "GravZ", "KinkAmp", "KinkFreq", "KinkShape", "BBTilt", "FStreng", "FFall", "FMaxD"};
+"GravX", "GravY", "GravZ", "KinkAmp", "KinkFreq", "KinkShape", "BBTilt",
+"FStreng", "FFall", "FMaxD", "F2Streng", "F2Fall", "F2MaxD"};
/* gets the appropriate icon for the given blocktype */
int geticon_ipo_blocktype(short blocktype)
diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c
index f47f14a605c..acd14aae7a5 100644
--- a/source/blender/src/resources.c
+++ b/source/blender/src/resources.c
@@ -313,7 +313,15 @@ char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp= ts->transition; break;
case TH_SEQ_META:
cp= ts->meta; break;
-
+ case TH_HANDLE_VERTEX:
+ cp= ts->handle_vertex;
+ break;
+ case TH_HANDLE_VERTEX_SELECT:
+ cp= ts->handle_vertex_select;
+ break;
+ case TH_HANDLE_VERTEX_SIZE:
+ cp= &ts->handle_vertex_size;
+ break;
}
}
@@ -493,6 +501,10 @@ void BIF_InitTheme(void)
SETCOL(btheme->tipo.hilite, 0x60, 0xc0, 0x40, 255);
btheme->tipo.vertex_size= 3;
+ SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255);
+ SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255);
+ btheme->tipo.handle_vertex_size= 3;
+
/* space file */
/* to have something initialized */
btheme->tfile= btheme->tv3d;
@@ -684,7 +696,10 @@ char *BIF_ThemeColorsPup(int spacetype)
str += sprintf(str, "Vertex %%x%d|", TH_VERTEX);
str += sprintf(str, "Vertex Selected %%x%d|", TH_VERTEX_SELECT);
str += sprintf(str, "Vertex Size %%x%d|", TH_VERTEX_SIZE);
- str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+ str += sprintf(str, "Current Frame %%x%d|", TH_CFRAME);
+ str += sprintf(str, "Handle Vertex %%x%d|", TH_HANDLE_VERTEX);
+ str += sprintf(str, "Handle Vertex Selected %%x%d|", TH_HANDLE_VERTEX_SELECT);
+ str += sprintf(str, "Handle Vertex Size %%x%d", TH_HANDLE_VERTEX_SIZE);
break;
case SPACE_FILE:
str += sprintf(str, "Selected file %%x%d", TH_HILITE);
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index fb055216f7f..8787cf9efc4 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -3492,6 +3492,9 @@ static void info_user_themebuts(uiBlock *block, short y1, short y2, short y3, sh
uiButSetFunc(but, set_userdef_iconfile_cb, &iconfileindex, NULL);
}
+ else if(th_curcol==TH_HANDLE_VERTEX_SIZE) {
+ uiDefButC(block, NUMSLI, B_UPDATE_THEME,"Handle size ", 465,y3,200,20, col, 1.0, 10.0, 0, 0, "");
+ }
else {
uiBlockBeginAlign(block);
if ELEM9(th_curcol, TH_PANEL, TH_LAMP, TH_FACE, TH_FACE_SELECT, TH_EDITMESH_ACTIVE, TH_MENU_BACK, TH_MENU_HILITE, TH_MENU_ITEM, TH_NODE) {
diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c
index 92e49ab29fa..15c2664a9d8 100644
--- a/source/blender/src/usiblender.c
+++ b/source/blender/src/usiblender.c
@@ -477,7 +477,15 @@ static void init_userdef_file(void)
if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 16)) {
U.flag |= USER_ADD_VIEWALIGNED|USER_ADD_EDITMODE;
}
-
+ if ((G.main->versionfile < 247) || (G.main->versionfile == 247 && G.main->subversionfile < 1)) {
+ bTheme *btheme;
+ for(btheme= U.themes.first; btheme; btheme= btheme->next) {
+ SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255);
+ SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255);
+ btheme->tipo.handle_vertex_size= 3;
+ }
+ }
+
/* GL Texture Garbage Collection (variable abused above!) */
if (U.textimeout == 0) {
U.texcollectrate = 60;
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 7de3056e382..16f8ae0095a 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -90,33 +90,10 @@ void update_for_newframe();
static BlendFileData *load_game_data(char *filename) {
BlendReadError error;
- //this doesn't work anymore for relative paths, so use BLO_read_from_memory instead
- //BlendFileData *bfd= BLO_read_from_file(filename, &error);
- FILE* file = fopen(filename,"rb");
- BlendFileData *bfd = 0;
- if (file)
- {
- fseek(file, 0L, SEEK_END);
- int len= ftell(file);
- fseek(file, 0L, SEEK_SET);
- char* filebuffer= new char[len];//MEM_mallocN(len, "text_buffer");
- int sizeread = fread(filebuffer,len,1,file);
- if (sizeread==1){
- bfd = BLO_read_from_memory(filebuffer, len, &error);
- } else {
- error = BRE_UNABLE_TO_READ;
- }
- fclose(file);
- // the memory is not released in BLO_read_from_memory, must do it here
- delete filebuffer;
- } else {
- error = BRE_UNABLE_TO_OPEN;
- }
-
+ BlendFileData *bfd= BLO_read_from_file(filename, &error);
if (!bfd) {
printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error));
}
-
return bfd;
}
@@ -139,7 +116,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
// Acquire Python's GIL (global interpreter lock)
// so we can safely run Python code and API calls
PyGILState_STATE gilstate = PyGILState_Ensure();
-
+
+ PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */
+
bgl::InitExtensions(true);
do
@@ -333,6 +312,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
initRasterizer(rasterizer, canvas);
PyObject *gameLogic = initGameLogic(startscene);
PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module.
+ PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
initGameKeys();
initPythonConstraintBinding();
initMathutils();
@@ -407,6 +387,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
// which allows the scene to safely delete them :)
// see: (space.c)->start_game
PyDict_Clear(PyModule_GetDict(gameLogic));
+ PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict);
ketsjiengine->StopEngine();
exitGamePythonScripting();
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 7be3b94d8ae..f859193ef7a 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -97,7 +97,7 @@ extern "C"
#include "GHOST_IEventConsumer.h"
#include "GHOST_IWindow.h"
#include "GHOST_Rect.h"
-
+#include "marshal.h"
static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
@@ -125,7 +125,9 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR
m_networkdevice(0),
m_audiodevice(0),
m_blendermat(0),
- m_blenderglslmat(0)
+ m_blenderglslmat(0),
+ m_pyGlobalDictString(0),
+ m_pyGlobalDictString_Length(0)
{
fSystem = system;
}
@@ -645,14 +647,23 @@ bool GPG_Application::startEngine(void)
PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
m_ketsjiengine->SetPythonDictionary(dictionaryobject);
initRasterizer(m_rasterizer, m_canvas);
- PyDict_SetItemString(dictionaryobject, "GameLogic", initGameLogic(startscene)); // Same as importing the module
+ PyObject *gameLogic = initGameLogic(startscene);
+ PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module
initGameKeys();
initPythonConstraintBinding();
initMathutils();
-
-
-
+ /* Restore the dict */
+ if (m_pyGlobalDictString) {
+ PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(m_pyGlobalDictString, m_pyGlobalDictString_Length);
+ if (pyGlobalDict) {
+ PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
+ } else {
+ PyErr_Clear();
+ printf("Error could not marshall string\n");
+ }
+ }
+
m_sceneconverter->ConvertScene(
startscenename,
startscene,
@@ -688,6 +699,32 @@ bool GPG_Application::startEngine(void)
void GPG_Application::stopEngine()
{
+ // get the python dict and convert to a string for future use
+ {
+ SetPyGlobalDictMarshal(NULL, 0);
+
+ PyObject* gameLogic = PyImport_ImportModule("GameLogic");
+ if (gameLogic) {
+ PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module
+ if (pyGlobalDict) {
+ PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5
+ if (pyGlobalDictMarshal) {
+ m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal);
+ PyObject_Print(pyGlobalDictMarshal, stderr, 0);
+ m_pyGlobalDictString = static_cast<char *> (malloc(m_pyGlobalDictString_Length));
+ memcpy(m_pyGlobalDictString, PyString_AsString(pyGlobalDictMarshal), m_pyGlobalDictString_Length);
+ } else {
+ printf("Error, GameLogic.globalDict could not be marshal'd\n");
+ }
+ } else {
+ printf("Error, GameLogic.globalDict was removed\n");
+ }
+ } else {
+ printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
+ }
+ }
+
+
// when exiting the mainloop
exitGamePythonScripting();
m_ketsjiengine->StopEngine();
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h
index 17f5add8b19..31f5eb75e52 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.h
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h
@@ -72,6 +72,29 @@ public:
bool StartGameEngine(int stereoMode);
void StopGameEngine();
+ char*
+ GetPyGlobalDictMarshal()
+ {
+ return m_pyGlobalDictString;
+ };
+
+ void
+ SetPyGlobalDictMarshal( char* pyGlobalDictString, int length )
+ {
+ if (m_pyGlobalDictString && m_pyGlobalDictString != pyGlobalDictString)
+ free(m_pyGlobalDictString);
+
+ m_pyGlobalDictString = pyGlobalDictString;
+ m_pyGlobalDictString_Length = length;
+ };
+
+ int
+ GetPyGlobalDictMarshalLength()
+ {
+ return m_pyGlobalDictString_Length;
+ };
+
+
protected:
bool handleWheel(GHOST_IEvent* event);
bool handleButton(GHOST_IEvent* event, bool isDown);
@@ -142,6 +165,12 @@ protected:
bool m_blendermat;
bool m_blenderglslmat;
-
+
+ /*
+ * GameLogic.globalDict as a string so that loading new blend files can use the same dict.
+ * Do this because python starts/stops when loading blend files.
+ */
+ char* m_pyGlobalDictString;
+ int m_pyGlobalDictString_Length;
};
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index 8222e5c8bac..26a85128025 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -293,7 +293,9 @@ int main(int argc, char** argv)
GHOST_TUns32 fullScreenHeight= 0;
int fullScreenBpp = 32;
int fullScreenFrequency = 60;
-
+ char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */
+ int pyGlobalDictString_Length = 0;
+
#ifdef __linux__
#ifdef __alpha__
signal (SIGFPE, SIG_IGN);
@@ -625,6 +627,10 @@ int main(int argc, char** argv)
titlename = maggie->name;
+ // Set the GameLogic.globalDict from marshal'd data, so we can load new blend files
+ // abd keep data in GameLogic.globalDict
+ app.SetPyGlobalDictMarshal(pyGlobalDictString, pyGlobalDictString_Length);
+
// Check whether the game should be displayed full-screen
if ((!fullScreenParFound) && (!windowParFound))
{
@@ -750,6 +756,12 @@ int main(int argc, char** argv)
}
}
app.StopGameEngine();
+
+ // GameLogic.globalDict has been converted into a buffer
+ // store in pyGlobalDictString so we can restore after python has stopped and started.
+ pyGlobalDictString = app.GetPyGlobalDictMarshal();
+ pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength();
+
BLO_blendfiledata_free(bfd);
#ifdef __APPLE__
@@ -772,6 +784,11 @@ int main(int argc, char** argv)
}
}
+ if (pyGlobalDictString) {
+ free(pyGlobalDictString);
+ pyGlobalDictString = NULL;
+ }
+
return error ? -1 : 0;
}
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index e0cd5a3bc9e..d6997ee29a8 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -680,188 +680,6 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj,
// forward declarations
-static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
-{
- if (!meshobj)
- return 0;
-
- btCollisionShape* collisionMeshShape = 0;
- btConvexHullShape* convexHullShape = 0;
- btTriangleMeshShape* concaveShape = 0;
-
- btTriangleMesh* collisionMeshData = 0;
-
- //see if there is any polygons, if not, bail out.
-
- int numPoints = 0;
- btVector3* points = 0;
-
- // Mesh has no polygons!
- int numpolys = meshobj->NumPolygons();
- if (!numpolys)
- {
- return NULL;
- }
-
- // Count the number of collision polygons and check they all come from the same
- // vertex array
- int numvalidpolys = 0;
- int vtxarray = -1;
- RAS_IPolyMaterial *poly_material = NULL;
- bool reinstance = true;
-
- for (int p=0; p<numpolys; p++)
- {
- RAS_Polygon* poly = meshobj->GetPolygon(p);
-
- // only add polygons that have the collisionflag set
- if (poly->IsCollider())
- {
- // check polygon is from the same vertex array
- if (poly->GetVertexIndexBase().m_vtxarray != vtxarray)
- {
- if (vtxarray < 0)
- vtxarray = poly->GetVertexIndexBase().m_vtxarray;
- else
- {
- reinstance = false;
- vtxarray = -1;
- }
- }
-
- // check poly is from the same material
- if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
- {
- if (poly_material)
- {
- reinstance = false;
- poly_material = NULL;
- }
- else
- poly_material = poly->GetMaterial()->GetPolyMaterial();
- }
-
- // count the number of collision polys
- numvalidpolys++;
-
- // We have one collision poly, and we can't reinstance, so we
- // might as well break here.
- if (!reinstance)
- break;
- }
- }
-
- // No collision polygons
- if (numvalidpolys < 1)
- return NULL;
-
-
- if (polytope)
- {
- convexHullShape = new btConvexHullShape(&points[0].getX(),numPoints);
- collisionMeshShape = convexHullShape;
- } else
- {
- collisionMeshData = new btTriangleMesh();
-// concaveShape = new btTriangleMeshShape(collisionMeshData);
- //collisionMeshShape = concaveShape;
-
- }
-
-
- numvalidpolys = 0;
-
- for (int p2=0; p2<numpolys; p2++)
- {
- RAS_Polygon* poly = meshobj->GetPolygon(p2);
-
- // only add polygons that have the collisionflag set
- if (poly->IsCollider())
- {
- //Bullet can raycast any shape, so
- if (polytope)
- {
- for (int i=0;i<poly->VertexCount();i++)
- {
- const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[i],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 point(vtx[0],vtx[1],vtx[2]);
- convexHullShape->addPoint(point);
- }
- if (poly->VertexCount())
- numvalidpolys++;
-
- } else
- {
- {
- const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[2],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
- vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[1],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
- vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[0],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
- collisionMeshData->addTriangle(vertex0,vertex1,vertex2);
- numvalidpolys++;
- }
- if (poly->VertexCount() == 4)
- {
- const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[3],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
- vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[2],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
- vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[0],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
- collisionMeshData->addTriangle(vertex0,vertex1,vertex2);
- numvalidpolys++;
- }
-
- }
- }
- }
-
-
-
- if (numvalidpolys > 0)
- {
-
- if (!polytope)
- {
- bool useQuantization = true;
- concaveShape = new btBvhTriangleMeshShape( collisionMeshData, useQuantization );
- //concaveShape = new btTriangleMeshShape( collisionMeshData );
-
- concaveShape->recalcLocalAabb();
- if (collisionMeshShape)
- delete collisionMeshShape;
- collisionMeshShape = concaveShape;
-
- }
-
-
-
- return collisionMeshShape;
- }
- if (collisionMeshShape)
- delete collisionMeshShape;
- if (collisionMeshData)
- delete collisionMeshData;
- return NULL;
-
-}
-
void KX_ConvertBulletObject( class KX_GameObject* gameobj,
class RAS_MeshObject* meshobj,
@@ -878,6 +696,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
bool isbulletdyna = false;
CcdConstructionInfo ci;
class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+ class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo();
@@ -894,120 +713,80 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_gravity = btVector3(0,0,0);
ci.m_localInertiaTensor =btVector3(0,0,0);
ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f;
+ shapeInfo->m_radius = objprop->m_radius;
isbulletdyna = objprop->m_dyna;
ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
- btTransform trans;
- trans.setIdentity();
-
btCollisionShape* bm = 0;
switch (objprop->m_boundclass)
{
case KX_BOUNDSPHERE:
{
- float radius = objprop->m_radius;
- btVector3 inertiaHalfExtents (
- radius,
- radius,
- radius);
+ //float radius = objprop->m_radius;
+ //btVector3 inertiaHalfExtents (
+ // radius,
+ // radius,
+ // radius);
//blender doesn't support multisphere, but for testing:
//bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1);
- bm = new btSphereShape(objprop->m_radius);
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+ shapeInfo->m_shapeType = PHY_SHAPE_SPHERE;
+ bm = shapeInfo->CreateBulletShape();
break;
};
case KX_BOUNDBOX:
{
- MT_Vector3 halfExtents (
+ shapeInfo->m_halfExtend.setValue(
objprop->m_boundobject.box.m_extends[0],
- objprop->m_boundobject.box.m_extends[1],
- objprop->m_boundobject.box.m_extends[2]);
-
- halfExtents /= 2.f;
-
- //btVector3 he (halfExtents[0]-CONVEX_DISTANCE_MARGIN ,halfExtents[1]-CONVEX_DISTANCE_MARGIN ,halfExtents[2]-CONVEX_DISTANCE_MARGIN );
- //he = he.absolute();
-
- btVector3 he (halfExtents[0],halfExtents[1],halfExtents[2]);
- he = he.absolute();
-
+ objprop->m_boundobject.box.m_extends[1],
+ objprop->m_boundobject.box.m_extends[2]);
- bm = new btBoxShape(he);
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+ shapeInfo->m_halfExtend /= 2.0;
+ shapeInfo->m_halfExtend = shapeInfo->m_halfExtend.absolute();
+ shapeInfo->m_shapeType = PHY_SHAPE_BOX;
+ bm = shapeInfo->CreateBulletShape();
break;
};
case KX_BOUNDCYLINDER:
{
- btVector3 halfExtents (
+ shapeInfo->m_halfExtend.setValue(
objprop->m_boundobject.c.m_radius,
objprop->m_boundobject.c.m_radius,
objprop->m_boundobject.c.m_height * 0.5f
);
- bm = new btCylinderShapeZ(halfExtents);
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
-
+ shapeInfo->m_shapeType = PHY_SHAPE_CYLINDER;
+ bm = shapeInfo->CreateBulletShape();
break;
}
- case KX_BOUNDCONE:
+ case KX_BOUNDCONE:
{
- btVector3 halfExtents (objprop->m_boundobject.box.m_extends[0],
- objprop->m_boundobject.box.m_extends[1],
- objprop->m_boundobject.box.m_extends[2]);
-
-
- halfExtents /= 2.f;
-
- bm = new btConeShapeZ(objprop->m_boundobject.c.m_radius,objprop->m_boundobject.c.m_height);
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
-
+ shapeInfo->m_radius = objprop->m_boundobject.c.m_radius;
+ shapeInfo->m_height = objprop->m_boundobject.c.m_height;
+ shapeInfo->m_shapeType = PHY_SHAPE_CONE;
+ bm = shapeInfo->CreateBulletShape();
break;
}
- case KX_BOUNDPOLYTOPE:
- {
- bm = CreateBulletShapeFromMesh(meshobj,true);
- if (bm)
- {
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
- }
- break;
- }
- case KX_BOUNDMESH:
- {
- if (!ci.m_mass)
- {
- bm = CreateBulletShapeFromMesh(meshobj,false);
- ci.m_localInertiaTensor.setValue(0.f,0.f,0.f);
- //no moving concave meshes, so don't bother calculating inertia
- //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
- }
-
- break;
- }
-
- default:
- //interpret the shape as a concave triangle-mesh
+ case KX_BOUNDPOLYTOPE:
{
- if (meshobj)
- {
- bm = CreateBulletShapeFromMesh(meshobj,false);
- ci.m_localInertiaTensor.setValue(0.f,0.f,0.f);
-
- // assert(0);
-
- /*
- meshobj->ScheduleCollisionPolygons();
-
- KX_DeformableMesh* gfxmesh = new KX_DeformableMesh(meshobj);
- gfxmesh->sendFixedMapping();
- //trianglemesh
- bm = new TriangleMeshInterface(gfxmesh,trans);
- */
+ shapeInfo->SetMesh(meshobj, true);
+ bm = shapeInfo->CreateBulletShape();
+ break;
+ }
+ case KX_BOUNDMESH:
+ {
+ if (!ci.m_mass)
+ {
+ shapeInfo->SetMesh(meshobj, false);
+ bm = shapeInfo->CreateBulletShape();
+ //no moving concave meshes, so don't bother calculating inertia
+ //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
}
+
+ break;
}
}
@@ -1017,44 +796,41 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
if (!bm)
{
delete motionstate;
+ delete shapeInfo;
return;
}
bm->setMargin(0.06);
-
if (objprop->m_isCompoundChild)
{
//find parent, compound shape and add to it
//take relative transform into account!
KX_BulletPhysicsController* parentCtrl = (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController();
assert(parentCtrl);
+ CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
btRigidBody* rigidbody = parentCtrl->GetRigidBody();
btCollisionShape* colShape = rigidbody->getCollisionShape();
assert(colShape->isCompound());
btCompoundShape* compoundShape = (btCompoundShape*)colShape;
- btTransform childTrans;
- childTrans.setIdentity();
- NodeList& children = objprop->m_dynamic_parent->GetSGNode()->GetSGChildren();
MT_Point3 childPos = gameobj->GetSGNode()->GetLocalPosition();
MT_Matrix3x3 childRot = gameobj->GetSGNode()->GetLocalOrientation();
MT_Vector3 childScale = gameobj->GetSGNode()->GetLocalScale();
bm->setLocalScaling(btVector3(childScale.x(),childScale.y(),childScale.z()));
- childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z()));
+ shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z()));
float rotval[12];
childRot.getValue(rotval);
btMatrix3x3 newRot;
newRot.setValue(rotval[0],rotval[1],rotval[2],rotval[4],rotval[5],rotval[6],rotval[8],rotval[9],rotval[10]);
newRot = newRot.transpose();
- childTrans.setBasis(newRot);
-
-
- compoundShape->addChildShape(childTrans,bm);
- kxscene->AddShape(bm);
+ shapeInfo->m_childTrans.setBasis(newRot);
+ parentShapeInfo->AddShape(shapeInfo);
+
+ compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
//do some recalc?
//recalc inertia for rigidbody
if (!rigidbody->isStaticOrKinematicObject())
@@ -1069,15 +845,16 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
if (objprop->m_hasCompoundChildren)
{
- //replace shape by compoundShape
+ // create a compound shape info
+ CcdShapeConstructionInfo *compoundShapeInfo = new CcdShapeConstructionInfo();
+ compoundShapeInfo->m_shapeType = PHY_SHAPE_COMPOUND;
+ compoundShapeInfo->AddShape(shapeInfo);
+ // create the compound shape manually as we already have the child shape
btCompoundShape* compoundShape = new btCompoundShape();
- btTransform identTrans;
- identTrans.setIdentity();
- compoundShape->addChildShape(identTrans,bm);
- //note abount compoundShape: Bullet does not delete the child shapes when
- //the compound shape is deleted, so insert also the child shapes
- kxscene->AddShape(bm);
+ compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
+ // now replace the shape
bm = compoundShape;
+ shapeInfo = compoundShapeInfo;
}
@@ -1113,6 +890,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_collisionShape = bm;
+ ci.m_shapeInfo = shapeInfo;
ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice
ci.m_restitution = smmaterial->m_restitution;
ci.m_physicsEnv = env;
@@ -1124,9 +902,12 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_collisionFilterGroup = (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : short(CcdConstructionInfo::StaticFilter);
ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter);
ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody;
+ MT_Vector3 scaling = gameobj->NodeGetWorldScaling();
+ ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]);
KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna);
- //remember that we created a shape so that we can delete it when the scene is removed (bullet will not delete it)
- kxscene->AddShape(bm);
+ // shapeInfo is reference counted, decrement now as we don't use it anymore
+ if (shapeInfo)
+ shapeInfo->Release();
if (objprop->m_in_active_layer)
{
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 868439546c3..472ae759d65 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -733,6 +733,10 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
+
+ // can be overwritten later for gameEngine instances that can load new blend files and re-initialize this module
+ // for now its safe to make sure it exists for other areas such as the web plugin
+ PyDict_SetItemString(d, "globalDict", PyDict_New());
ErrorObject = PyString_FromString("GameLogic.error");
PyDict_SetItemString(d, "error", ErrorObject);
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 2828663c63d..ab3692d2411 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -234,40 +234,9 @@ KX_Scene::~KX_Scene()
{
delete m_bucketmanager;
}
-#ifdef USE_BULLET
- // This is a fix for memory leaks in bullet: the collision shapes is not destroyed
- // when the physical controllers are destroyed. The reason is that shapes are shared
- // between replicas of an object. There is no reference count in Bullet so the
- // only workaround that does not involve changes in Bullet is to save in this array
- // the list of shapes that are created when the scene is created (see KX_ConvertPhysicsObjects.cpp)
- class btCollisionShape* shape;
- class btTriangleMeshShape* meshShape;
- vector<class btCollisionShape*>::iterator it = m_shapes.begin();
- while (it != m_shapes.end()) {
- shape = *it;
- if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- meshShape = static_cast<btTriangleMeshShape*>(shape);
- // shapes based on meshes use an interface that contains the vertices.
- // Again the idea is to be able to share the interface between shapes but
- // this is not used in Blender: each base object will have its own interface
- btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
- if (meshInterface)
- delete meshInterface;
- }
- delete shape;
- it++;
- }
-#endif
//Py_DECREF(m_attrlist);
}
-void KX_Scene::AddShape(class btCollisionShape*shape)
-{
- m_shapes.push_back(shape);
-}
-
-
void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
{
m_projectionmat = pmat;
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index 80a2abe287a..1c56dd1ee55 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -122,11 +122,6 @@ protected:
*/
list<class KX_Camera*> m_cameras;
/**
- * The set of bullet shapes that must be deleted at the end of the scene
- * to avoid memory leak (not deleted by bullet because shape are shared between replicas)
- */
- vector<class btCollisionShape*> m_shapes;
- /**
* Various SCA managers used by the scene
*/
SCA_LogicManager* m_logicmgr;
@@ -322,7 +317,6 @@ public:
int NewRemoveObject(CValue* gameobj);
void ReplaceMesh(CValue* gameobj,
void* meshobj);
- void AddShape(class btCollisionShape* shape);
/**
* @section Logic stuff
* Initiate an update of the logic system.
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index b872fae6138..d6a32dfd9c0 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -18,6 +18,7 @@ subject to the following restrictions:
#include "PHY_IMotionState.h"
#include "CcdPhysicsEnvironment.h"
+#include "RAS_MeshObject.h"
class BP_Proxy;
@@ -44,7 +45,18 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
m_newClientInfo = 0;
m_registerCount = 0;
+ // copy pointers locally to allow smart release
m_MotionState = ci.m_MotionState;
+ m_collisionShape = ci.m_collisionShape;
+ // apply scaling before creating rigid body
+ m_collisionShape->setLocalScaling(m_cci.m_scaling);
+ if (m_cci.m_mass)
+ m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
+ // shape info is shared, increment ref count
+ m_shapeInfo = ci.m_shapeInfo;
+ if (m_shapeInfo)
+ m_shapeInfo->AddRef();
+
m_bulletMotionState = 0;
@@ -116,7 +128,7 @@ void CcdPhysicsController::CreateRigidbody()
m_body = new btRigidBody(m_cci.m_mass,
m_bulletMotionState,
- m_cci.m_collisionShape,
+ m_collisionShape,
m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor,
m_cci.m_linearDamping,m_cci.m_angularDamping,
m_cci.m_friction,m_cci.m_restitution);
@@ -144,6 +156,19 @@ void CcdPhysicsController::CreateRigidbody()
}
}
+static void DeleteBulletShape(btCollisionShape* shape)
+{
+ if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ // shapes based on meshes use an interface that contains the vertices.
+ btTriangleMeshShape* meshShape = static_cast<btTriangleMeshShape*>(shape);
+ btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
+ if (meshInterface)
+ delete meshInterface;
+ }
+ delete shape;
+}
+
CcdPhysicsController::~CcdPhysicsController()
{
//will be reference counted, due to sharing
@@ -155,6 +180,27 @@ CcdPhysicsController::~CcdPhysicsController()
if (m_bulletMotionState)
delete m_bulletMotionState;
delete m_body;
+
+ if (m_collisionShape)
+ {
+ // collision shape is always unique to the controller, can delete it here
+ if (m_collisionShape->isCompound())
+ {
+ // bullet does not delete the child shape, must do it here
+ btCompoundShape* compoundShape = (btCompoundShape*)m_collisionShape;
+ int numChild = compoundShape->getNumChildShapes();
+ for (int i=numChild-1 ; i >= 0; i--)
+ {
+ btCollisionShape* childShape = compoundShape->getChildShape(i);
+ DeleteBulletShape(childShape);
+ }
+ }
+ DeleteBulletShape(m_collisionShape);
+ }
+ if (m_shapeInfo)
+ {
+ m_shapeInfo->Release();
+ }
}
@@ -219,11 +265,33 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
{
m_MotionState = motionstate;
m_registerCount = 0;
-
+ m_collisionShape = NULL;
+
+ // always create a new shape to avoid scaling bug
+ if (m_shapeInfo)
+ {
+ m_shapeInfo->AddRef();
+ m_collisionShape = m_shapeInfo->CreateBulletShape();
+
+ if (m_collisionShape)
+ {
+ // new shape has no scaling, apply initial scaling
+ m_collisionShape->setLocalScaling(m_cci.m_scaling);
+ if (m_cci.m_mass)
+ m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
+ }
+ }
m_body = 0;
CreateRigidbody();
-
+
+ if (m_body)
+ {
+ if (m_cci.m_mass)
+ {
+ m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
+ }
+ }
m_cci.m_physicsEnv->addCcdPhysicsController(this);
@@ -597,29 +665,32 @@ bool CcdPhysicsController::wantsSleeping()
PHY_IPhysicsController* CcdPhysicsController::GetReplica()
{
- //very experimental, shape sharing is not implemented yet.
- //just support btSphereShape/ConeShape for now
-
+ // This is used only to replicate Near and Radar sensor controllers
+ // The replication of object physics controller is done in KX_BulletPhysicsController::GetReplica()
CcdConstructionInfo cinfo = m_cci;
- if (cinfo.m_collisionShape)
+ if (m_shapeInfo)
{
- switch (cinfo.m_collisionShape->getShapeType())
+ // This situation does not normally happen
+ cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape();
+ }
+ else if (m_collisionShape)
+ {
+ switch (m_collisionShape->getShapeType())
{
case SPHERE_SHAPE_PROXYTYPE:
{
- btSphereShape* orgShape = (btSphereShape*)cinfo.m_collisionShape;
+ btSphereShape* orgShape = (btSphereShape*)m_collisionShape;
cinfo.m_collisionShape = new btSphereShape(*orgShape);
break;
}
- case CONE_SHAPE_PROXYTYPE:
+ case CONE_SHAPE_PROXYTYPE:
{
- btConeShape* orgShape = (btConeShape*)cinfo.m_collisionShape;
+ btConeShape* orgShape = (btConeShape*)m_collisionShape;
cinfo.m_collisionShape = new btConeShape(*orgShape);
break;
}
-
default:
{
return 0;
@@ -628,6 +699,7 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplica()
}
cinfo.m_MotionState = new DefaultMotionState();
+ cinfo.m_shapeInfo = m_shapeInfo;
CcdPhysicsController* replica = new CcdPhysicsController(cinfo);
return replica;
@@ -689,3 +761,201 @@ void DefaultMotionState::calculateWorldTransformations()
}
+// Shape constructor
+bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope)
+{
+ // assume no shape information
+ m_shapeType = PHY_SHAPE_NONE;
+ m_vertexArray.clear();
+
+ if (!meshobj)
+ return false;
+
+ // Mesh has no polygons!
+ int numpolys = meshobj->NumPolygons();
+ if (!numpolys)
+ {
+ return false;
+ }
+
+ // check that we have at least one colliding polygon
+ int numvalidpolys = 0;
+
+ for (int p=0; p<numpolys; p++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ numvalidpolys++;
+ break;
+ }
+ }
+
+ // No collision polygons
+ if (numvalidpolys < 1)
+ return false;
+
+ m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
+
+ numvalidpolys = 0;
+
+ for (int p2=0; p2<numpolys; p2++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p2);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ //Bullet can raycast any shape, so
+ if (polytope)
+ {
+ for (int i=0;i<poly->VertexCount();i++)
+ {
+ const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[i],
+ poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+ btPoint3 point(vtx[0],vtx[1],vtx[2]);
+ m_vertexArray.push_back(point);
+ numvalidpolys++;
+ }
+ } else
+ {
+ {
+ const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[2],
+ poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+ btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
+ vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[1],
+ poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+ btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
+ vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[0],
+ poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+ btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
+ m_vertexArray.push_back(vertex0);
+ m_vertexArray.push_back(vertex1);
+ m_vertexArray.push_back(vertex2);
+ numvalidpolys++;
+ }
+ if (poly->VertexCount() == 4)
+ {
+ const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[3],
+ poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+ btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
+ vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[2],
+ poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+ btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
+ vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[0],
+ poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+ btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
+ m_vertexArray.push_back(vertex0);
+ m_vertexArray.push_back(vertex1);
+ m_vertexArray.push_back(vertex2);
+ numvalidpolys++;
+ }
+ }
+ }
+ }
+
+ if (!numvalidpolys)
+ {
+ // should not happen
+ m_shapeType = PHY_SHAPE_NONE;
+ return false;
+ }
+ return true;
+}
+
+btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
+{
+ btCollisionShape* collisionShape = 0;
+ btTriangleMeshShape* concaveShape = 0;
+ btTriangleMesh* collisionMeshData = 0;
+ btCompoundShape* compoundShape = 0;
+ CcdShapeConstructionInfo* nextShapeInfo;
+
+ switch (m_shapeType)
+ {
+ case PHY_SHAPE_NONE:
+ break;
+
+ case PHY_SHAPE_BOX:
+ collisionShape = new btBoxShape(m_halfExtend);
+ break;
+
+ case PHY_SHAPE_SPHERE:
+ collisionShape = new btSphereShape(m_radius);
+ break;
+
+ case PHY_SHAPE_CYLINDER:
+ collisionShape = new btCylinderShapeZ(m_halfExtend);
+ break;
+
+ case PHY_SHAPE_CONE:
+ collisionShape = new btConeShapeZ(m_radius, m_height);
+ break;
+
+ case PHY_SHAPE_POLYTOPE:
+ collisionShape = new btConvexHullShape(&m_vertexArray.begin()->getX(), m_vertexArray.size());
+ break;
+
+ case PHY_SHAPE_MESH:
+ collisionMeshData = new btTriangleMesh();
+ // m_vertexArray is necessarily a multiple of 3
+ for (std::vector<btPoint3>::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); )
+ {
+ collisionMeshData->addTriangle(*it++,*it++,*it++);
+ }
+ concaveShape = new btBvhTriangleMeshShape( collisionMeshData, true );
+ concaveShape->recalcLocalAabb();
+ collisionShape = concaveShape;
+ break;
+
+ case PHY_SHAPE_COMPOUND:
+ if (m_nextShape)
+ {
+ compoundShape = new btCompoundShape();
+ for (nextShapeInfo=m_nextShape; nextShapeInfo; nextShapeInfo = nextShapeInfo->m_nextShape)
+ {
+ collisionShape = nextShapeInfo->CreateBulletShape();
+ if (collisionShape)
+ {
+ compoundShape->addChildShape(nextShapeInfo->m_childTrans, collisionShape);
+ }
+ }
+ collisionShape = compoundShape;
+ }
+ }
+ return collisionShape;
+}
+
+void CcdShapeConstructionInfo::AddShape(CcdShapeConstructionInfo* shapeInfo)
+{
+ CcdShapeConstructionInfo* nextShape = this;
+ while (nextShape->m_nextShape != NULL)
+ nextShape = nextShape->m_nextShape;
+ nextShape->m_nextShape = shapeInfo;
+}
+
+CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
+{
+ CcdShapeConstructionInfo* childShape = m_nextShape;
+
+ while (childShape)
+ {
+ CcdShapeConstructionInfo* nextShape = childShape->m_nextShape;
+ childShape->m_nextShape = NULL;
+ childShape->Release();
+ childShape = nextShape;
+ }
+
+ m_vertexArray.clear();
+}
+
+
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 448e5622eff..1e1a38aa2a6 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -17,11 +17,14 @@ subject to the following restrictions:
#ifndef BULLET2_PHYSICSCONTROLLER_H
#define BULLET2_PHYSICSCONTROLLER_H
+#include <vector>
+
#include "PHY_IPhysicsController.h"
/// PHY_IPhysicsController is the abstract simplified Interface to a physical object.
/// It contains the IMotionState and IDeformableMesh Interfaces.
#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btTransform.h"
#include "PHY_IMotionState.h"
@@ -31,8 +34,66 @@ extern float gAngularSleepingTreshold;
extern bool gDisableDeactivation;
class CcdPhysicsEnvironment;
class btMotionState;
+class RAS_MeshObject;
+class btCollisionShape;
+
+// Shape contructor
+// It contains all the information needed to create a simple bullet shape at runtime
+class CcdShapeConstructionInfo
+{
+public:
+ CcdShapeConstructionInfo() :
+ m_shapeType(PHY_SHAPE_NONE),
+ m_radius(1.0),
+ m_height(1.0),
+ m_halfExtend(0.f,0.f,0.f),
+ m_nextShape(NULL),
+ m_refCount(1)
+ {
+ m_childTrans.setIdentity();
+ }
+ ~CcdShapeConstructionInfo();
+ CcdShapeConstructionInfo* AddRef()
+ {
+ m_refCount++;
+ return this;
+ }
+
+ int Release()
+ {
+ if (--m_refCount > 0)
+ return m_refCount;
+ delete this;
+ return 0;
+ }
+
+ void AddShape(CcdShapeConstructionInfo* shapeInfo);
+
+ CcdShapeConstructionInfo* GetNextShape()
+ {
+ return m_nextShape;
+ }
+
+ bool SetMesh(RAS_MeshObject* mesh, bool polytope);
+
+ btCollisionShape* CreateBulletShape();
+
+ // member variables
+ PHY_ShapeType m_shapeType;
+ btScalar m_radius;
+ btScalar m_height;
+ btVector3 m_halfExtend;
+ btTransform m_childTrans;
+ std::vector<btPoint3> m_vertexArray; // Contains both vertex array for polytope shape and
+ // triangle array for concave mesh shape.
+ // In this case a triangle is made of 3 consecutive points
+protected:
+ CcdShapeConstructionInfo* m_nextShape; // for compound shape
+ int m_refCount; // this class is shared between replicas
+ // keep track of users so that we can release it
+};
struct CcdConstructionInfo
{
@@ -65,6 +126,7 @@ struct CcdConstructionInfo
m_collisionFilterMask(AllFilter),
m_collisionShape(0),
m_MotionState(0),
+ m_shapeInfo(0),
m_physicsEnv(0),
m_inertiaFactor(1.f)
{
@@ -89,8 +151,11 @@ struct CcdConstructionInfo
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
+ ///these pointers are used as argument passing for the CcdPhysicsController constructor
+ ///and not anymore after that
class btCollisionShape* m_collisionShape;
class PHY_IMotionState* m_MotionState;
+ class CcdShapeConstructionInfo* m_shapeInfo;
CcdPhysicsEnvironment* m_physicsEnv; //needed for self-replication
float m_inertiaFactor;//tweak the inertia (hooked up to Blender 'formfactor'
@@ -106,6 +171,9 @@ class CcdPhysicsController : public PHY_IPhysicsController
btRigidBody* m_body;
class PHY_IMotionState* m_MotionState;
btMotionState* m_bulletMotionState;
+ class btCollisionShape* m_collisionShape;
+ class CcdShapeConstructionInfo* m_shapeInfo;
+
friend class CcdPhysicsEnvironment; // needed when updating the controller
@@ -137,6 +205,7 @@ class CcdPhysicsController : public PHY_IPhysicsController
btRigidBody* GetRigidBody() { return m_body;}
+ CcdShapeConstructionInfo* GetShapeInfo() { return m_shapeInfo; }
btCollisionShape* GetCollisionShape() {
return m_body->getCollisionShape();
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index dfbcf115fd7..d8e05fab839 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -1370,8 +1370,9 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
{
CcdConstructionInfo cinfo;
- //This is a memory leak: Bullet does not delete the shape and it cannot be added to
- //the KX_Scene.m_shapes list -- too bad but that's not a lot of data
+
+ // we don't need a CcdShapeConstructionInfo for this shape:
+ // it is simple enough for the standard copy constructor (see CcdPhysicsController::GetReplica)
cinfo.m_collisionShape = new btConeShape(coneradius,coneheight);
cinfo.m_MotionState = 0;
cinfo.m_physicsEnv = this;
diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript
index dd6eab0f018..0936d45197a 100644
--- a/source/gameengine/Physics/Bullet/SConscript
+++ b/source/gameengine/Physics/Bullet/SConscript
@@ -3,7 +3,7 @@ Import ('env')
sources = 'CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp'
-incs = '. ../common'
+incs = '. ../common #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer'
incs += ' ' + env['BF_BULLET_INC']
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
index c289b9d8bcb..3b3e42c38d2 100644
--- a/source/gameengine/Physics/common/PHY_DynamicTypes.h
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -87,6 +87,18 @@ typedef enum PHY_ConstraintType {
} PHY_ConstraintType;
+typedef enum PHY_ShapeType {
+ PHY_SHAPE_NONE,
+ PHY_SHAPE_BOX,
+ PHY_SHAPE_SPHERE,
+ PHY_SHAPE_CYLINDER,
+ PHY_SHAPE_CONE,
+ PHY_SHAPE_MESH,
+ PHY_SHAPE_POLYTOPE,
+ PHY_SHAPE_COMPOUND
+} PHY_ShapeType;
+
+
typedef float PHY_Vector3[3];
#endif //__PHY_DYNAMIC_TYPES