Merging fluidcontrol to trunk from rev16649 fluidcontrol branch. Code provided by...
[blender-staging.git] / source / blender / blenkernel / intern / object.c
index a364c108c380286200462970afd19ae4b795894e..5d352c1e11db51f4aeb7a4cb61ab3383c838ee5c 100644 (file)
@@ -3,15 +3,12 @@
  * 
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,7 +26,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include <string.h>
@@ -53,6 +50,8 @@
 #include "DNA_lattice_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_curve_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_nla_types.h"
@@ -60,6 +59,7 @@
 #include "DNA_object_force.h"
 #include "DNA_object_fluidsim.h"
 #include "DNA_oops_types.h"
+#include "DNA_particle_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
@@ -90,7 +90,6 @@
 #include "BKE_constraint.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
-#include "BKE_effect.h"
 #include "BKE_group.h"
 #include "BKE_icons.h"
 #include "BKE_ipo.h"
 #include "BKE_mball.h"
 #include "BKE_modifier.h"
 #include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
 #include "BKE_property.h"
 #include "BKE_sca.h"
 #include "BKE_scene.h"
 
 #include "BPY_extern.h"
 
+#include "GPU_material.h"
+
+#include "blendef.h"
+
 /* Local function protos */
 static void solve_parenting (Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul);
 
@@ -155,6 +160,25 @@ void update_base_layer(Object *ob)
        }
 }
 
+void object_free_particlesystems(Object *ob)
+{
+       while(ob->particlesystem.first){
+               ParticleSystem *psys = ob->particlesystem.first;
+
+               BLI_remlink(&ob->particlesystem,psys);
+
+               psys_free(ob,psys);
+       }
+}
+
+void object_free_softbody(Object *ob)
+{
+       if(ob->soft) {
+               sbFree(ob->soft);
+               ob->soft= NULL;
+       }
+}
+
 void object_free_modifiers(Object *ob)
 {
        while (ob->modifiers.first) {
@@ -164,6 +188,12 @@ void object_free_modifiers(Object *ob)
 
                modifier_free(md);
        }
+
+       /* particle modifiers were freed, so free the particlesystems as well */
+       object_free_particlesystems(ob);
+
+       /* same for softbody */
+       object_free_softbody(ob);
 }
 
 /* here we will collect all local displist stuff */
@@ -214,14 +244,12 @@ void free_object(Object *ob)
        ob->path= 0;
        if(ob->ipo) ob->ipo->id.us--;
        if(ob->action) ob->action->id.us--;
+       if(ob->poselib) ob->poselib->id.us--;
        if(ob->dup_group) ob->dup_group->id.us--;
        if(ob->defbase.first)
                BLI_freelistN(&ob->defbase);
-       if(ob->pose) {
-               free_pose_channels(ob->pose);
-               MEM_freeN(ob->pose);
-       }
-       free_effects(&ob->effect);
+       if(ob->pose)
+               free_pose(ob->pose);
        free_properties(&ob->prop);
        object_free_modifiers(ob);
        
@@ -235,9 +263,13 @@ void free_object(Object *ob)
        
        BPY_free_scriptlink(&ob->scriptlink);
        
-       if(ob->pd) MEM_freeN(ob->pd);
+       if(ob->pd){
+               if(ob->pd->tex)
+                       ob->pd->tex->id.us--;
+               MEM_freeN(ob->pd);
+       }
        if(ob->soft) sbFree(ob->soft);
-       if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings);
+       if(ob->gpulamp.first) GPU_lamp_free(ob);
 }
 
 static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -263,6 +295,7 @@ void unlink_object(Object *ob)
        Camera *camera;
        bConstraint *con;
        bActionStrip *strip;
+       ModifierData *md;
        int a;
        
        unlink_controllers(&ob->controllers);
@@ -361,10 +394,13 @@ void unlink_object(Object *ob)
                
                /* object is deflector or field */
                if(ob->pd) {
-                       if(give_parteff(obt))
-                               obt->recalc |= OB_RECALC_DATA;
-                       else if(obt->soft)
+                       if(obt->soft)
                                obt->recalc |= OB_RECALC_DATA;
+
+                       /* cloth */
+                       for(md=obt->modifiers.first; md; md=md->next)
+                               if(md->type == eModifierType_Cloth)
+                                       obt->recalc |= OB_RECALC_DATA;
                }
                
                /* strips */
@@ -380,6 +416,47 @@ void unlink_object(Object *ob)
                        }
                }
 
+               /* particle systems */
+               if(obt->particlesystem.first) {
+                       ParticleSystem *tpsys= obt->particlesystem.first;
+                       for(; tpsys; tpsys=tpsys->next) {
+                               if(tpsys->keyed_ob==ob) {
+                                       ParticleSystem *psys= BLI_findlink(&ob->particlesystem,tpsys->keyed_psys-1);
+
+                                       if(psys && psys->keyed_ob) {
+                                               tpsys->keyed_ob= psys->keyed_ob;
+                                               tpsys->keyed_psys= psys->keyed_psys;
+                                       }
+                                       else
+                                               tpsys->keyed_ob= NULL;
+
+                                       obt->recalc |= OB_RECALC_DATA;
+                               }
+
+                               if(tpsys->target_ob==ob) {
+                                       tpsys->target_ob= NULL;
+                                       obt->recalc |= OB_RECALC_DATA;
+                               }
+
+                               if(tpsys->part->dup_ob==ob)
+                                       tpsys->part->dup_ob= NULL;
+
+                               if(tpsys->part->flag&PART_STICKY) {
+                                       ParticleData *pa;
+                                       int p;
+
+                                       for(p=0,pa=tpsys->particles; p<tpsys->totpart; p++,pa++) {
+                                               if(pa->stick_ob==ob) {
+                                                       pa->stick_ob= 0;
+                                                       pa->flag &= ~PARS_STICKY;
+                                               }
+                                       }
+                               }
+                       }
+                       if(ob->pd)
+                               obt->recalc |= OB_RECALC_DATA;
+               }
+
                obt= obt->id.next;
        }
        
@@ -459,11 +536,11 @@ void unlink_object(Object *ob)
 
                                        if(v3d->camera==ob) {
                                                v3d->camera= NULL;
-                                               if(v3d->persp>1) v3d->persp= 1;
+                                               if(v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP;
                                        }
                                        if(v3d->localvd && v3d->localvd->camera==ob ) {
                                                v3d->localvd->camera= NULL;
-                                               if(v3d->localvd->persp>1) v3d->localvd->persp= 1;
+                                               if(v3d->localvd->persp==V3D_CAMOB) v3d->localvd->persp= V3D_PERSP;
                                        }
                                }
                                else if(sl->spacetype==SPACE_IPO) {
@@ -619,9 +696,11 @@ float dof_camera(Object *ob)
        if (cam->dof_ob) {      
                /* too simple, better to return the distance on the view axis only
                 * return VecLenf(ob->obmat[3], cam->dof_ob->obmat[3]); */
+               float mat[4][4], obmat[4][4];
                
-               float mat[4][4];
-               Mat4Invert(ob->imat, ob->obmat);
+               Mat4CpyMat4(obmat, ob->obmat);
+               Mat4Ortho(obmat);
+               Mat4Invert(ob->imat, obmat);
                Mat4MulMat4(mat, cam->dof_ob->obmat, ob->imat);
                return fabs(mat[3][2]);
        }
@@ -657,6 +736,20 @@ void *add_lamp(char *name)
        la->preview=NULL;
        la->falloff_type = LA_FALLOFF_INVLINEAR;
        la->curfalloff = curvemapping_add(1, 0.0f, 1.0f, 1.0f, 0.0f);
+       la->sun_effect_type = 0;
+       la->horizon_brightness = 1.0;
+       la->spread = 1.0;
+       la->sun_brightness = 1.0;
+       la->sun_size = 1.0;
+       la->backscattered_light = 1.0;
+       la->atm_turbidity = 2.0;
+       la->atm_inscattering_factor = 1.0;
+       la->atm_extinction_factor = 1.0;
+       la->atm_distance_factor = 1.0;
+       la->sun_intensity = 1.0;
+       la->skyblendtype= MA_RAMP_ADD;
+       la->skyblendfac= 1.0f;
+
        curvemapping_initialize(la->curfalloff);
        return la;
 }
@@ -827,10 +920,12 @@ Object *add_only_object(int type, char *name)
        ob->type= type;
        /* ob->transflag= OB_QUAT; */
 
+#if 0 /* not used yet */
        QuatOne(ob->quat);
        QuatOne(ob->dquat);
+#endif 
 
-       ob->col[0]= ob->col[1]= ob->col[2]= 0.0;
+       ob->col[0]= ob->col[1]= ob->col[2]= 1.0;
        ob->col[3]= 1.0;
 
        ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0;
@@ -857,6 +952,7 @@ Object *add_only_object(int type, char *name)
        ob->ipowin= ID_OB;      /* the ipowin shown */
        ob->dupon= 1; ob->dupoff= 0;
        ob->dupsta= 1; ob->dupend= 100;
+       ob->dupfacesca = 1.0;
 
        /* Game engine defaults*/
        ob->mass= ob->inertia= 1.0f;
@@ -866,7 +962,8 @@ Object *add_only_object(int type, char *name)
        ob->anisotropicFriction[0] = 1.0f;
        ob->anisotropicFriction[1] = 1.0f;
        ob->anisotropicFriction[2] = 1.0f;
-       ob->gameflag= OB_PROP;
+       ob->gameflag= OB_PROP|OB_COLLISION;
+       ob->margin = 0.0;
 
        /* NT fluid sim defaults */
        ob->fluidsimFlag = 0;
@@ -916,13 +1013,17 @@ void base_init_from_view3d(Base *base, View3D *v3d)
                VECCOPY(ob->loc, G.scene->cursor);
        }
 
-       v3d->viewquat[0]= -v3d->viewquat[0];
-       if (ob->transflag & OB_QUAT) {
-               QUATCOPY(ob->quat, v3d->viewquat);
-       } else {
-               QuatToEul(v3d->viewquat, ob->rot);
+       if (U.flag & USER_ADD_VIEWALIGNED) {
+               v3d->viewquat[0]= -v3d->viewquat[0];
+
+               /* Quats arnt used yet */
+               /*if (ob->transflag & OB_QUAT) {
+                       QUATCOPY(ob->quat, v3d->viewquat);
+               } else {*/
+                       QuatToEul(v3d->viewquat, ob->rot);
+               /*}*/
+               v3d->viewquat[0]= -v3d->viewquat[0];
        }
-       v3d->viewquat[0]= -v3d->viewquat[0];
 }
 
 SoftBody *copy_softbody(SoftBody *sb)
@@ -935,20 +1036,92 @@ SoftBody *copy_softbody(SoftBody *sb)
        sbn->totspring= sbn->totpoint= 0;
        sbn->bpoint= NULL;
        sbn->bspring= NULL;
-       sbn->ctime= 0.0f;
        
        sbn->keys= NULL;
        sbn->totkey= sbn->totpointkey= 0;
        
        sbn->scratch= NULL;
+
+       sbn->pointcache= BKE_ptcache_copy(sb->pointcache);
+
        return sbn;
 }
 
+ParticleSystem *copy_particlesystem(ParticleSystem *psys)
+{
+       ParticleSystem *psysn;
+       ParticleData *pa;
+       int a;
+
+       psysn= MEM_dupallocN(psys);
+       psysn->particles= MEM_dupallocN(psys->particles);
+       psysn->child= MEM_dupallocN(psys->child);
+
+       for(a=0, pa=psysn->particles; a<psysn->totpart; a++, pa++) {
+               if(pa->hair)
+                       pa->hair= MEM_dupallocN(pa->hair);
+               if(pa->keys)
+                       pa->keys= MEM_dupallocN(pa->keys);
+       }
+
+       if(psys->soft) {
+               psysn->soft= copy_softbody(psys->soft);
+               psysn->soft->particles = psysn;
+       }
+       
+       psysn->pathcache= NULL;
+       psysn->childcache= NULL;
+       psysn->edit= NULL;
+       psysn->effectors.first= psysn->effectors.last= 0;
+       
+       psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL;
+       psysn->childcachebufs.first = psysn->childcachebufs.last = NULL;
+       psysn->reactevents.first = psysn->reactevents.last = NULL;
+       psysn->renderdata = NULL;
+       
+       psysn->pointcache= BKE_ptcache_copy(psys->pointcache);
+
+       id_us_plus((ID *)psysn->part);
+
+       return psysn;
+}
+
+void copy_object_particlesystems(Object *obn, Object *ob)
+{
+       ParticleSystemModifierData *psmd;
+       ParticleSystem *psys, *npsys;
+       ModifierData *md;
+
+       obn->particlesystem.first= obn->particlesystem.last= NULL;
+       for(psys=ob->particlesystem.first; psys; psys=psys->next) {
+               npsys= copy_particlesystem(psys);
+
+               BLI_addtail(&obn->particlesystem, npsys);
+
+               /* need to update particle modifiers too */
+               for(md=obn->modifiers.first; md; md=md->next) {
+                       if(md->type==eModifierType_ParticleSystem) {
+                               psmd= (ParticleSystemModifierData*)md;
+                               if(psmd->psys==psys)
+                                       psmd->psys= npsys;
+                       }
+               }
+       }
+}
+
+void copy_object_softbody(Object *obn, Object *ob)
+{
+       if(ob->soft)
+               obn->soft= copy_softbody(ob->soft);
+}
+
 static void copy_object_pose(Object *obn, Object *ob)
 {
        bPoseChannel *chan;
        
-       copy_pose(&obn->pose, ob->pose, 1);
+       /* note: need to clear obn->pose pointer first, so that copy_pose works (otherwise there's a crash) */
+       obn->pose= NULL;
+       copy_pose(&obn->pose, ob->pose, 1);     /* 1 = copy constraints */
 
        for (chan = obn->pose->chanbase.first; chan; chan=chan->next){
                bConstraint *con;
@@ -960,6 +1133,14 @@ static void copy_object_pose(Object *obn, Object *ob)
                        ListBase targets = {NULL, NULL};
                        bConstraintTarget *ct;
                        
+                       if(con->ipo) {
+                               IpoCurve *icu;
+                               for(icu= con->ipo->curve.first; icu; icu= icu->next) {
+                                       if(icu->driver && icu->driver->ob==ob)
+                                               icu->driver->ob= obn;
+                               }
+                       }
+                       
                        if (cti && cti->get_constraint_targets) {
                                cti->get_constraint_targets(con, &targets);
                                
@@ -991,7 +1172,6 @@ Object *copy_object(Object *ob)
        obn->path= NULL;
        obn->flag &= ~OB_FROMGROUP;
        
-       copy_effects(&obn->effect, &ob->effect);
        obn->modifiers.first = obn->modifiers.last= NULL;
        
        for (md=ob->modifiers.first; md; md=md->next) {
@@ -1029,17 +1209,14 @@ Object *copy_object(Object *ob)
        
        obn->disp.first= obn->disp.last= NULL;
        
-       if(ob->pd) obn->pd= MEM_dupallocN(ob->pd);
+       if(ob->pd){
+               obn->pd= MEM_dupallocN(ob->pd);
+               if(obn->pd->tex)
+                       id_us_plus(&(obn->pd->tex->id));
+       }
        obn->soft= copy_softbody(ob->soft);
 
-       /* NT copy fluid sim setting memory */
-       if(obn->fluidsimSettings) {
-               obn->fluidsimSettings = fluidsimSettingsCopy(ob->fluidsimSettings);
-               /* copying might fail... */
-               if(obn->fluidsimSettings) {
-                       obn->fluidsimSettings->orgMesh = (Mesh *)obn->data;
-               }
-       }
+       copy_object_particlesystems(obn, ob);
        
        obn->derivedDeform = NULL;
        obn->derivedFinal = NULL;
@@ -1048,6 +1225,7 @@ Object *copy_object(Object *ob)
        obn->vnode = NULL;
 #endif
 
+       obn->gpulamp.first = obn->gpulamp.last = NULL;
 
        return obn;
 }
@@ -1055,11 +1233,13 @@ Object *copy_object(Object *ob)
 void expand_local_object(Object *ob)
 {
        bActionStrip *strip;
+       ParticleSystem *psys;
        int a;
        
        id_lib_extern((ID *)ob->action);
        id_lib_extern((ID *)ob->ipo);
        id_lib_extern((ID *)ob->data);
+       id_lib_extern((ID *)ob->dup_group);
        
        for(a=0; a<ob->totcol; a++) {
                id_lib_extern((ID *)ob->mat[a]);
@@ -1067,7 +1247,8 @@ void expand_local_object(Object *ob)
        for (strip=ob->nlastrips.first; strip; strip=strip->next) {
                id_lib_extern((ID *)strip->act);
        }
-
+       for(psys=ob->particlesystem.first; psys; psys=psys->next)
+               id_lib_extern((ID *)psys->part);
 }
 
 void make_local_object(Object *ob)
@@ -1139,6 +1320,20 @@ void make_local_object(Object *ob)
 
 /* *************** PROXY **************** */
 
+/* when you make proxy, ensure the exposed layers are extern */
+void armature_set_id_extern(Object *ob)
+{
+       bArmature *arm= ob->data;
+       bPoseChannel *pchan;
+       int lay= arm->layer_protected;
+       
+       for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+               if(!(pchan->bone->layer & lay))
+                       id_lib_extern((ID *)pchan->custom);
+       }
+                       
+}
+
 /* proxy rule: lib_object->proxy_from == the one we borrow from, set temporally while object_update */
 /*             local_object->proxy == pointer to library object, saved in files and read */
 /*             local_object->proxy_group == pointer to group dupli-object, saved in files and read */
@@ -1162,6 +1357,8 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
                VECCOPY(ob->loc, gob->loc);
                VECCOPY(ob->rot, gob->rot);
                VECCOPY(ob->size, gob->size);
+               
+               group_tag_recalc(gob->dup_group);
        }
        else {
                VECCOPY(ob->loc, target->loc);
@@ -1175,15 +1372,36 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
        
        /* skip constraints, constraintchannels, nla? */
        
+       /* set object type and link to data */
        ob->type= target->type;
        ob->data= target->data;
        id_us_plus((ID *)ob->data);             /* ensures lib data becomes LIB_EXTERN */
        
+       /* copy material and index information */
+       ob->actcol= ob->totcol= 0;
+       if(ob->mat) MEM_freeN(ob->mat);
+       ob->mat = NULL;
+       if ((target->totcol) && (target->mat) && OB_SUPPORT_MATERIAL(ob)) {
+               int i;
+               ob->colbits = target->colbits;
+               
+               ob->actcol= target->actcol;
+               ob->totcol= target->totcol;
+               
+               ob->mat = MEM_dupallocN(target->mat);
+               for(i=0; i<target->totcol; i++) {
+                       /* dont need to run test_object_materials since we know this object is new and not used elsewhere */
+                       id_us_plus((ID *)ob->mat[i]); 
+               }
+       }
+       
        /* type conversions */
        if(target->type == OB_ARMATURE) {
                copy_object_pose(ob, target);   /* data copy, object pointers in constraints */
                rest_pose(ob->pose);                    /* clear all transforms in channels */
                armature_rebuild_pose(ob, ob->data);    /* set all internal links */
+               
+               armature_set_id_extern(ob);
        }
 }
 
@@ -1223,12 +1441,12 @@ float bsystem_time(Object *ob, float cfra, float ofs)
        cfra*= G.scene->r.framelen;     
        
        if (ob) {
-               if (no_speed_curve==0 && ob->ipo) 
+               if (no_speed_curve==0 && ob->ipo)
                        cfra= calc_ipo_time(ob->ipo, cfra);
                
                /* ofset frames */
                if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) 
-                       cfra-= ob->sf;
+                       cfra-= give_timeoffset(ob);
        }
        
        cfra-= ofs;
@@ -1240,7 +1458,7 @@ void object_to_mat3(Object *ob, float mat[][3])   /* no parent */
 {
        float smat[3][3], vec[3];
        float rmat[3][3];
-       float q1[4];
+       /*float q1[4];*/
        
        /* size */
        if(ob->ipo) {
@@ -1254,7 +1472,8 @@ void object_to_mat3(Object *ob, float mat[][3])   /* no parent */
        }
 
        /* rot */
-       if(ob->transflag & OB_QUAT) {
+       /* Quats arnt used yet */
+       /*if(ob->transflag & OB_QUAT) {
                if(ob->ipo) {
                        QuatMul(q1, ob->quat, ob->dquat);
                        QuatToMat3(q1, rmat);
@@ -1263,7 +1482,7 @@ void object_to_mat3(Object *ob, float mat[][3])   /* no parent */
                        QuatToMat3(ob->quat, rmat);
                }
        }
-       else {
+       else {*/
                if(ob->ipo) {
                        vec[0]= ob->rot[0]+ob->drot[0];
                        vec[1]= ob->rot[1]+ob->drot[1];
@@ -1273,7 +1492,7 @@ void object_to_mat3(Object *ob, float mat[][3])   /* no parent */
                else {
                        EulToMat3(ob->rot, rmat);
                }
-       }
+       /*}*/
        Mat3MulMat3(mat, rmat, smat);
 }
 
@@ -1298,8 +1517,8 @@ int enable_cu_speed= 1;
 static void ob_parcurve(Object *ob, Object *par, float mat[][4])
 {
        Curve *cu;
-       float q[4], vec[4], dir[3], *quat, x1, ctime;
-       float timeoffs= 0.0;
+       float q[4], vec[4], dir[3], quat[4], x1, ctime;
+       float timeoffs = 0.0, sf_orig = 0.0;
        
        Mat4One(mat);
        
@@ -1310,7 +1529,8 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4])
        
        /* exception, timeoffset is regarded as distance offset */
        if(cu->flag & CU_OFFS_PATHDIST) {
-               SWAP(float, timeoffs, ob->sf);
+               timeoffs = give_timeoffset(ob);
+               SWAP(float, sf_orig, ob->sf);
        }
        
        /* catch exceptions: feature for nla stride editing */
@@ -1327,7 +1547,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4])
                }
        }
        else {
-               ctime= G.scene->r.cfra - ob->sf;
+               ctime= G.scene->r.cfra - give_timeoffset(ob);
                ctime /= cu->pathlen;
                
                CLAMP(ctime, 0.0, 1.0);
@@ -1338,7 +1558,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4])
                ctime += timeoffs/cu->path->totdist;
 
                /* restore */
-               SWAP(float, timeoffs, ob->sf);
+               SWAP(float, sf_orig, ob->sf);
        }
        
        
@@ -1346,7 +1566,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4])
        if( where_on_path(par, ctime, vec, dir) ) {
 
                if(cu->flag & CU_FOLLOW) {
-                       quat= vectoquat(dir, ob->trackflag, ob->upflag);
+                       vectoquat(dir, ob->trackflag, ob->upflag, quat);
                        
                        /* the tilt */
                        Normalize(dir);
@@ -1407,7 +1627,7 @@ static void give_parvert(Object *par, int nr, float *vec)
                        
                        for(eve= em->verts.first; eve; eve= eve->next) {
                                if(eve->keyindex==nr) {
-                                       memcpy(vec, eve->co, 12);
+                                       memcpy(vec, eve->co, sizeof(float)*3);
                                        break;
                                }
                        }
@@ -1429,9 +1649,12 @@ static void give_parvert(Object *par, int nr, float *vec)
                                        }
                                }
 
-                               if(count > 0) {
+                               if (count==0) {
+                                       /* keep as 0,0,0 */
+                               } else if(count > 0) {
                                        VecMulf(vec, 1.0f / count);
                                } else {
+                                       /* use first index if its out of range */
                                        dm->getVertCo(dm, 0, vec);
                                }
                        }
@@ -1442,18 +1665,20 @@ static void give_parvert(Object *par, int nr, float *vec)
                Curve *cu;
                BPoint *bp;
                BezTriple *bezt;
+               int found= 0;
                
                cu= par->data;
                nu= cu->nurb.first;
                if(par==G.obedit) nu= editNurb.first;
                
                count= 0;
-               while(nu) {
+               while(nu && !found) {
                        if((nu->type & 7)==CU_BEZIER) {
                                bezt= nu->bezt;
                                a= nu->pntsu;
                                while(a--) {
                                        if(count==nr) {
+                                               found= 1;
                                                VECCOPY(vec, bezt->vec[1]);
                                                break;
                                        }
@@ -1466,7 +1691,8 @@ static void give_parvert(Object *par, int nr, float *vec)
                                a= nu->pntsu*nu->pntsv;
                                while(a--) {
                                        if(count==nr) {
-                                               memcpy(vec, bp->vec, 12);
+                                               found= 1;
+                                               memcpy(vec, bp->vec, sizeof(float)*3);
                                                break;
                                        }
                                        count++;
@@ -1596,7 +1822,7 @@ void where_is_object_time(Object *ob, float ctime)
        if(ob->parent) {
                Object *par= ob->parent;
                
-               if(ob->ipoflag & OB_OFFS_PARENT) ctime-= ob->sf;
+               if(ob->ipoflag & OB_OFFS_PARENT) ctime-= give_timeoffset(ob);
                
                /* hurms, code below conflicts with depgraph... (ton) */
                /* and even worse, it gives bad effects for NLA stride too (try ctime != par->ctime, with MBlur) */
@@ -1620,7 +1846,7 @@ void where_is_object_time(Object *ob, float ctime)
                if(ob->partype & PARSLOW) {
                        // include framerate
 
-                       fac1= (1.0f/(1.0f+ fabs(ob->sf)));
+                       fac1= (1.0f/(1.0f+ fabs(give_timeoffset(ob))));
                        if(fac1>=1.0) return;
                        fac2= 1.0f-fac1;
                        
@@ -1746,13 +1972,13 @@ static void solve_parenting (Object *ob, Object *par, float obmat[][4], float sl
 }
 void solve_tracking (Object *ob, float targetmat[][4])
 {
-       float *quat;
+       float quat[4];
        float vec[3];
        float totmat[3][3];
        float tmat[4][4];
        
        VecSubf(vec, ob->obmat[3], targetmat[3]);
-       quat= vectoquat(vec, ob->trackflag, ob->upflag);
+       vectoquat(vec, ob->trackflag, ob->upflag, quat);
        QuatToMat3(quat, totmat);
        
        if(ob->parent && (ob->transflag & OB_POWERTRACK)) {
@@ -1803,7 +2029,7 @@ for a lamp that is the child of another object */
 
                if(ob->partype & PARSLOW) {
 
-                       fac1= (float)(1.0/(1.0+ fabs(ob->sf)));
+                       fac1= (float)(1.0/(1.0+ fabs(give_timeoffset(ob))));
                        fac2= 1.0f-fac1;
                        fp1= ob->obmat[0];
                        fp2= slowmat[0];
@@ -1864,7 +2090,7 @@ BoundBox *unit_boundbox()
        BoundBox *bb;
        float min[3] = {-1,-1,-1}, max[3] = {-1,-1,-1};
 
-       bb= MEM_mallocN(sizeof(BoundBox), "bb");
+       bb= MEM_callocN(sizeof(BoundBox), "bb");
        boundbox_set_from_min_max(bb, min, max);
        
        return bb;
@@ -1887,7 +2113,7 @@ BoundBox *object_get_boundbox(Object *ob)
        BoundBox *bb= NULL;
        
        if(ob->type==OB_MESH) {
-               bb = mesh_get_bb(ob->data);
+               bb = mesh_get_bb(ob);
        }
        else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
                bb= ( (Curve *)ob->data )->bb;
@@ -1949,7 +2175,7 @@ void minmax_object(Object *ob, float *min, float *max)
                me= get_mesh(ob);
                
                if(me) {
-                       bb = *mesh_get_bb(me);
+                       bb = *mesh_get_bb(ob);
                        
                        for(a=0; a<8; a++) {
                                Mat4MulVecfl(ob->obmat, bb.vec[a]);
@@ -2008,7 +2234,7 @@ void object_handle_update(Object *ob)
        if(ob->recalc & OB_RECALC) {
                
                if(ob->recalc & OB_RECALC_OB) {
-                       
+
                        // printf("recalcob %s\n", ob->id.name+2);
                        
                        /* handle proxy copy for target */
@@ -2024,6 +2250,7 @@ void object_handle_update(Object *ob)
                        }
                        else
                                where_is_object(ob);
+                       if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_OBJECTUPDATE);
                }
                
                if(ob->recalc & OB_RECALC_DATA) {
@@ -2043,6 +2270,16 @@ void object_handle_update(Object *ob)
                        else if(ob->type==OB_LATTICE) {
                                lattice_calc_modifiers(ob);
                        }
+                       else if(ob->type==OB_CAMERA) {
+                               Camera *cam = (Camera *)ob->data;
+                               calc_ipo(cam->ipo, frame_to_float(G.scene->r.cfra));
+                               execute_ipo(&cam->id, cam->ipo);
+                       }
+                       else if(ob->type==OB_LAMP) {
+                               Lamp *la = (Lamp *)ob->data;
+                               calc_ipo(la->ipo, frame_to_float(G.scene->r.cfra));
+                               execute_ipo(&la->id, la->ipo);
+                       }
                        else if(ob->type==OB_ARMATURE) {
                                /* this happens for reading old files and to match library armatures with poses */
                                if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC))
@@ -2057,8 +2294,41 @@ void object_handle_update(Object *ob)
                                        where_is_pose(ob);
                                }
                        }
+
+                       if(ob->particlesystem.first) {
+                               ParticleSystem *tpsys, *psys;
+                               DerivedMesh *dm;
+                               
+                               psys= ob->particlesystem.first;
+                               while(psys) {
+                                       if(psys_check_enabled(ob, psys)) {
+                                               particle_system_update(ob, psys);
+                                               psys= psys->next;
+                                       }
+                                       else if(psys->flag & PSYS_DELETE) {
+                                               tpsys=psys->next;
+                                               BLI_remlink(&ob->particlesystem, psys);
+                                               psys_free(ob,psys);
+                                               psys= tpsys;
+                                       }
+                                       else
+                                               psys= psys->next;
+                               }
+
+                               if(G.rendering && ob->transflag & OB_DUPLIPARTS) {
+                                       /* this is to make sure we get render level duplis in groups:
+                                        * the derivedmesh must be created before init_render_mesh,
+                                        * since object_duplilist does dupliparticles before that */
+                                       dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+                                       dm->release(dm);
+
+                                       for(psys=ob->particlesystem.first; psys; psys=psys->next)
+                                               psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
+                               }
+                       }
+                       if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_OBDATAUPDATE);
                }
-       
+
                /* the no-group proxy case, we call update */
                if(ob->proxy && ob->proxy_group==NULL) {
                        /* set pointer in library proxy target, for copying, but restore it */
@@ -2076,3 +2346,78 @@ void object_handle_update(Object *ob)
                // printf("set proxy pointer for later group stuff %s\n", ob->id.name);
        }
 }
+
+float give_timeoffset(Object *ob) {
+       if ((ob->ipoflag & OB_OFFS_PARENTADD) && ob->parent) {
+               return ob->sf + give_timeoffset(ob->parent);
+       } else {
+               return ob->sf;
+       }
+}
+
+int give_obdata_texspace(Object *ob, int **texflag, float **loc, float **size, float **rot) {
+       
+       if (ob->data==NULL)
+               return 0;
+       
+       switch (GS(((ID *)ob->data)->name)) {
+       case ID_ME:
+       {
+               Mesh *me= ob->data;
+               if (texflag)    *texflag = &me->texflag;
+               if (loc)                *loc = me->loc;
+               if (size)               *size = me->size;
+               if (rot)                *rot = me->rot;
+               break;
+       }
+       case ID_CU:
+       {
+               Curve *cu= ob->data;
+               if (texflag)    *texflag = &cu->texflag;
+               if (loc)                *loc = cu->loc;
+               if (size)               *size = cu->size;
+               if (rot)                *rot = cu->rot;
+               break;
+       }
+       case ID_MB:
+       {
+               MetaBall *mb= ob->data;
+               if (texflag)    *texflag = &mb->texflag;
+               if (loc)                *loc = mb->loc;
+               if (size)               *size = mb->size;
+               if (rot)                *rot = mb->rot;
+               break;
+       }
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+/*
+ * Test a bounding box for ray intersection
+ * assumes the ray is already local to the boundbox space
+ */
+int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3])
+{
+       static int triangle_indexes[12][3] = {{0, 1, 2}, {0, 2, 3},
+                                                                                 {3, 2, 6}, {3, 6, 7},
+                                                                                 {1, 2, 6}, {1, 6, 5}, 
+                                                                                 {5, 6, 7}, {4, 5, 7},
+                                                                                 {0, 3, 7}, {0, 4, 7},
+                                                                                 {0, 1, 5}, {0, 4, 5}};
+       int result = 0;
+       int i;
+       
+       for (i = 0; i < 12 && result == 0; i++)
+       {
+               float lambda;
+               int v1, v2, v3;
+               v1 = triangle_indexes[i][0];
+               v2 = triangle_indexes[i][1];
+               v3 = triangle_indexes[i][2];
+               result = RayIntersectsTriangle(ray_start, ray_normal, bb->vec[v1], bb->vec[v2], bb->vec[v3], &lambda, NULL);
+       }
+       
+       return result;
+}