diff options
author | Nicholas Bishop <nicholasbishop@gmail.com> | 2010-10-18 05:10:35 +0400 |
---|---|---|
committer | Nicholas Bishop <nicholasbishop@gmail.com> | 2010-10-18 05:10:35 +0400 |
commit | 5b31d545dfae5ee3fd5f4a5d0e9497a1c7c2a86b (patch) | |
tree | 7494146547b5ca59c5a206ab59daa90d60a85a20 /source/blender/blenkernel | |
parent | 9e7142e2b0d2e8cdc78ca45162584b6da892931e (diff) | |
parent | 8b7e01b0bbdada3070c52f980a5f610d4a6c98c8 (diff) |
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r31926:32200
Diffstat (limited to 'source/blender/blenkernel')
31 files changed, 865 insertions, 2059 deletions
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 0e406a16d0c..25d0eb5bc36 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -62,7 +62,7 @@ float brush_curve_strength_clamp(struct Brush *br, float p, const float len); float brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ /* sampling */ -void brush_sample_tex(struct Brush *brush, float *xy, float *rgba); +void brush_sample_tex(struct Brush *brush, float *xy, float *rgba, const int thread); void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf); diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index f6d41190c5a..9f38c5833a2 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -163,6 +163,8 @@ void CTX_wm_screen_set(bContext *C, struct bScreen *screen); /* to be removed */ void CTX_wm_area_set(bContext *C, struct ScrArea *sa); void CTX_wm_region_set(bContext *C, struct ARegion *region); void CTX_wm_menu_set(bContext *C, struct ARegion *menu); +const char *CTX_wm_operator_poll_msg_get(struct bContext *C); +void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg); /* Data Context diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h index bd5af66c6a8..740a94b6169 100644 --- a/source/blender/blenkernel/BKE_exotic.h +++ b/source/blender/blenkernel/BKE_exotic.h @@ -34,9 +34,6 @@ struct Mesh; struct Scene; -void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a); -unsigned int *mcol_to_vcol(struct Mesh *me); // used in py_main.c - /** * Reads all 3D fileformats other than Blender fileformat * @retval 0 The file could not be read. @@ -46,7 +43,6 @@ unsigned int *mcol_to_vcol(struct Mesh *me); // used in py_main.c int BKE_read_exotic(struct Scene *scene, char *name); void write_dxf(struct Scene *scene, char *str); -void write_vrml(struct Scene *scene, char *str); void write_stl(struct Scene *scene, char *str); #endif diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index c842efaa3b2..0a07e6d482c 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -48,7 +48,7 @@ void BKE_stamp_info(struct Scene *scene, struct ImBuf *ibuf); void BKE_stamp_buf(struct Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels); int BKE_write_ibuf(struct Scene *scene, struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); void BKE_makepicstring(char *string, char *base, int frame, int imtype, int use_ext); -void BKE_add_image_extension(char *string, int imtype); +int BKE_add_image_extension(char *string, int imtype); int BKE_ftype_to_imtype(int ftype); int BKE_imtype_to_ftype(int imtype); int BKE_imtype_is_movie(int imtype); @@ -115,7 +115,7 @@ void BKE_image_release_ibuf(struct Image *ima, void *lock); struct Image *BKE_add_image_file(const char *name, int frame); /* adds image, adds ibuf, generates color or pattern */ -struct Image *BKE_add_image_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]); +struct Image *BKE_add_image_size(unsigned int width, unsigned int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]); /* adds image from imbuf, owns imbuf */ struct Image *BKE_add_image_imbuf(struct ImBuf *ibuf); diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h index 36ccc1f1497..7461d43e721 100644 --- a/source/blender/blenkernel/BKE_unit.h +++ b/source/blender/blenkernel/BKE_unit.h @@ -36,12 +36,18 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system, /* replace units with values, used before python button evaluation */ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pref, int system, int type); +/* make string keyboard-friendly: 10µm --> 10um */ +void bUnit_ToUnitAltName(char *str, int len_max, char *orig_str, int system, int type); + /* the size of the unit used for this value (used for calculating the ckickstep) */ double bUnit_ClosestScalar(double value, int system, int type); /* base scale for these units */ double bUnit_BaseScalar(int system, int type); +/* return true is the unit system exists */ +int bUnit_IsValid(int system, int type); + /* loop over scales, coudl add names later */ //double bUnit_Iter(void **unit, char **name, int system, int type); @@ -60,6 +66,7 @@ double bUnit_GetScaler(void *usys_pt, int index); #define B_UNIT_TIME 6 #define B_UNIT_VELOCITY 7 #define B_UNIT_ACCELERATION 8 +#define B_UNIT_MAXDEF 9 #ifdef __cplusplus } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index f7f11279fad..784c7116a65 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -31,7 +31,6 @@ SET(INC ../avi ../blenlib ../blenloader - ../editors/include ../gpu ../ikplugin ../imbuf @@ -39,6 +38,7 @@ SET(INC ../makesrna ../modifiers ../nodes + ../editors/include ../render/extern/include ../../../extern/glew/include ../../../intern/audaspace/intern diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index b2441a8a58f..ae99e2c9242 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -242,6 +242,15 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me) if(!CustomData_has_layer(&tmp.fdata, CD_MFACE)) CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupFaceArray(dm), totface); + /* object had got displacement layer, should copy this layer to save sculpted data */ + /* NOTE: maybe some other layers should be copied? nazgul */ + if(CustomData_has_layer(&me->fdata, CD_MDISPS)) { + if (totface == me->totface) { + MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + CustomData_add_layer(&tmp.fdata, CD_MDISPS, CD_DUPLICATE, mdisps, totface); + } + } + mesh_update_customdata_pointers(&tmp); CustomData_free(&me->vdata, me->totvert); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 98bdf3b2e9f..6da9f2bbabc 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -640,29 +640,19 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, /* Need to verify the quat interpolation is correct - XXX */ if (quat) { - //float totfac, q1[4], q2[4]; + float totfac, q1[4], q2[4]; - /* checks for totfac are needed when 'fac' is 1.0 key_curve_position_weights can assign zero - * to more then one index in data which can give divide by zero error */ -/* - totfac= data[0]+data[1]; - if(totfac>0.000001) interp_qt_qtqt(q1, p0->quat, p1->quat, data[0] / totfac); - else QUATCOPY(q1, p1->quat); + totfac= data[0]+data[3]; + if(totfac>FLT_EPSILON) interp_qt_qtqt(q1, p0->quat, p3->quat, data[3] / totfac); + else QUATCOPY(q1, p1->quat); - normalize_qt(q1); - - totfac= data[2]+data[3]; - if(totfac>0.000001) interp_qt_qtqt(q2, p2->quat, p3->quat, data[2] / totfac); - else QUATCOPY(q1, p3->quat); - normalize_qt(q2); + totfac= data[1]+data[2]; + if(totfac>FLT_EPSILON) interp_qt_qtqt(q2, p1->quat, p2->quat, data[2] / totfac); + else QUATCOPY(q1, p3->quat); totfac = data[0]+data[1]+data[2]+data[3]; - if(totfac>0.000001) interp_qt_qtqt(quat, q1, q2, (data[0]+data[1]) / totfac); - else QUATCOPY(quat, q2); - normalize_qt(quat); - */ - // XXX - find some way to make quat interpolation work correctly, above code fails in rare but nasty cases. - QUATCOPY(quat, p1->quat); + if(totfac>FLT_EPSILON) interp_qt_qtqt(quat, q1, q2, (data[1]+data[2]) / totfac); + else QUATCOPY(quat, q2); } if(radius) diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 41821f34ba8..2e760f53155 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1289,7 +1289,9 @@ void vec_roll_to_mat3(float *vec, float roll, float mat[][3]) /* Find Axis & Amount for bone matrix*/ cross_v3_v3v3(axis,target,nor); - if (dot_v3v3(axis,axis) > 0.0000000000001) { + /* was 0.0000000000001, caused bug [#23954], smaller values give unstable + * roll when toggling editmode */ + if (dot_v3v3(axis,axis) > 0.00001) { /* if nor is *not* a multiple of target ... */ normalize_v3(axis); diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 54ffda6c0a9..69a42e52247 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -240,6 +240,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size); bbd->wanted_speed = sqrt(t) * len_v3(pa->prev_state.vel); + bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed); return 1; } @@ -736,6 +737,7 @@ static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData * val->jump_speed = 0.0f; /* no jumping in air */ } } + static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *ground_co, float *ground_nor) { BoidParticle *bpa = pa->boid; @@ -765,16 +767,15 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro if(!bbd->sim->colliders) return NULL; + /* first try to find below boid */ copy_v3_v3(col.co1, pa->state.co); - copy_v3_v3(col.co2, pa->state.co); - add_v3_v3(col.co1, zvec); + sub_v3_v3v3(col.co2, pa->state.co, zvec); sub_v3_v3(col.co2, zvec); sub_v3_v3v3(ray_dir, col.co2, col.co1); col.t = 0.0f; hit.index = -1; hit.dist = col.ray_len = len_v3(ray_dir); - /* find out upmost deflector object */ for(coll = bbd->sim->colliders->first; coll; coll = coll->next){ col.ob = coll->ob; col.md = coll->collmd; @@ -789,14 +790,37 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro normalize_v3_v3(ground_nor, col.nor); return col.hit_ob; } - else { - /* default to z=0 */ - VECCOPY(ground_co, pa->state.co); - ground_co[2] = 0; - ground_nor[0] = ground_nor[1] = 0.0f; - ground_nor[2] = 1.0f; - return NULL; + + /* couldn't find below, so find upmost deflector object */ + add_v3_v3v3(col.co1, pa->state.co, zvec); + sub_v3_v3v3(col.co2, pa->state.co, zvec); + sub_v3_v3(col.co2, zvec); + sub_v3_v3v3(ray_dir, col.co2, col.co1); + col.t = 0.0f; + hit.index = -1; + hit.dist = col.ray_len = len_v3(ray_dir); + + for(coll = bbd->sim->colliders->first; coll; coll = coll->next){ + col.ob = coll->ob; + col.md = coll->collmd; + + if(col.md && col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); + } + /* then use that object */ + if(hit.index>=0) { + t = hit.dist/col.ray_len; + interp_v3_v3v3(ground_co, col.co1, col.co2, t); + normalize_v3_v3(ground_nor, col.nor); + return col.hit_ob; } + + /* default to z=0 */ + VECCOPY(ground_co, pa->state.co); + ground_co[2] = 0; + ground_nor[0] = ground_nor[1] = 0.0f; + ground_nor[2] = 1.0f; + return NULL; } } static int boid_rule_applies(ParticleData *pa, BoidSettings *boids, BoidRule *rule) @@ -1226,8 +1250,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) VECADDFAC(pa->state.vel, pa->state.vel, acc, dtime); - if(bpa->data.mode != eBoidMode_InAir) - bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); + //if(bpa->data.mode != eBoidMode_InAir) + bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); /* change modes, constrain movement & keep track of down vector */ switch(bpa->data.mode) { @@ -1255,11 +1279,18 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) boid_find_ground(bbd, pa, ground_co, ground_nor); boid_climb(boids, pa, ground_co, ground_nor); } - /* land boid when belowg ground */ - else if(boids->options & BOID_ALLOW_LAND && pa->state.co[2] <= ground_co[2] + pa->size * boids->height) { - pa->state.co[2] = ground_co[2] + pa->size * boids->height; - pa->state.vel[2] = 0.0f; - bpa->data.mode = eBoidMode_OnLand; + else if(pa->state.co[2] <= ground_co[2] + pa->size * boids->height) { + /* land boid when below ground */ + if(boids->options & BOID_ALLOW_LAND) { + pa->state.co[2] = ground_co[2] + pa->size * boids->height; + pa->state.vel[2] = 0.0f; + bpa->data.mode = eBoidMode_OnLand; + } + /* fly above ground */ + else { + pa->state.co[2] = ground_co[2] + pa->size * boids->height; + pa->state.vel[2] = 0.0f; + } } break; } @@ -1355,7 +1386,9 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) /* save direction to state.ave unless the boid is falling */ /* (boids can't effect their direction when falling) */ if(bpa->data.mode!=eBoidMode_Falling && len_v3(pa->state.vel) > 0.1*pa->size) { - normalize_v3_v3(pa->state.ave, pa->state.vel); + copy_v3_v3(pa->state.ave, pa->state.vel); + pa->state.ave[2] *= bbd->part->boids->pitch; + normalize_v3(pa->state.ave); } /* apply damping */ @@ -1440,6 +1473,7 @@ void boid_default_settings(BoidSettings *boids) boids->landing_smoothness = 3.0f; boids->banking = 1.0f; + boids->pitch = 1.0f; boids->height = 1.0f; boids->health = 1.0f; diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 90ea562be9d..c67db9382f3 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -480,7 +480,7 @@ int brush_clone_image_delete(Brush *brush) } /* Brush Sampling */ -void brush_sample_tex(Brush *brush, float *xy, float *rgba) +void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread) { MTex *mtex= &brush->mtex; @@ -493,7 +493,7 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba) co[1]= xy[1]/radius; co[2]= 0.0f; - hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta); + hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); if (hasrgb) { rgba[0]= tr; @@ -547,12 +547,12 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius); } else if (texfall == 1) { - brush_sample_tex(brush, xy, dstf); + brush_sample_tex(brush, xy, dstf, 0); } else { dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - brush_sample_tex(brush, xy, rgba); + brush_sample_tex(brush, xy, rgba, 0); dstf[0] = rgba[0]*brush->rgb[0]; dstf[1] = rgba[1]*brush->rgb[1]; @@ -583,7 +583,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius)); } else if (texfall == 1) { - brush_sample_tex(brush, xy, rgba); + brush_sample_tex(brush, xy, rgba, 0); dst[0]= FTOCHAR(rgba[0]); dst[1]= FTOCHAR(rgba[1]); dst[2]= FTOCHAR(rgba[2]); @@ -592,7 +592,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf else { dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - brush_sample_tex(brush, xy, rgba); + brush_sample_tex(brush, xy, rgba, 0); dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]); dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]); dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]); @@ -739,7 +739,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i xy[0] = x + xoff; xy[1] = y + yoff; - brush_sample_tex(brush, xy, tf); + brush_sample_tex(brush, xy, tf, 0); } bf[0] = tf[0]*mf[0]; @@ -770,7 +770,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i xy[0] = x + xoff; xy[1] = y + yoff; - brush_sample_tex(brush, xy, rgba); + brush_sample_tex(brush, xy, rgba, 0); t[0]= FTOCHAR(rgba[0]); t[1]= FTOCHAR(rgba[1]); t[2]= FTOCHAR(rgba[2]); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 57e5630da19..fe69f13bbda 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -850,7 +850,14 @@ static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta * the effect of this constraint (i.e. owner is 'parented' to parent) */ copy_m4_m4(tempmat, cob->matrix); - mul_m4_m4m4(cob->matrix, tempmat, parmat); + mul_m4_m4m4(cob->matrix, tempmat, parmat); + + /* without this, changes to scale and rotation can change location + * of a parentless bone or a disconnected bone. Even though its set + * to zero above. */ + if (!(data->flag & CHILDOF_LOCX)) cob->matrix[3][0]= tempmat[3][0]; + if (!(data->flag & CHILDOF_LOCY)) cob->matrix[3][1]= tempmat[3][1]; + if (!(data->flag & CHILDOF_LOCZ)) cob->matrix[3][2]= tempmat[3][2]; } } @@ -1629,8 +1636,9 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta mat4_to_size(size, cob->matrix); /* to allow compatible rotations, must get both rotations in the order of the owner... */ - mat4_to_eulO(eul, cob->rotOrder, ct->matrix); mat4_to_eulO(obeul, cob->rotOrder, cob->matrix); + /* we must get compatible eulers from the beginning because some of them can be modified below (see bug #21875) */ + mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix); if ((data->flag & ROTLIKE_X)==0) eul[0] = obeul[0]; @@ -1662,6 +1670,7 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta eul[2] *= -1; } + /* good to make eulers compatible again, since we don't know how much they were changed above */ compatible_eul(eul, obeul); loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder); } @@ -4349,8 +4358,7 @@ void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n, void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) { bConstraint *con; - float solution[4][4], delta[4][4]; - float oldmat[4][4], imat[4][4]; + float oldmat[4][4]; float enf; /* check that there is a valid constraint object to evaluate */ @@ -4402,7 +4410,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) } } - /* Solve the constraint */ + /* Solve the constraint and put result in cob->matrix */ cti->evaluate_constraint(con, cob, &targets); /* clear targets after use @@ -4414,23 +4422,13 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) } /* Interpolate the enforcement, to blend result of constraint into final owner transform */ - /* 1. Remove effects of original matrix from constraint solution ==> delta */ - invert_m4_m4(imat, oldmat); - copy_m4_m4(solution, cob->matrix); - mul_m4_m4m4(delta, solution, imat); - - /* 2. If constraint influence is not full strength, then interpolate - * identity_matrix --> delta_matrix to get the effect the constraint actually exerts - */ + /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate, or did I miss something? -jahka */ if (enf < 1.0) { - float identity[4][4]; - unit_m4(identity); - blend_m4_m4m4(delta, identity, delta, enf); + float solution[4][4]; + copy_m4_m4(solution, cob->matrix); + blend_m4_m4m4(cob->matrix, oldmat, solution, enf); } - /* 3. Now multiply the delta by the matrix in use before the evaluation */ - mul_m4_m4m4(cob->matrix, delta, oldmat); - /* move owner back into worldspace for next constraint/other business */ if ((con->flag & CONSTRAINT_SPACEONCE) == 0) constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 7928424e47c..a5d96baf049 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -64,6 +64,7 @@ struct bContext { struct ARegion *region; struct ARegion *menu; struct bContextStore *store; + const char *operator_poll_msg; /* reason for poll failing */ } wm; /* data context */ @@ -399,6 +400,16 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu) C->wm.menu= menu; } +void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg) +{ + C->wm.operator_poll_msg= msg; +} + +const char *CTX_wm_operator_poll_msg_get(bContext *C) +{ + return C->wm.operator_poll_msg; +} + /* data context utility functions */ struct bContextDataResult { diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 358dd1914e7..d13738808d1 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -74,12 +74,22 @@ void unlink_curve(Curve *cu) for(a=0; a<cu->totcol; a++) { if(cu->mat[a]) cu->mat[a]->id.us--; - cu->mat[a]= 0; + cu->mat[a]= NULL; } if(cu->vfont) cu->vfont->id.us--; - cu->vfont= 0; + cu->vfont= NULL; + + if(cu->vfontb) cu->vfontb->id.us--; + cu->vfontb= NULL; + + if(cu->vfonti) cu->vfonti->id.us--; + cu->vfonti= NULL; + + if(cu->vfontbi) cu->vfontbi->id.us--; + cu->vfontbi= NULL; + if(cu->key) cu->key->id.us--; - cu->key= 0; + cu->key= NULL; } /* frees editcurve entirely */ @@ -210,9 +220,12 @@ void make_local_curve(Curve *cu) */ if(cu->id.lib==0) return; - - if(cu->vfont) cu->vfont->id.lib= 0; - + + if(cu->vfont) cu->vfont->id.lib= NULL; + if(cu->vfontb) cu->vfontb->id.lib= NULL; + if(cu->vfonti) cu->vfonti->id.lib= NULL; + if(cu->vfontbi) cu->vfontbi->id.lib= NULL; + if(cu->id.us==1) { cu->id.lib= 0; cu->id.flag= LIB_LOCAL; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index a44c5ace298..d0336d9f786 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -930,7 +930,7 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal) EditFace *efa; DispList *dlnew=0, *dl; float *f1; - int colnr=0, charidx=0, cont=1, tot, a, *index; + int colnr=0, charidx=0, cont=1, tot, a, *index, nextcol= 0; intptr_t totvert; if(dispbase==0) return; @@ -938,38 +938,41 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal) while(cont) { cont= 0; - totvert=0; + totvert= 0; + nextcol= 0; dl= dispbase->first; while(dl) { if(dl->type==DL_POLY) { if(charidx<dl->charidx) cont= 1; - else if(charidx==dl->charidx) { - - colnr= dl->col; - charidx= dl->charidx; - - /* make editverts and edges */ - f1= dl->verts; - a= dl->nr; - eve= v1= 0; - - while(a--) { - vlast= eve; - - eve= BLI_addfillvert(f1); - totvert++; + else if(charidx==dl->charidx) { /* character with needed index */ + if(colnr==dl->col) { + /* make editverts and edges */ + f1= dl->verts; + a= dl->nr; + eve= v1= 0; - if(vlast==0) v1= eve; - else { - BLI_addfilledge(vlast, eve); + while(a--) { + vlast= eve; + + eve= BLI_addfillvert(f1); + totvert++; + + if(vlast==0) v1= eve; + else { + BLI_addfilledge(vlast, eve); + } + f1+=3; } - f1+=3; - } - - if(eve!=0 && v1!=0) { - BLI_addfilledge(eve, v1); + + if(eve!=0 && v1!=0) { + BLI_addfilledge(eve, v1); + } + } else if (colnr<dl->col) { + /* got poly with next material at current char */ + cont= 1; + nextcol= 1; } } } @@ -1032,7 +1035,14 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal) } BLI_end_edgefill(); - charidx++; + if(nextcol) { + /* stay at current char but fill polys with next material */ + colnr++; + } else { + /* switch to next char and start filling from first material */ + charidx++; + colnr= 0; + } } /* do not free polys, needed for wireframe display */ diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 05fcabd371f..4860e7d8eed 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -29,6 +29,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stddef.h> #include "BLI_storage.h" /* _LARGEFILE_SOURCE */ #include <math.h> @@ -85,7 +86,6 @@ #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_scene.h" -#include "BKE_screen.h" #include "BKE_utildefines.h" #include "RE_render_ext.h" diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index cdefbb54ecf..9dac409226b 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -29,12 +29,14 @@ * * ***** END GPL LICENSE BLOCK *****/ +#include <stddef.h> #include "BLI_storage.h" +#include <stdlib.h> #include <ctype.h> /* isdigit, isspace */ #include <math.h> #include <stdio.h> -#include <stdlib.h> + #include <fcntl.h> #include <string.h> #include <errno.h> @@ -449,1328 +451,10 @@ static void read_stl_mesh_ascii(Scene *scene, char *str) #undef STLREADLINE #undef STLREADVERT -/* ***************** INVENTOR ******************* */ - - -#define IV_MAXSTACK 3000000 -#define IV_MAXFIELD 10 -#define IV_MAXCOL 16 - -static float *iv_data_stack; -static float ivcolors[IV_MAXCOL][3]; -static Object *ivsurf; -static ListBase ivbase; - -struct IvNode { - struct IvNode *next, *prev; - char *nodename; - char *fieldname[IV_MAXFIELD]; - int datalen[IV_MAXFIELD]; - float *data[IV_MAXFIELD]; -}; - -static int iv_curcol=0; - -static int iv_colornumber(struct IvNode *iv) -{ - float *fp, fr = 0.0, fg = 0.0, fb = 0.0; - int a; - char *cp; - - /* search back to last material */ - while(iv) { - if( strcmp(iv->nodename, "Material")==0) { - fp= iv->data[0]; - if(fp==0) fp= iv->data[1]; - if(fp) { - fr= fp[0]; - fg= fp[1]; - fb= fp[2]; - } - break; - } - else if( strcmp(iv->nodename, "BaseColor")==0) { - fp= iv->data[0]; - fr= fp[0]; - fg= fp[1]; - fb= fp[2]; - break; - } - else if( strcmp(iv->nodename, "PackedColor")==0) { - cp= (char *)iv->data[0]; - fr= cp[3]/255.0f; - fg= cp[2]/255.0f; - fb= cp[1]/255.0f; - break; - } - iv= iv->prev; - - } - if(iv==0) return 0; - if(iv->datalen[0]<3) return 0; - - for(a=0; a<iv_curcol; a++) { - - if(ivcolors[a][0]== fr) - if(ivcolors[a][1]== fg) - if(ivcolors[a][2]== fb) return a+1 - ; - } - - if(a>=IV_MAXCOL) a= IV_MAXCOL-1; - iv_curcol= a+1; - ivcolors[a][0]= fr; - ivcolors[a][1]= fg; - ivcolors[a][2]= fb; - - return iv_curcol; -} - -static int iv_finddata(struct IvNode *iv, char *field, int fieldnr) -{ - /* search for "field", count data size and make datablock. return skipdata */ - float *fp; - int len, stackcount, skipdata=0; - char *cpa, terminator, str[64]; - intptr_t i; - - len= strlen(field); - - cpa= iv->nodename+1; - while( *cpa != '}' ) { - - if( *cpa == *field ) { - if( strncmp(cpa, field, len)==0 ) { - iv->fieldname[fieldnr]= cpa; - - /* read until first character */ - cpa+= len; - skipdata+= len; - *cpa= 0; - cpa++; - skipdata++; - - while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) cpa++; - if( *cpa=='[' ) { - terminator= ']'; - cpa++; - skipdata++; - } - else terminator= 13; - - stackcount= 0; - fp= iv_data_stack; - - while( *cpa!=terminator && *cpa != '}' ) { - - /* in fact, isdigit should include the dot and minus */ - if( (isdigit(*cpa) || *cpa=='.' || *cpa=='-') && (isspace(cpa[-1]) || cpa[-1]==0 || cpa[-1]==',') ) { - if(cpa[1]=='x') { - memcpy(str, cpa, 16); - str[16]= 0; - - sscanf(str, "%x", (int *)fp); - } - else { - /* atof doesn't stop after the first float - * in a long string at Windows... so we copy - * the float to a new string then atof... */ - char *cpa_temp = strpbrk(cpa, ", \n"); - i = cpa_temp - cpa; - - if (i>63) *fp= 0.0; - else { - memcpy(str, cpa, i); - str[i]=0; - - *fp= (float) atof(str); - } - } - - stackcount++; - if(stackcount>=IV_MAXSTACK) { - printf("stackoverflow in IV read\n"); - break; - } - fp++; - } - cpa++; - skipdata++; - } - - iv->datalen[fieldnr]= stackcount; - if(stackcount) { - iv->data[fieldnr]= MEM_mallocN(sizeof(float)*stackcount, "iv_finddata"); - memcpy(iv->data[fieldnr], iv_data_stack, sizeof(float)*stackcount); - } - else iv->data[fieldnr]= 0; - - return skipdata; - } - } - cpa++; - skipdata++; - } - - return skipdata; -} - -static void read_iv_index(float *data, float *baseadr, float *index, int nr, int coordtype) -{ - /* write in data: baseadr with offset index (and number nr) */ - float *fp; - int ofs; - - while(nr--) { - ofs= (int) *index; - fp= baseadr+coordtype*ofs; - VECCOPY(data, fp); - data+= 3; - index++; - } -} - - - -static void read_inventor(Scene *scene, char *str, struct ListBase *listb) -{ - struct IvNode *iv, *ivp, *ivn; - char *maindata, *md, *cpa; - float *index, *data, *fp; - int file, filelen, count, lll, face, nr = 0; - int skipdata, ok, a, b, tot, first, colnr, coordtype, polytype, *idata; - struct DispList *dl; - ReportList *reports= NULL; /* XXX */ - - ivbase.first= ivbase.last= 0; - iv_curcol= 0; - ivsurf= 0; - - file= open(str, O_BINARY|O_RDONLY); - if(file== -1) { - BKE_reportf(reports, RPT_ERROR, "Can't read file: %s.", strerror(errno)); - return; - } - - filelen= BLI_filesize(file); - if(filelen < 1) { - close(file); - return; - } - - maindata= MEM_mallocN(filelen, "leesInventor"); - if(read(file, maindata, filelen) < filelen) { - BKE_reportf(reports, RPT_ERROR, "Failed reading file: premature end of file."); - close(file); - return; - } - close(file); - - iv_data_stack= MEM_mallocN(sizeof(float)*IV_MAXSTACK, "ivstack"); - - /* preprocess: remove comments */ - md= maindata+20; - count= 20; - while(count<filelen) { - if( *md=='#' ) { /* comment */ - while( *md!=13 && *md!=10) { /* enters */ - *md= 32; - md++; - count++; - if(count>=filelen) break; - } - } - md++; - count++; - } - - - /* now time to collect: which are the nodes and fields? */ - md= maindata; - count= 0; - while(count<filelen) { - if( *md=='{' ) { /* read back */ - - cpa= md-1; - while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) { /* remove spaces/enters/tab */ - *cpa= 0; - cpa--; - } - - while( *cpa>32 && *cpa<128) cpa--; - cpa++; - *md= 0; - - ok= 0; - skipdata= 0; - iv= MEM_callocN(sizeof(struct IvNode), "leesInventor"); - iv->nodename= cpa; - - if(strcmp(cpa, "Coordinate3")==0 || strcmp(cpa, "Coordinate4")==0) { - skipdata= iv_finddata(iv, "point", 0); - ok= 1; - } - else if(strcmp(cpa, "VertexProperty")==0) { - skipdata= iv_finddata(iv, "vertex", 0); - ok= 1; - } - else if(strcmp(cpa, "IndexedLineSet")==0) { - skipdata= iv_finddata(iv, "coordIndex", 0); - ok= 1; - } - else if(strcmp(cpa, "IndexedTriangleMesh")==0) { - skipdata= iv_finddata(iv, "coordIndex", 0); - ok= 1; - } - else if(strcmp(cpa, "IndexedFaceSet")==0) { - skipdata= iv_finddata(iv, "coordIndex", 0); - ok= 1; - } - else if(strcmp(cpa, "FaceSet")==0) { - skipdata= iv_finddata(iv, "numVertices", 0); - ok= 1; - } - else if(strcmp(cpa, "Material")==0) { - iv_finddata(iv, "diffuseColor", 0); - iv_finddata(iv, "ambientColor", 1); - ok= 1; - } - else if(strcmp(cpa, "BaseColor")==0) { - iv_finddata(iv, "rgb", 0); - ok= 1; - } - else if(strcmp(cpa, "PackedColor")==0) { - iv_finddata(iv, "rgba", 0); - ok= 1; - } - else if(strcmp(cpa, "QuadMesh")==0) { - iv_finddata(iv, "verticesPerColumn", 0); - iv_finddata(iv, "verticesPerRow", 1); - - ok= 1; - } - else if(strcmp(cpa, "IndexedTriangleStripSet")==0) { - skipdata= iv_finddata(iv, "coordIndex", 0); - ok= 1; - } - else if(strcmp(cpa, "TriangleStripSet")==0) { - skipdata= iv_finddata(iv, "numVertices", 0); - ok= 1; - } - else if(strcmp(cpa, "IndexedNurbsSurface")==0 || strcmp(cpa, "NurbsSurface")==0) { - iv_finddata(iv, "numUControlPoints", 0); - iv_finddata(iv, "numVControlPoints", 1); - iv_finddata(iv, "uKnotVector", 2); - iv_finddata(iv, "vKnotVector", 3); - ok= 1; - } - else { - /* to the end */ - while( *md != '}') { - md++; - count++; - if(count<filelen) break; - } - } - - - if(ok) { - BLI_addtail(&ivbase, iv); - md+= skipdata; - count+= skipdata; - } - else MEM_freeN(iv); - - } - md++; - count++; - } - - /* join nodes */ - iv= ivbase.first; - - while(iv) { - ivn= iv->next; - - if( strncmp(iv->nodename, "Indexed", 7)==0) { - /* seek back: same name? */ - - ivp= iv->prev; - while(ivp) { - if(strcmp(iv->nodename, ivp->nodename)==0) break; - - if(strcmp(ivp->nodename, "Coordinate3")==0 || - strcmp(ivp->nodename, "Coordinate4")==0 || - strcmp(ivp->nodename, "VertexProperty")==0) { - ivp= 0; - break; - } - ivp= ivp->prev; - } - - if(ivp) { - /* add iv to ivp */ - - tot= iv->datalen[0] + ivp->datalen[0]; - if(tot) { - data= MEM_mallocN(tot*sizeof(float), "samenvoeg iv"); - memcpy(data, ivp->data[0], sizeof(float)*ivp->datalen[0]); - memcpy(data+ivp->datalen[0], iv->data[0], sizeof(float)*iv->datalen[0]); - - ivp->datalen[0]+= iv->datalen[0]; - MEM_freeN(ivp->data[0]); - ivp->data[0]= data; - - BLI_remlink(&ivbase, iv); - MEM_freeN(iv->data[0]); - MEM_freeN(iv); - } - } - } - - iv= ivn; - } - - - /* convert Nodes to DispLists */ - iv= ivbase.first; - while(iv) { - - /* printf(" Node: %s\n", iv->nodename); */ - /* if(iv->fieldname[0]) printf(" Field: %s len %d\n", iv->fieldname[0], iv->datalen[0]); */ - coordtype= 3; - - if( strcmp(iv->nodename, "IndexedLineSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - if(ivp) { - - /* count the nr of lines */ - tot= 0; - index= iv->data[0]; - lll = iv->datalen[0]-1; - for(a=0; a<lll; a++) { - if(index[0]!= -1 && index[1]!= -1) tot++; - index++; - } - - tot*= 2; /* nr of vertices */ - dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor1"); - BLI_addtail(listb, dl); - dl->type= DL_SEGM; - dl->nr= 2; - dl->parts= tot/2; - dl->col= colnr; - data= (float *)(dl+1); - - index= iv->data[0]; - for(a=0; a<lll; a++) { - if(index[0]!= -1 && index[1]!= -1) { - read_iv_index(data, ivp->data[0], index, 2, coordtype); - data+= 6; - } - index++; - } - } - } - else if( strcmp(iv->nodename, "FaceSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - - if(ivp) { - /* count triangles */ - tot= 0; - - index= iv->data[0]; - polytype= (int) index[0]; - - for(a=0; a<iv->datalen[0]; a++) { - if(index[0]== polytype) tot++; /* one kind? */ - index++; - } - - - tot*= polytype; /* nr of vertices */ - dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor4"); - BLI_addtail(listb, dl); - dl->type= DL_POLY; - dl->nr= polytype; - dl->parts= tot/polytype; - dl->col= colnr; - data= (float *)(dl+1); - - index= ivp->data[0]; - first= 1; - for(a=0; a<iv->datalen[0]; a++) { - - VECCOPY(data, index); - data+= 3; - index+= 3; - - VECCOPY(data, index); - data+= 3; - index+= 3; - - VECCOPY(data, index); - data+= 3; - index+= 3; - - if(polytype==4) { - VECCOPY(data, index); - data+= 3; - index+= 3; - } - } - } - } - else if( strcmp(iv->nodename, "TriangleStripSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - - if(ivp) { - /* count triangles */ - tot= 0; - face= 0; - - index= iv->data[0]; /* strip size */ - - for(a=0; a<iv->datalen[0]; a++) { - tot+= (int) index[0]; - face+= ((int) index[0]) - 2; - index++; - } - - dl= MEM_callocN(sizeof(struct DispList), "leesInventor4"); - dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts"); - dl->index= MEM_callocN( face*3*sizeof(int), "dl index"); - - dl->type= DL_INDEX3; - dl->nr= tot; - dl->parts= face; - - BLI_addtail(listb, dl); - dl->col= colnr; - - index= iv->data[0]; /* strip size */ - fp= ivp->data[0]; /* vertices */ - data= dl->verts; - idata= dl->index; - first= 0; - - for(a=0; a<iv->datalen[0]; a++) { - - /* vertices */ - for(b=0; b<index[0]; b++) { - VECCOPY(data, fp); - data+= 3; - fp+= coordtype; - } - - /* indices */ - lll = index[0] - 2; - for(b=0; b<lll; b++) { - idata[0]= first; - idata[1]= first+1; - idata[2]= first+2; - first++; - idata+= 3; - } - first+= 2; - - index++; - } - } - } - else if( strcmp(iv->nodename, "IndexedFaceSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - if(ivp) { - - /* count triangles */ - face= 0; - index= iv->data[0]; - lll = iv->datalen[0]-2; - for(a=0; a<lll; a++) { - if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++; - index++; - } - - /*number of vertices */ - tot= ivp->datalen[0]/coordtype; - - if(tot) { - dl= MEM_callocN(sizeof(struct DispList), "leesInventor5"); - BLI_addtail(listb, dl); - dl->type= DL_INDEX3; - dl->nr= tot; - dl->parts= face; - dl->col= colnr; - - dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts"); - dl->index= MEM_callocN(sizeof(int)*3*face, "dl index"); - - /* vertices */ - fp= ivp->data[0]; - data= dl->verts; - for(b=tot; b>0; b--) { - VECCOPY(data, fp); - data+= 3; - fp+= coordtype; - } - - /* indices */ - index= iv->data[0]; - idata= dl->index; - first= 1; - lll=iv->datalen[0]-2; - for(a=0; a<lll; a++) { - - if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) { - - /* this trick is to fill poly's with more than 3 vertices correctly */ - if(first) { - nr= (int) index[0]; - first= 0; - } - idata[0]= nr; - idata[1]= (int) index[1]; - idata[2]= (int) index[2]; - idata+= 3; - } - else first= 1; - - index++; - } - } - } - } - else if( strcmp(iv->nodename, "IndexedTriangleMesh")==0 || - strcmp(iv->nodename, "IndexedTriangleStripSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - if(ivp) { - - /* count triangles */ - face= 0; - index= iv->data[0]; - lll=iv->datalen[0]-2; - for(a=0; a<lll; a++) { - if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++; - index++; - } - - /* nr of vertices */ - tot= ivp->datalen[0]/coordtype; - - dl= MEM_callocN(sizeof(struct DispList), "leesInventor6"); - BLI_addtail(listb, dl); - dl->type= DL_INDEX3; - dl->nr= tot; - dl->parts= face; - dl->col= colnr; - - dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts"); - dl->index= MEM_callocN(sizeof(int)*3*face, "dl index"); - - /* vertices */ - fp= ivp->data[0]; - data= dl->verts; - for(b=tot; b>0; b--) { - VECCOPY(data, fp); - data+= 3; - fp+= coordtype; - } - - /* indices */ - index= iv->data[0]; - idata= dl->index; - - lll=iv->datalen[0]-2; - for(a=lll; a>0; a--) { - - if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) { - idata[0]= (int) index[0]; - idata[1]= (int) index[1]; - idata[2]= (int) index[2]; - idata+= 3; - } - index++; - } - } - } - else if( strcmp(iv->nodename, "QuadMesh")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "VertexProperty")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - - if(ivp) { - tot= (int) (floor(*(iv->data[0])+0.5) * floor(*(iv->data[1])+0.5)); - - if(tot>0) { - dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor8"); - BLI_addtail(listb, dl); - dl->type= DL_SURF; - dl->parts= (int) floor(*(iv->data[0])+0.5); - dl->nr= (int) floor(*(iv->data[1])+0.5); - dl->col= colnr; - data= (float *)(dl+1); - memcpy(data, ivp->data[0], tot*3*sizeof(float)); - } - } - } - else if(strcmp(iv->nodename, "IndexedNurbsSurface")==0 || strcmp(iv->nodename, "NurbsSurface")==0) { - - colnr= iv_colornumber(iv); - - /* sek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - if(ivp) { - a= (int) *(iv->data[0]); - b= (int) *(iv->data[1]); - - tot= a*b; - - if( (a>=4 || b>=4) && tot>6) { - Object *ob; - Curve *cu; - Nurb *nu; - BPoint *bp; - - if(ivsurf==0) { - ob= add_object(scene, OB_SURF); - ivsurf= ob; - } - else ob= ivsurf; - cu= ob->data; - nu = (Nurb*) MEM_callocN(sizeof(Nurb),"addNurbprim") ; - BLI_addtail(&cu->nurb, nu); - nu->type= CU_NURBS; - - nu->pntsu= a; - nu->pntsv= b; - nu->resolu= 2*a; - nu->resolv= 2*b; - - nu->flagu= 0; - nu->flagv= 0; - - nu->bp = bp = - (BPoint*)MEM_callocN(tot * sizeof(BPoint), "addNurbprim3"); - a= tot; - data= ivp->data[0]; - while(a--) { - VECCOPY(bp->vec, data); - if(coordtype==4) { - bp->vec[3]= data[3]; - mul_v3_fl(bp->vec, 1.0f/data[3]); - } - else bp->vec[3]= 1.0; - data+= coordtype; - bp++; - } - - /* iv->datalen[2] / [3] is number of knots */ - nu->orderu= iv->datalen[2] - nu->pntsu; - nu->orderv= iv->datalen[3] - nu->pntsv; - - nu->knotsu= MEM_mallocN( sizeof(float)*(iv->datalen[2]), "knots"); - memcpy(nu->knotsu, iv->data[2], sizeof(float)*(iv->datalen[2])); - nu->knotsv= MEM_mallocN( sizeof(float)*(iv->datalen[3]), "knots"); - memcpy(nu->knotsv, iv->data[3], sizeof(float)*(iv->datalen[3])); - - switchdirectionNurb(nu); - - } - else { - dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor3"); - BLI_addtail(listb, dl); - dl->type= DL_SURF; - dl->nr= (int) *(iv->data[0]); - dl->parts= (int) *(iv->data[1]); - dl->col= colnr; - data= (float *)(dl+1); - - a= tot; - fp= ivp->data[0]; - while(a--) { - VECCOPY(data, fp); - fp+= coordtype; - data+= 3; - } - } - } - } - iv= iv->next; - } - - /* free */ - iv= ivbase.first; - while(iv) { - for(a=0; a<IV_MAXFIELD; a++) { - if(iv->data[a]) MEM_freeN(iv->data[a]); - } - iv= iv->next; - } - - BLI_freelistN(&ivbase); - MEM_freeN(maindata); - MEM_freeN(iv_data_stack); - -} - /* ************************************************************ */ -static void displist_to_mesh(Scene *scene, DispList *dlfirst) -{ - Object *ob; - Mesh *me; - Material *ma; - DispList *dl; - MVert *mvert; - MFace *mface; - float *data, vec[3], min[3], max[3]; - int a, b, startve, *idata, totedge=0, tottria=0, totquad=0, totvert=0, totface, totcol=0, colnr; - int p1, p2, p3, p4; - unsigned int maxvertidx; - - /* count first */ - INIT_MINMAX(min, max); - - dl= dlfirst; - while(dl) { - - /* PATCH 1 (polyfill) can't be done, there's no listbase here. do that first! */ - /* PATCH 2 */ - if(dl->type==DL_SEGM && dl->nr>2) { - data= (float *)(dl+1); - if(data[0]==data[3*(dl->nr-1)]) { - if(data[1]==data[3*(dl->nr-1)+1]) { - if(data[2]==data[3*(dl->nr-1)+2]) { - dl->type= DL_POLY; - dl->nr--; - } - } - } - } - - /* colors */ - if(dl->col > totcol) totcol= dl->col; - - /* size and count */ - if(dl->type==DL_SURF) { - a= dl->nr; - b= dl->parts; - if(dl->flag & DL_CYCL_U) a++; - if(dl->flag & DL_CYCL_V) b++; - - totquad+= a*b; - - totvert+= dl->nr*dl->parts; - - data= (float *)(dl+1); - for(a= dl->nr*dl->parts; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - } - else if(dl->type==DL_POLY) { - if(dl->nr==3 || dl->nr==4) { - if(dl->nr==3) tottria+= dl->parts; - else totquad+= dl->parts; - - totvert+= dl->nr*dl->parts; - - data= (float *)(dl+1); - for(a= dl->nr*dl->parts; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - } - else if(dl->nr>4) { - - tottria+= dl->nr*dl->parts; - totvert+= dl->nr*dl->parts; - - data= (float *)(dl+1); - for(a= dl->nr*dl->parts; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - - } - } - else if(dl->type==DL_INDEX3) { - tottria+= dl->parts; - totvert+= dl->nr; - - data= dl->verts; - for(a= dl->nr; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - } - else if(dl->type==DL_SEGM) { - - tottria+= (dl->nr-1)*dl->parts; - totvert+= dl->nr*dl->parts; - - data= (float *)(dl+1); - for(a= dl->nr*dl->parts; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - } - - dl= dl->next; - } - - if(totvert==0) { - return; - } - - vec[0]= (min[0]+max[0])/2; - vec[1]= (min[1]+max[1])/2; - vec[2]= (min[2]+max[2])/2; - - ob= add_object(scene, OB_MESH); - VECCOPY(ob->loc, vec); - where_is_object(scene, ob); - - me= ob->data; - - /* colors */ - if(totcol) { - ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat"); - ob->matbits= MEM_callocN(sizeof(char)*totcol, "ob->matbits"); - me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat"); - me->totcol= totcol; - ob->totcol= (unsigned char) me->totcol; - ob->actcol= 1; - } - - /* materials */ - for(a=0; a<totcol; a++) { - ma= G.main->mat.first; - while(ma) { - if(ma->mtex[0]==0) { - if(ivcolors[a][0]==ma->r && ivcolors[a][1]==ma->g && ivcolors[a][2]==ma->b) { - me->mat[a]= ma; - ma->id.us++; - break; - } - } - ma= ma->id.next; - } - if(ma==0) { - ma= add_material("ext"); - me->mat[a]= ma; - ma->r= ivcolors[a][0]; - ma->g= ivcolors[a][1]; - ma->b= ivcolors[a][2]; - automatname(ma); - } - } - - totface= totquad+tottria+totedge; - - printf("Import: %d vertices %d faces\n", totvert, totface); - - me->totvert= totvert; - me->totface= totface; - me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, - NULL, me->totvert); - me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, - NULL, me->totface); - maxvertidx= totvert-1; - - mvert= me->mvert; - mface= me->mface; - - startve= 0; - - dl= dlfirst; - while(dl) { - - colnr= dl->col; - if(colnr) colnr--; - - if(dl->type==DL_SURF) { - data= (float *)(dl+1); - - for(a=dl->parts*dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - - data+=3; - mvert++; - } - - for(a=0; a<dl->parts; a++) { - - if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0) - break; - - p1+= startve; - p2+= startve; - p3+= startve; - p4+= startve; - - for(; b<dl->nr; b++) { - - mface->v1= p1; - mface->v2= p2; - mface->v3= p4; - mface->v4= p3; - - mface->mat_nr= colnr; - test_index_face(mface, NULL, 0, 4); - - mface++; - - p4= p3; - p3++; - p2= p1; - p1++; - } - } - - startve += dl->parts*dl->nr; - - } - else if(dl->type==DL_POLY) { - - if(dl->nr==3 || dl->nr==4) { - data= (float *)(dl+1); - - for(a=dl->parts*dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - data+=3; - mvert++; - } - - for(a=0; a<dl->parts; a++) { - if(dl->nr==3) { - mface->v1= startve+a*dl->nr; - mface->v2= startve+a*dl->nr+1; - mface->v3= startve+a*dl->nr+2; - mface->mat_nr= colnr; - test_index_face(mface, NULL, 0, 3); - mface++; - } - else { - mface->v1= startve+a*dl->nr; - mface->v2= startve+a*dl->nr+1; - mface->v3= startve+a*dl->nr+2; - mface->v4= startve+a*dl->nr+3; - mface->mat_nr= colnr; - test_index_face(mface, NULL, 0, 4); - mface++; - } - } - startve += dl->parts*dl->nr; - } - else if(dl->nr>4) { - data= (float *)(dl+1); - - for(a=dl->parts*dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - - data+=3; - mvert++; - } - - for(b=0; b<dl->parts; b++) { - for(a=0; a<dl->nr; a++) { - mface->v1= startve+a; - - if(a==dl->nr-1) mface->v2= startve; - else mface->v2= startve+a+1; - - mface->mat_nr= colnr; - - mface++; - } - startve += dl->nr; - } - } - } - else if(dl->type==DL_INDEX3) { - data= dl->verts; - - for(a=dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - data+=3; - mvert++; - } - - idata= dl->index; - for(b=dl->parts; b>0; b--) { - mface->v1= startve+idata[0]; - mface->v2= startve+idata[1]; - mface->v3= startve+idata[2]; - mface->mat_nr= colnr; - - if (mface->v1>maxvertidx) mface->v1= maxvertidx; - if (mface->v2>maxvertidx) mface->v2= maxvertidx; - if (mface->v3>maxvertidx) mface->v3= maxvertidx; - - test_index_face(mface, NULL, 0, 3); - mface++; - idata+= 3; - } - startve += dl->nr; - } - else if(dl->type==DL_SEGM) { - data= (float *)(dl+1); - - for(a=dl->parts*dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - data+=3; - mvert++; - } - - for(b=0; b<dl->parts; b++) { - for(a=0; a<dl->nr-1; a++) { - mface->v1= startve+a; - mface->v2= startve+a+1; - mface->mat_nr= colnr; - mface++; - } - startve += dl->nr; - } - } - dl= dl->next; - } - - mesh_add_normals_flags(me); - make_edges(me, 0); -} - -static void displist_to_objects(Scene *scene, ListBase *lbase) -{ - DispList *dl, *first, *prev, *next; - ListBase tempbase; - int maxaantal, curcol, totvert=0, vert; - - /* irst this: is still active */ - if(ivsurf) { - where_is_object(scene, ivsurf); -// XXX docenter_new(); - } - - dl= lbase->first; - while(dl) { - next= dl->next; - - /* PATCH 1: polyfill */ - if(dl->type==DL_POLY && dl->nr>4) { - /* solution: put them together in separate listbase */ - ; - } - /* PATCH 2: poly's of 2 points */ - if(dl->type==DL_POLY && dl->nr==2) dl->type= DL_SEGM; - - dl= next; - } - - /* count vertices */ - - dl= lbase->first; - while(dl) { - - if(dl->type==DL_SURF) totvert+= dl->nr*dl->parts; - else if(dl->type==DL_POLY) { - if(dl->nr==3 || dl->nr==4) totvert+= dl->nr*dl->parts; - else if(dl->nr>4) totvert+= dl->nr*dl->parts; - } - else if(dl->type==DL_INDEX3) totvert+= dl->nr; - else if(dl->type==DL_SEGM) totvert+= dl->nr*dl->parts; - - dl= dl->next; - } - - if(totvert==0) { - - if(ivsurf==0) {}; //XXX error("Found no data"); - if(lbase->first) BLI_freelistN(lbase); - - return; - } - - maxaantal= 32000; - - if(totvert>maxaantal) { - - /* try to put colors together */ - curcol= 0; - tempbase.first= tempbase.last= 0; - - while(lbase->first) { - dl= lbase->first; - while(dl) { - next= dl->next; - if(dl->col==curcol) { - BLI_remlink(lbase, dl); - BLI_addtail(&tempbase, dl); - dl->col= 0; - } - - dl= next; - } - - /* in tempbase are all 'curcol' */ - totvert= 0; - dl= first= tempbase.first; - while(dl) { - vert= 0; - - if(dl->type==DL_SURF) vert= dl->nr*dl->parts; - else if(dl->type==DL_POLY) { - if(dl->nr==3 || dl->nr==4) vert= dl->nr*dl->parts; - else if(dl->nr>4) vert= dl->nr*dl->parts; - } - else if(dl->type==DL_INDEX3) totvert+= dl->nr; - else if(dl->type==DL_SEGM) vert= dl->nr*dl->parts; - - totvert+= vert; - if(totvert > maxaantal || dl->next==0) { - if(dl->next==0) { - displist_to_mesh(scene, first); - } - else if(dl->prev) { - prev= dl->prev; - prev->next= 0; - displist_to_mesh(scene, first); - prev->next= dl; - first= dl; - totvert= 0; - } - } - - dl= dl->next; - } - - freedisplist(&tempbase); - - curcol++; - } - } - else displist_to_mesh(scene, lbase->first); - - freedisplist(lbase); - -} - int BKE_read_exotic(Scene *scene, char *name) { - ListBase lbase={0, 0}; int len; gzFile gzfile; char str[32]; @@ -1793,21 +477,7 @@ int BKE_read_exotic(Scene *scene, char *name) if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) { //XXX waitcursor(1); - if(strncmp(str, "#Inventor V1.0", 14)==0) { - if( strncmp(str+15, "ascii", 5)==0) { - read_inventor(scene, name, &lbase); - displist_to_objects(scene, &lbase); - retval = 1; - } else { - //XXX error("Can only read Inventor 1.0 ascii"); - } - } - else if((strncmp(str, "#VRML V1.0 asc", 14)==0)) { - read_inventor(scene, name, &lbase); - displist_to_objects(scene, &lbase); - retval = 1; - } - else if(is_dxf(name)) { + if(is_dxf(name)) { dxf_read(scene, name); retval = 1; } @@ -1907,15 +577,8 @@ void write_stl(Scene *scene, char *str) FILE *fpSTL; int numfacets = 0; ReportList *reports= NULL; /* XXX */ - - if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0; - if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0; - if(BLI_testextensie(str,".stl")==0) strcat(str, ".stl"); - if (BLI_exists(str)) { - ; //XXX if(saveover(str)==0) - //XXX return; - } + /* XXX, operator needs to manage filename extension */ fpSTL= fopen(str, "wb"); @@ -1965,7 +628,6 @@ void write_stl(Scene *scene, char *str) //XXX waitcursor(0); } -/* ******************************* WRITE VRML ***************************** */ static void replace_chars(char *str1, char *str2) { @@ -1978,354 +640,6 @@ static void replace_chars(char *str1, char *str2) } } - -static void write_material_vrml(FILE *fp, Material *ma) -{ - char str[32]; - - replace_chars(str, ma->id.name+2); - - fprintf(fp, "\tDEF %s\n", str); - fprintf(fp, "\tMaterial {\n"); - - fprintf(fp, "\t\tdiffuseColor %f %f %f\n", ma->r, ma->g, ma->b); - fprintf(fp, "\t\tspecularColor %f %f %f\n", ma->specr, ma->specg, ma->specb); - fprintf(fp, "\t\tshininess %f \n", ((float)ma->har)/100.0); - fprintf(fp, "\t\ttransparency %f \n", 1.0-ma->alpha); - - fprintf(fp, "\t}\n"); - -} - -unsigned int *mcol_to_vcol(Mesh *me) -{ - MFace *mface; - unsigned int *mcol, *mcoln, *mcolmain; - int a; - - if(me->totface==0 || me->mcol==0) return 0; - - mcoln= mcolmain= MEM_mallocN(sizeof(int)*me->totvert, "mcoln"); - mcol = (unsigned int *)me->mcol; - mface= me->mface; - - for(a=me->totface; a>0; a--, mface++) { - mcoln[mface->v1]= mcol[0]; - mcoln[mface->v2]= mcol[1]; - mcoln[mface->v3]= mcol[2]; - if(mface->v4) mcoln[mface->v4]= mcol[3]; - - mcol+= 4; - } - - return mcolmain; -} - -void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a) -{ - char *cp; - - cp = (char *)&col; - - *r= cp[3]; - *r /= 255.0; - - *g= cp[2]; - *g /= 255.0; - - *b= cp[1]; - *b /= 255.0; - - *a= cp[0]; - *a /= 255.0; -} - -static void write_mesh_vrml(FILE *fp, Mesh *me) -{ - Material *ma; - MVert *mvert; - MFace *mface; - MTFace *tface; - Image *ima; - int a, b, totcol, texind; - char str[32]; - - replace_chars(str, me->id.name+2); - - fprintf(fp, "\tDEF %s\n", str); - fprintf(fp, "\tSeparator {\n"); - - if(me->mtface) { - ima= ((MTFace *)me->mtface)->tpage; - if(ima) { - fprintf(fp, "\t\tTexture2 {\n"); - fprintf(fp, "\t\t\tfilename %s\n", ima->name); - fprintf(fp, "\t\t\twrapS REPEAT \n"); - fprintf(fp, "\t\t\twrapT REPEAT \n"); - fprintf(fp, "\t\t}\n"); - } - } - - if(me->mcol) { - unsigned int *mcol, *mcolmain; - float r, g, b, cola; - - fprintf(fp, "\t\tMaterial {\n"); - fprintf(fp, "\t\t\tdiffuseColor [\n"); - - a= me->totvert; - mcol= mcolmain= mcol_to_vcol(me); - if(mcol) { - while(a--) { - mcol_to_rgba(*mcol, &r, &g, &b, &cola); - fprintf(fp, "\t\t\t\t %f %f %f,\n", r, g, b); - mcol++; - } - MEM_freeN(mcolmain); - } - fprintf(fp, "\t\t\t]\n"); - fprintf(fp, "\t\t}\n"); - - fprintf(fp, "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n"); - } - - - fprintf(fp, "\t\tCoordinate3 {\n"); - fprintf(fp, "\t\t\tpoint [\n"); - - a= me->totvert; - mvert= me->mvert; - while(a--) { - fprintf(fp, "\t\t\t\t %f %f %f,\n", mvert->co[0], mvert->co[1], mvert->co[2]); - mvert++; - } - fprintf(fp, "\t\t\t]\n"); - fprintf(fp, "\t\t}\n"); - - - totcol= me->totcol; - if(totcol==0) totcol= 1; - texind= 0; // index for uv coords - - for(b=0; b<totcol; b++) { - - if(me->mcol==0) { - if(me->mat) { - ma= me->mat[b]; - if(ma) { - replace_chars(str, ma->id.name+2); - - fprintf(fp, "\t\tUSE %s\n\n", str); - } - } - } - - if(me->mtface) { - fprintf(fp, "\t\tTextureCoordinate2 {\n"); - fprintf(fp, "\t\t\tpoint [\n"); - - a= me->totface; - mface= me->mface; - tface= me->mtface; - while(a--) { - if(mface->mat_nr==b) { - fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[0][0], tface->uv[0][1]); - fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[1][0], tface->uv[1][1]); - fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[2][0], tface->uv[2][1]); - if(mface->v4) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[3][0], tface->uv[3][1]); - } - mface++; - tface++; - } - fprintf(fp, "\t\t\t]\n"); - fprintf(fp, "\t\t}\n"); - } - - fprintf(fp, "\t\tIndexedFaceSet {\n"); - fprintf(fp, "\t\t\tcoordIndex [\n"); - - a= me->totface; - mface= me->mface; - while(a--) { - if(mface->mat_nr==b) { - if(mface->v4) fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3, mface->v4); - else fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3); - } - mface++; - } - fprintf(fp, "\t\t\t]\n"); - - if(me->mtface) { - fprintf(fp, "\t\t\ttextureCoordIndex [\n"); - - a= me->totface; - mface= me->mface; - while(a--) { - if(mface->mat_nr==b) { - if(mface->v4) { - fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", texind, texind+1, texind+2, texind+3); - texind+= 4; - } - else { - fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", texind, texind+1, texind+2); - texind+= 3; - } - } - mface++; - } - fprintf(fp, "\t\t\t]\n"); - } - fprintf(fp, "\t\t}\n"); - } - - fprintf(fp, "\t}\n"); -} - -static void write_camera_vrml(FILE *fp, Object *ob) -{ - Camera *cam; - - if(ob==0) return; - invert_m4_m4(ob->imat, ob->obmat); - - fprintf(fp, "\tMatrixTransform {\n"); - - fprintf(fp, "\tmatrix \n"); - - fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[0][0], ob->imat[0][1], ob->imat[0][2], ob->imat[0][3]); - fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[1][0], ob->imat[1][1], ob->imat[1][2], ob->imat[1][3]); - fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[2][0], ob->imat[2][1], ob->imat[2][2], ob->imat[2][3]); - fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[3][0], ob->imat[3][1], ob->imat[3][2], ob->imat[3][3]); - - fprintf(fp, "\t}\n"); - - cam= ob->data; - - fprintf(fp, "\tPerspectiveCamera {\n"); - fprintf(fp, "\t\tfocalDistance %f\n", cam->lens/10.0); - - fprintf(fp, "\t}\n"); - -} - -static void write_object_vrml(FILE *fp, Object *ob) -{ - ID *id; - char str[32]; - - fprintf(fp, "\tSeparator {\n"); - fprintf(fp, "\t\tMatrixTransform {\n"); - - fprintf(fp, "\t\tmatrix \n"); - - fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[0][0], ob->obmat[0][1], ob->obmat[0][2], ob->obmat[0][3]); - fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[1][0], ob->obmat[1][1], ob->obmat[1][2], ob->obmat[1][3]); - fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[2][0], ob->obmat[2][1], ob->obmat[2][2], ob->obmat[2][3]); - fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2], ob->obmat[3][3]); - - fprintf(fp, "\t\t}\n"); - - id= ob->data; - - replace_chars(str, id->name+2); - - fprintf(fp, "\t\tUSE %s\n", str); - fprintf(fp, "\t}\n"); -} - - -void write_vrml(Scene *scene, char *str) -{ - Mesh *me; - Material *ma; - Base *base; - FILE *fp; - - if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0; - if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0; - if(BLI_testextensie(str,".wrl")==0) strcat(str, ".wrl"); - //XXX saveover() if(saveover(str)==0) return; - - fp= fopen(str, "w"); - - if(fp==NULL) { - //XXX error("Can't write file"); - return; - } - strcpy(temp_dir, str); - - //XXX waitcursor(1); - - /* FIRST: write all the datablocks */ - - fprintf(fp, "#VRML V1.0 ascii\n\n# Blender V%d\n\n# 'Switch' is used as a hack, to ensure it is not part of the drawing\n\n", BLENDER_VERSION); - fprintf(fp, "Separator {\n"); - fprintf(fp, "Switch {\n"); - - ma= G.main->mat.first; - while(ma) { - if(ma->id.us) { - write_material_vrml(fp, ma); - } - ma= ma->id.next; - } - - /* only write meshes we're using in this scene */ - flag_listbase_ids(&G.main->mesh, LIB_DOIT, 0); - - for(base= scene->base.first; base; base= base->next) - if(base->object->type== OB_MESH) - ((ID *)base->object->data)->flag |= LIB_DOIT; - - me= G.main->mesh.first; - while(me) { - if(me->id.flag & LIB_DOIT) { /* is the mesh used in this scene ? */ - write_mesh_vrml(fp, me); - } - me= me->id.next; - } - - /* THEN:Hidden Objects */ - fprintf(fp, "\n\t# Hidden Objects, in invisible layers\n\n"); - base= scene->base.first; - while(base) { - if(base->object->type== OB_MESH) { - if( (base->lay & scene->lay)==0 ) { - write_object_vrml(fp, base->object); - } - } - base= base->next; - } - - fprintf(fp, "}\n"); - fprintf(fp, "\n# Visible Objects\n\n"); - fprintf(fp, "Separator {\n"); - - /* The camera */ - - write_camera_vrml(fp, scene->camera); - - /* THEN:The Objects */ - - base= scene->base.first; - while(base) { - if(base->object->type== OB_MESH) { - if(base->lay & scene->lay) { - write_object_vrml(fp, base->object); - } - } - base= base->next; - } - - fprintf(fp, "}\n"); - fprintf(fp, "}\n"); - - fclose(fp); - - //XXX waitcursor(0); -} - - /* ******************************* WRITE DXF ***************************** */ #define write_group(id,data) fprintf(fp, "%d\n%s\n", id, data) @@ -2551,15 +865,7 @@ void write_dxf(struct Scene *scene, char *str) Base *base; FILE *fp; - if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0; - if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0; - if(BLI_testextensie(str,".dxf")==0) strcat(str, ".dxf"); - - - if (BLI_exists(str)) { - ; //XXX if(saveover(str)==0) - // return; - } + /* XXX, operator needs to handle overwrite & rename */ fp= fopen(str, "w"); diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 04ce6c39694..ef89d39864a 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -28,6 +28,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stddef.h> #include "BLI_storage.h" /* _LARGEFILE_SOURCE */ #include "MEM_guardedalloc.h" diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index c0a60ea6294..47627d09b97 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -1146,7 +1146,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) return NULL; } - if(mode==0) { + if(mode == FO_EDIT) { /* make nurbdata */ unsigned long cha; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index e77183d785f..cb2261932ce 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -382,7 +382,7 @@ Image *BKE_add_image_file(const char *name, int frame) return ima; } -static ImBuf *add_ibuf_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) +static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) { ImBuf *ibuf; unsigned char *rect= NULL; @@ -415,7 +415,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int depth, int fl } /* adds new image block, creates ImBuf and initializes color */ -Image *BKE_add_image_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) +Image *BKE_add_image_size(unsigned int width, unsigned int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) { /* on save, type is changed to FILE in editsima.c */ Image *ima= image_alloc(name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); @@ -757,9 +757,9 @@ int BKE_imtype_is_movie(int imtype) return 0; } -void BKE_add_image_extension(char *string, int imtype) +int BKE_add_image_extension(char *string, int imtype) { - char *extension=""; + char *extension= NULL; if(imtype== R_IRIS) { if(!BLI_testextensie(string, ".rgb")) @@ -830,7 +830,12 @@ void BKE_add_image_extension(char *string, int imtype) extension= ".jpg"; } - strcat(string, extension); + if(extension) { + return BLI_replace_extension(string, FILE_MAX, extension); + } + else { + return FALSE; + } } /* could allow access externally - 512 is for long names, 64 is for id names */ @@ -1772,8 +1777,6 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) else BLI_path_abs(str, G.sce); - BLI_path_frame(str, cfra, 0); - /* read ibuf */ ibuf = IMB_loadiffname(str, flag); } @@ -2017,14 +2020,9 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); } else if(ima->source == IMA_SRC_VIEWER) { - if(ima->type==IMA_TYPE_R_RESULT) { - /* always verify entirely, not that this shouldn't happen - * during render anyway */ - } - else if(ima->type==IMA_TYPE_COMPOSITE) { - frame= iuser?iuser->framenr:0; - ibuf= image_get_ibuf(ima, 0, frame); - } + /* always verify entirely, not that this shouldn't happen + * as part of texture sampling in rendering anyway, so not + * a big bottleneck */ } *frame_r = frame; @@ -2141,10 +2139,15 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) BLI_lock_thread(LOCK_VIEWER); *lock_r= ima; - /* Composite Viewer, all handled in compositor */ - /* fake ibuf, will be filled in compositor */ - ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); - image_assign_ibuf(ima, ibuf, 0, frame); + frame= iuser?iuser->framenr:0; + ibuf= image_get_ibuf(ima, 0, frame); + + if(!ibuf) { + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); + image_assign_ibuf(ima, ibuf, 0, frame); + } } } } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 2f8553b06b3..6f1cdefbcad 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -440,7 +440,7 @@ void transform_mesh_orco_verts(Mesh *me, float (*orco)[3], int totvert, int inve int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) { /* first test if the face is legal */ - if(mface->v3 && mface->v3==mface->v4) { + if((mface->v3 || nr==4) && mface->v3==mface->v4) { mface->v4= 0; nr--; } @@ -854,6 +854,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int mface->v2= startvert+index[2]; mface->v3= startvert+index[1]; mface->v4= 0; + mface->mat_nr= (unsigned char)dl->col; test_index_face(mface, NULL, 0, 3); if(smooth) mface->flag |= ME_SMOOTH; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 4a9f7116755..c5a12d1fb4e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -509,12 +509,10 @@ void unlink_object(Scene *scene, Object *ob) } /* textures */ - tex= bmain->tex.first; - while(tex) { - if(tex->env) { - if(tex->env->object == ob) tex->env->object= NULL; - } - tex= tex->id.next; + for(tex= bmain->tex.first; tex; tex= tex->id.next) { + if(tex->env && (ob==tex->env->object)) tex->env->object= NULL; + if(tex->pd && (ob==tex->pd->object)) tex->pd->object= NULL; + if(tex->vd && (ob==tex->vd->object)) tex->vd->object= NULL; } /* worlds */ @@ -1315,6 +1313,8 @@ Object *copy_object(Object *ob) obn->gpulamp.first = obn->gpulamp.last = NULL; obn->pc_ids.first = obn->pc_ids.last = NULL; + + obn->mpath= NULL; return obn; } @@ -1665,11 +1665,29 @@ void object_mat3_to_rot(Object *ob, float mat[][3], int use_compat) /* see pchan_apply_mat4() for the equivalent 'pchan' function */ void object_apply_mat4(Object *ob, float mat[][4]) { - float mat3[3][3]; + float mat3[3][3], tmat[3][3], imat[3][3]; + + /* location */ copy_v3_v3(ob->loc, mat[3]); - mat4_to_size(ob->size, mat); + + /* rotation */ copy_m3_m4(mat3, mat); object_mat3_to_rot(ob, mat3, 0); + + /* scale */ +#if 0 + /* works fine except for neg scales */ + mat4_to_size(ob->size, mat); +#else + /* this is more complicated but works for negative scales */ + object_rot_to_mat3(ob, tmat); + invert_m3_m3(imat, tmat); + mul_m3_m3m3(tmat, imat, mat3); + + ob->size[0]= tmat[0][0]; + ob->size[1]= tmat[1][1]; + ob->size[2]= tmat[2][2]; +#endif } void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 07b712c4330..723ff7faed3 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -272,7 +272,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) } psmd= psys_get_modifier(ob, psys); - if(psys->renderdata) { + if(psys->renderdata || G.rendering) { if(!(psmd->modifier.mode & eModifierMode_Render)) return 0; } @@ -3686,7 +3686,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float else VECCOPY(texco,orco); - externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3); + externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3, 0); if((event & mtex->pmapto) & MAP_PA_TIME){ if((setvars&MAP_PA_TIME)==0){ ptex->time=0.0; @@ -3740,7 +3740,7 @@ void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *p psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } - externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3); + externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3, 0); if((event & mtex->pmapto) & MAP_PA_TIME){ /* the first time has to set the base value for time regardless of blend mode */ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 0d14c3cb9f6..47a220dcefb 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -29,6 +29,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stddef.h> #include "BLI_storage.h" /* _LARGEFILE_SOURCE */ #include <stdlib.h> @@ -194,9 +195,11 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) psys->free_edit = NULL; } - newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); - if(psys->part->phystype == PART_PHYS_BOIDS) - newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles"); + if(totpart) { + newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); + if(psys->part->phystype == PART_PHYS_BOIDS) + newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles"); + } if(psys->particles) { totsaved=MIN2(psys->totpart,totpart); @@ -2836,11 +2839,18 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B } while(t2); } -/* particle - mesh collision code */ -/* in addition to basic point to surface collisions handles friction & damping,*/ -/* angular momentum <-> linear momentum and swept sphere - mesh collisions */ -/* 1. check for all possible deflectors for closest intersection on particle path */ -/* 2. if deflection was found kill the particle or calculate new coordinates */ +/* Particle - Mesh collision code + * Features: + * - point and swept sphere to mesh surface collisions + * - moving colliders (but not yet rotating or deforming colliders) + * - friction & damping + * - angular momentum <-> linear momentum + * - high accuracy by re-applying particle acceleration after collision + * - behaves relatively well even if limit of 10 collisions per simulation step is exceeded + * Main parts: + * 1. check for all possible deflectors for closest intersection on particle path + * 2. if deflection was found calculate new coordinates or kill the particle + */ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, float cfra){ Object *ground_ob = NULL; ParticleSettings *part = sim->psys->part; @@ -2848,19 +2858,21 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo ParticleCollision col; ColliderCache *coll; BVHTreeRayHit hit; - float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; + float ray_dir[3], acc[3]; float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f), boid_z = 0.0f; - float timestep = psys_get_timestep(sim); + float timestep = psys_get_timestep(sim) * dfra; + float inv_timestep = 1.0f/timestep; int deflections=0, max_deflections=10; - VECCOPY(col.co1, pa->prev_state.co); - VECCOPY(col.co2, pa->state.co); - - VECCOPY(col.ve1, pa->prev_state.vel); - VECCOPY(col.ve2, pa->state.vel); - mul_v3_fl(col.ve1, timestep * dfra); - mul_v3_fl(col.ve2, timestep * dfra); - + /* get acceleration (from gravity, forcefields etc. to be re-applied after collision) */ + sub_v3_v3v3(acc, pa->state.vel, pa->prev_state.vel); + mul_v3_fl(acc, inv_timestep); + + /* set values for first iteration */ + copy_v3_v3(col.co1, pa->prev_state.co); + copy_v3_v3(col.co2, pa->state.co); + copy_v3_v3(col.ve1, pa->prev_state.vel); + copy_v3_v3(col.ve2, pa->state.vel); col.t = 0.0f; /* override for boids */ @@ -2875,7 +2887,7 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo if(sim->colliders) while(deflections < max_deflections){ /* 1. */ - VECSUB(ray_dir, col.co2, col.co1); + sub_v3_v3v3(ray_dir, col.co2, col.co1); hit.index = -1; hit.dist = col.ray_len = len_v3(ray_dir); @@ -2903,45 +2915,49 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo /* 2. */ if(hit.index>=0) { PartDeflect *pd = col.hit_ob->pd; - int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; float co[3]; /* point of collision */ - float vec[3]; /* movement through collision */ - float acc[3]; /* acceleration */ - float x = hit.dist/col.ray_len; /* location of collision between this iteration */ - float le = len_v3(col.ve1)/col.ray_len; - float ac = len_v3(col.ve2)/col.ray_len - le; /* (taking acceleration into account) */ - float t = (-le + sqrt(le*le + 2*ac*x))/ac; /* time of collision between this iteration */ - float dt = col.t + x * (1.0f - col.t); /* time of collision between frame change*/ - float it = 1.0 - t; + float df = col.t + x * (1.0f - col.t); /* time of collision between frame change*/ + float dt1 = (df - col.t) * timestep; /* iteration time of collision (in seconds) */ + float dt2 = (1.0f - df) * timestep; /* time left after collision (in seconds) */ + int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */ + + deflections++; interp_v3_v3v3(co, col.co1, col.co2, x); - VECSUB(vec, col.co2, col.co1); - - VECSUB(acc, col.ve2, col.ve1); - mul_v3_fl(col.vel, 1.0f-col.t); + /* make sure we don't hit the current face again */ + /* TODO: could/should this be proportional to pa->size? */ + madd_v3_v3fl(co, col.nor, (through ? -0.0001f : 0.0001f)); /* particle dies in collision */ if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) { pa->alive = PARS_DYING; - pa->dietime = pa->state.time + (cfra - pa->state.time) * dt; - - /* we have to add this for dying particles too so that reactors work correctly */ - VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); + pa->dietime = pa->state.time + (cfra - pa->state.time) * df; - VECCOPY(pa->state.co, co); - interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, dt); - interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, dt); - interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, dt); + copy_v3_v3(pa->state.co, co); + interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, df); + interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, df); + interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, df); /* particle is dead so we don't need to calculate further */ - deflections=max_deflections; + return; } + /* figure out velocity and other data after collision */ else { - float nor_vec[3], tan_vec[3], tan_vel[3]; + float v0[3]; /* velocity directly before collision to be modified into velocity directly after collision */ + float v0_nor[3];/* normal component of v0 */ + float v0_tan[3];/* tangential component of v0 */ + float vc_tan[3];/* tangential component of collision surface velocity */ + float check[3]; + float v0_dot, vc_dot, check_dot; float damp, frict; - float inp, inp_v; + + /* get exact velocity right before collision */ + madd_v3_v3v3fl(v0, col.ve1, acc, dt1); + + /* convert collider velocity from 1/framestep to 1/s */ + mul_v3_fl(col.vel, inv_timestep); /* get damping & friction factors */ damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f); @@ -2951,119 +2967,118 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo CLAMP(frict,0.0,1.0); /* treat normal & tangent components separately */ - inp = dot_v3v3(col.nor, vec); - inp_v = dot_v3v3(col.nor, col.vel); - - VECADDFAC(tan_vec, vec, col.nor, -inp); - VECADDFAC(tan_vel, col.vel, col.nor, -inp_v); - if((part->flag & PART_ROT_DYN)==0) - interp_v3_v3v3(tan_vec, tan_vec, tan_vel, frict); - - VECCOPY(nor_vec, col.nor); - inp *= 1.0f - damp; - - if(through) - inp_v *= damp; - - /* special case for object hitting the particle from behind */ - if(through==0 && ((inp_v>0 && inp>0 && inp_v>inp) || (inp_v<0 && inp<0 && inp_v<inp))) - mul_v3_fl(nor_vec, inp_v); - else - mul_v3_fl(nor_vec, inp_v + (through ? 1.0f : -1.0f) * inp); + v0_dot = dot_v3v3(col.nor, v0); + madd_v3_v3v3fl(v0_tan, v0, col.nor, -v0_dot); - /* angular <-> linear velocity - slightly more physical and looks even nicer than before */ - if(part->flag & PART_ROT_DYN) { - float surface_vel[3], rot_vel[3], friction[3], dave[3], dvel[3]; + vc_dot = dot_v3v3(col.nor, col.vel); + madd_v3_v3v3fl(vc_tan, col.vel, col.nor, -vc_dot); - /* apparent velocity along collision surface */ - VECSUB(surface_vel, tan_vec, tan_vel); + /* handle friction effects (tangential and angular velocity) */ + if(frict > 0.0f) { + /* angular <-> linear velocity */ + if(part->flag & PART_ROT_DYN) { + float vr_tan[3], v1_tan[3], ave[3]; + + /* linear velocity of particle surface */ + cross_v3_v3v3(vr_tan, col.nor, pa->state.ave); + mul_v3_fl(vr_tan, pa->size); - /* direction of rolling friction */ - cross_v3_v3v3(rot_vel, pa->state.ave, col.nor); - /* convert to current dt */ - mul_v3_fl(rot_vel, (timestep*dfra) * (1.0f - col.t)); - mul_v3_fl(rot_vel, pa->size); + /* change to coordinates that move with the collision plane */ + sub_v3_v3v3(v1_tan, v0_tan, vc_tan); + + /* The resulting velocity is a weighted average of particle cm & surface + * velocity. This weight (related to particle's moment of inertia) could + * be made a parameter for angular <-> linear conversion. + */ + madd_v3_v3fl(v1_tan, vr_tan, -0.4); + mul_v3_fl(v1_tan, 1.0f/1.4f); /* 1/(1+0.4) */ - /* apply sliding friction */ - VECSUB(surface_vel, surface_vel, rot_vel); - VECCOPY(friction, surface_vel); + /* rolling friction is around 0.01 of sliding friction (could be made a parameter) */ + mul_v3_fl(v1_tan, 1.0f - 0.01f * frict); - mul_v3_fl(surface_vel, 1.0 - frict); - mul_v3_fl(friction, frict); + /* surface_velocity is opposite to cm velocity */ + mul_v3_v3fl(vr_tan, v1_tan, -1.0f); - /* sliding changes angular velocity */ - cross_v3_v3v3(dave, col.nor, friction); - mul_v3_fl(dave, 1.0f/MAX2(pa->size, 0.001)); + /* get back to global coordinates */ + add_v3_v3(v1_tan, vc_tan); - /* we assume rolling friction is around 0.01 of sliding friction */ - mul_v3_fl(rot_vel, 1.0 - frict*0.01); + /* convert to angular velocity*/ + cross_v3_v3v3(ave, vr_tan, col.nor); + mul_v3_fl(ave, 1.0f/MAX2(pa->size, 0.001)); - /* change in angular velocity has to be added to the linear velocity too */ - cross_v3_v3v3(dvel, dave, col.nor); - mul_v3_fl(dvel, pa->size); - VECADD(rot_vel, rot_vel, dvel); + /* only friction will cause change in linear & angular velocity */ + interp_v3_v3v3(pa->state.ave, pa->state.ave, ave, frict); + interp_v3_v3v3(v0_tan, v0_tan, v1_tan, frict); + } + else { + /* just basic friction (unphysical due to the friction model used in Blender) */ + interp_v3_v3v3(v0_tan, v0_tan, vc_tan, frict); + } + } - VECADD(surface_vel, surface_vel, rot_vel); - VECADD(tan_vec, surface_vel, tan_vel); + /* stickness was possibly added before, so cancel that before calculating new normal velocity */ + /* otherwise particles go flying out of the surface because of high reversed sticky velocity */ + if(v0_dot < 0.0f) { + v0_dot += pd->pdef_stickness; + if(v0_dot > 0.0f) + v0_dot = 0.0f; + } - /* convert back to normal time */ - mul_v3_fl(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); + /* damping and flipping of velocity around normal */ + v0_dot *= 1.0f - damp; + vc_dot *= through ? damp : 1.0f; - mul_v3_fl(pa->state.ave, 1.0 - frict*0.01); - VECADD(pa->state.ave, pa->state.ave, dave); - } + /* special case for object hitting the particle from behind */ + if(through==0 && ((vc_dot>0.0f && v0_dot>0.0f && vc_dot>v0_dot) || (vc_dot<0.0f && v0_dot<0.0f && vc_dot<v0_dot))) + mul_v3_v3fl(v0_nor, col.nor, vc_dot); + else + mul_v3_v3fl(v0_nor, col.nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot); /* combine components together again */ - VECADD(vec, nor_vec, tan_vec); - - /* make sure we don't hit the current face again */ - VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); + add_v3_v3v3(v0, v0_nor, v0_tan); + /* keep boids above ground */ if(part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) { BoidParticle *bpa = pa->boid; if(bpa->data.mode == eBoidMode_OnLand || co[2] <= boid_z) { co[2] = boid_z; - vec[2] = 0.0f; + v0[2] = 0.0f; } } - - /* set coordinates for next iteration */ - /* apply acceleration to final position, but make sure particle stays above surface */ - madd_v3_v3v3fl(acc, vec, acc, it); - ac = dot_v3v3(acc, col.nor); - if((!through && ac < 0.0f) || (through && ac > 0.0f)) - madd_v3_v3fl(acc, col.nor, -ac); - - VECCOPY(col.co1, co); - VECADDFAC(col.co2, co, acc, it); - - VECCOPY(col.ve1, vec); - VECCOPY(col.ve2, acc); - - if(len_v3(vec) < 0.001 && len_v3v3(pa->state.co, pa->prev_state.co) < 0.001) { - /* kill speed to stop slipping */ - VECCOPY(pa->state.vel,zerovec); - VECCOPY(pa->state.co, co); - if(part->flag & PART_ROT_DYN) { - VECCOPY(pa->state.ave,zerovec); - } - } - else { - VECCOPY(pa->state.co, col.co2); - mul_v3_v3fl(pa->state.vel, acc, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - + if(deflections < max_deflections) { + /* re-apply acceleration to final velocity and location */ + madd_v3_v3v3fl(pa->state.vel, v0, acc, dt2); + madd_v3_v3v3fl(pa->state.co, co, v0, dt2); + madd_v3_v3fl(pa->state.co, acc, 0.5f*dt2*dt2); + + /* make sure particle stays on the right side of the surface */ + sub_v3_v3v3(check, pa->state.co, co); + /* (collision surface has moved during the time too) */ + madd_v3_v3fl(check, col.vel, -dt2); + + check_dot = dot_v3v3(check, col.nor); + if((!through && check_dot < 0.0f) || (through && check_dot > 0.0f)) + madd_v3_v3fl(pa->state.co, col.nor, (through ? -0.0001f : 0.0001f) - check_dot); + /* Stickness to surface */ - normalize_v3(nor_vec); madd_v3_v3fl(pa->state.vel, col.nor, -pd->pdef_stickness); - } - col.t = dt; - } - deflections++; + /* set coordinates for next iteration */ + copy_v3_v3(col.co1, co); + copy_v3_v3(col.co2, pa->state.co); - //reaction_state.time = cfra - (1.0f - dt) * dfra; - //push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); + copy_v3_v3(col.ve1, v0); + copy_v3_v3(col.ve2, pa->state.vel); + + col.t = df; + } + else { + /* final chance to prevent failure, so don't do anything fancy */ + copy_v3_v3(pa->state.co, co); + copy_v3_v3(pa->state.vel, v0); + } + } } else return; @@ -3345,6 +3360,8 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) /* frame & time changes */ float dfra, dtime, pa_dtime, pa_dfra=0.0; float birthtime, dietime; + + int invalidParticles=0; /* where have we gone in time since last time */ dfra= cfra - psys->cfra; @@ -3440,7 +3457,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) else if(part->phystype == PART_PHYS_NO) reset_particle(sim, pa, dtime, cfra); - if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ + if(pa_dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ switch(part->phystype){ case PART_PHYS_NEWTON: /* do global forces & effectors */ @@ -3495,6 +3512,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) //push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); } + if (isnan(pa->state.co[0]) || isnan(pa->state.co[1]) || isnan(pa->state.co[2])) {invalidParticles++;} } free_collider_cache(&sim->colliders); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 741580048cf..784f6e40706 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1008,11 +1008,22 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - if(psys->part) { - pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_particles(pid, ob, psys); - BLI_addtail(lb, pid); - } + if(psys->part==NULL) + continue; + + /* check to make sure point cache is actually used by the particles */ + if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) + continue; + + if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) + continue; + + if(psys->part->type == PART_FLUID) + continue; + + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_particles(pid, ob, psys); + BLI_addtail(lb, pid); } for(md=ob->modifiers.first; md; md=md->next) { @@ -1876,6 +1887,9 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) else cache->flag |= PTCACHE_FRAMES_SKIPPED; } + + if(cache->cached_frames) + cache->cached_frames[cfra] = 1; if(pf) ptcache_file_close(pf); @@ -1893,6 +1907,9 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) { int len; /* store the length of the string */ + int i; + int sta = pid->cache->startframe; + int end = pid->cache->endframe; /* mode is same as fopen's modes */ DIR *dir; @@ -1936,6 +1953,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) pid->cache->last_exact = MIN2(pid->cache->startframe, 0); BLI_join_dirfile(path_full, path, de->d_name); BLI_delete(path_full, 0, 0); + if(pid->cache->cached_frames) for(i=0; i<end-sta+1; i++) + pid->cache->cached_frames[i] = 0; } else { /* read the number of the file */ int frame, len2 = (int)strlen(de->d_name); @@ -1950,6 +1969,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) BLI_join_dirfile(path_full, path, de->d_name); BLI_delete(path_full, 0, 0); + if(frame >=sta && frame <= end) + pid->cache->cached_frames[frame-sta] = 0; } } } @@ -1970,11 +1991,16 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) for(; pm; pm=pm->next) ptcache_free_data(pm); BLI_freelistN(&pid->cache->mem_cache); + + if(pid->cache->cached_frames) for(i=0; i<end-sta+1; i++) + pid->cache->cached_frames[i] = 0; } else { while(pm) { if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { link = pm; + if(pm->frame >=sta && pm->frame <= end) + pid->cache->cached_frames[pm->frame-sta] = 0; ptcache_free_data(pm); pm = pm->next; BLI_freelinkN(&pid->cache->mem_cache, link); @@ -2004,6 +2030,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) } } } + if(pid->cache->cached_frames && cfra>=sta && cfra<=end) + pid->cache->cached_frames[cfra-sta] = 0; break; } @@ -2014,6 +2042,12 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { if(!pid->cache) return 0; + + if(cfra<pid->cache->startframe || cfra > pid->cache->endframe) + return 0; + + if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0) + return 0; if(pid->cache->flag & PTCACHE_DISK_CACHE) { char filename[MAX_PTCACHE_FILE]; @@ -2073,6 +2107,71 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra *endframe += (int)(offset+0.5f); } } + + /* verify cached_frames array is up to date */ + if(cache->cached_frames) { + if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { + MEM_freeN(cache->cached_frames); + cache->cached_frames = NULL; + } + } + + if(cache->cached_frames==NULL && cache->endframe > cache->startframe) { + int sta=cache->startframe; + int end=cache->endframe; + + cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); + + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[MAX_PTCACHE_PATH]; + char filename[MAX_PTCACHE_FILE]; + char ext[MAX_PTCACHE_PATH]; + int len; /* store the length of the string */ + + ptcache_path(pid, path); + + len = BKE_ptcache_id_filename(pid, filename, (int)cfra, 0, 0); /* no path */ + + dir = opendir(path); + if (dir==NULL) + return; + + snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + /* read the number of the file */ + int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + if(frame >= sta && frame <= end) + cache->cached_frames[frame-sta] = 1; + } + } + } + } + closedir(dir); + } + else { + PTCacheMem *pm= pid->cache->mem_cache.first; + + pm= pid->cache->mem_cache.first; + + while(pm) { + if(pm->frame >= sta && pm->frame <= end) + cache->cached_frames[pm->frame-sta] = 1; + pm = pm->next; + } + } + } } int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) @@ -2293,6 +2392,8 @@ void BKE_ptcache_free(PointCache *cache) BKE_ptcache_free_mem(&cache->mem_cache); if(cache->edit && cache->free_edit) cache->free_edit(cache->edit); + if(cache->cached_frames) + MEM_freeN(cache->cached_frames); MEM_freeN(cache); } void BKE_ptcache_free_list(ListBase *ptcaches) @@ -2840,7 +2941,10 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - if(totframes && cache->totpoint) + /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ + if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) + sprintf(cache->info, "%i frames found!", totframes); + else if(totframes && cache->totpoint) sprintf(cache->info, "%i points found!", cache->totpoint); else sprintf(cache->info, "No valid data to read!"); diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 461cb075bb0..4a00922f1d2 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2873,7 +2873,7 @@ static void init_speed_effect(Sequence *seq) v = (SpeedControlVars *)seq->effectdata; v->globalSpeed = 1.0; v->frameMap = 0; - v->flags = 0; + v->flags |= SEQ_SPEED_INTEGRATE; /* should be default behavior */ v->length = 0; } @@ -2936,9 +2936,8 @@ static void store_icu_yrange_speed(struct Sequence * seq, } void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) { - float ctime, div; int cfra; - float fallback_fac; + float fallback_fac = 1.0f; SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; FCurve *fcu= NULL; @@ -2955,7 +2954,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) /* XXX - new in 2.5x. should we use the animation system this way? * The fcurve is needed because many frames need evaluating at once - campbell */ - fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_fader", 0); + fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0); if (!v->frameMap || v->length != seq->len) { @@ -2966,17 +2965,12 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) v->frameMap = MEM_callocN(sizeof(float) * v->length, "speedcontrol frameMap"); } - - fallback_fac = 1.0; - /* if there is no fcurve, try to make retiming easy by stretching the - strip */ - if (!fcu && seq->seq1->enddisp != seq->seq1->start && seq->seq1->len != 0) { - fallback_fac = (float) seq->seq1->len / - (float) (seq->seq1->enddisp - seq->seq1->start); - } + /* if there is no fcurve, use value as simple multiplier */ + if (!fcu) + fallback_fac = seq->speed_fader; /* same as speed_factor in rna*/ - if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) { + if (v->flags & SEQ_SPEED_INTEGRATE) { float cursor = 0; float facf; @@ -2985,10 +2979,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) for (cfra = 1; cfra < v->length; cfra++) { if(fcu) { - ctime = seq->startdisp + cfra; - div = 1.0; - - facf = evaluate_fcurve(fcu, ctime/div); + facf = evaluate_fcurve(fcu, seq->startdisp + cfra); } else { facf = fallback_fac; } @@ -3010,19 +3001,16 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) for (cfra = 0; cfra < v->length; cfra++) { if(fcu) { - ctime = seq->startdisp + cfra; - div = 1.0; - - facf = evaluate_fcurve(fcu, ctime / div); - if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) { - facf *= v->length; - } + facf = evaluate_fcurve(fcu, seq->startdisp + cfra); + } else { + facf = fallback_fac; } - - if (!fcu) { - facf = (float) cfra * fallback_fac; + + if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) { + facf *= v->length; } facf *= v->globalSpeed; + if (facf >= seq->seq1->len) { facf = seq->seq1->len - 1; } else { diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 8edb01c09a6..ceb693c4ecc 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -337,7 +337,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S } //After sucessufuly build the trees, start projection vertexs - if( bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6) + if( bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 4, 6) && (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6))) { @@ -383,6 +383,9 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData); + + if(hit.index != -1) + madd_v3_v3v3fl(hit.co, hit.co, tmp_no, -calc->keepDist); } //Project over negative direction of axis @@ -395,6 +398,9 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData); + + if(hit.index != -1) + madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist); } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index d2d8d5a6e07..d0fcde0da58 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1338,10 +1338,17 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM cache_wt = sds->point_cache[1]; BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd); - if(!smd->domain->fluid) + if(!smd->domain->fluid || framenr == startframe) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_validate(cache, framenr); + cache->flag &= ~PTCACHE_REDO_NEEDED; + BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED); + if(cache_wt) { + BKE_ptcache_validate(cache_wt, framenr); + cache_wt->flag &= ~PTCACHE_REDO_NEEDED; + } } if(framenr < startframe) @@ -1368,6 +1375,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM if(cache_result == PTCACHE_READ_EXACT) { BKE_ptcache_validate(cache, framenr); + smd->time = framenr; if(sds->wt) { @@ -1388,14 +1396,21 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM else return; } - - /* only calculate something when we advanced a frame */ - if(framenr == smd->time) + /* only calculate something when we advanced a single frame */ + else if(framenr != (int)smd->time+1) return; tstart(); smoke_calc_domain(scene, ob, smd); + + /* if on second frame, write cache for first frame */ + /* this needs to be done for smoke too so that pointcache works properly */ + if((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) { + BKE_ptcache_write_cache(&pid, startframe); + if(sds->wt) + BKE_ptcache_write_cache(&pid_wt, startframe); + } // set new time smd->time = scene->r.cfra; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index a4f1d5d0578..90a8ca03079 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1557,7 +1557,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); } - if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) { + if(!doDraw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) && !setDrawOptions(userData, origIndex))) { a += gridFaces*gridFaces*numVerts; continue; } diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 133f858e9ea..3d984c7e877 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -24,6 +24,8 @@ #include <stdio.h> #include <ctype.h> #include <string.h> +#include "BKE_unit.h" + #ifdef WIN32 #define _USE_MATH_DEFINES #endif @@ -31,20 +33,51 @@ #include "BLI_winstuff.h" + #define TEMP_STR_SIZE 256 #define SEP_CHR '#' #define SEP_STR "#" -#define EPS 0.000001 - +#define EPS 0.00001 + +#define UN_SC_KM 1000.0f +#define UN_SC_HM 100.0f +#define UN_SC_DAM 10.0f +#define UN_SC_M 1.0f +#define UN_SC_DM 0.1f +#define UN_SC_CM 0.01f +#define UN_SC_MM 0.001f +#define UN_SC_UM 0.000001f + +#define UN_SC_MI 1609.344f +#define UN_SC_FUR 201.168f +#define UN_SC_CH 20.1168f +#define UN_SC_YD 0.9144f +#define UN_SC_FT 0.3048f +#define UN_SC_IN 0.0254f +#define UN_SC_MIL 0.0000254f + +#define UN_SC_MTON 1000.0f /* metric ton */ +#define UN_SC_QL 100.0f +#define UN_SC_KG 1.0f +#define UN_SC_HG 0.1f +#define UN_SC_DAG 0.01f +#define UN_SC_G 0.001f + +#define UN_SC_ITON 907.18474f /* imperial ton */ +#define UN_SC_CWT 45.359237f +#define UN_SC_ST 6.35029318f +#define UN_SC_LB 0.45359237f +#define UN_SC_OZ 0.028349523125f /* define a single unit */ typedef struct bUnitDef { char *name; char *name_plural; /* abused a bit for the display name */ char *name_short; /* this is used for display*/ - char *name_alt; /* can be NULL */ + char *name_alt; /* keyboard-friendly ASCII-only version of name_short, can be NULL */ + /* if name_short has non-ASCII chars, name_alt should be present */ char *name_display; /* can be NULL */ @@ -59,7 +92,7 @@ typedef struct bUnitDef { /* define a single unit */ typedef struct bUnitCollection { struct bUnitDef *units; - int base_unit; /* use for 0.0, or none given */ + int base_unit; /* basic unit index (when user desn't specify unit explicitly) */ int flag; /* options for this system */ int length; /* to quickly find the last item */ } bUnitCollection; @@ -74,14 +107,14 @@ static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0, sizeof(buDum /* Lengths */ static struct bUnitDef buMetricLenDef[] = { - {"kilometer", "kilometers", "km", NULL, "Kilometers", 1000.0, 0.0, B_UNIT_DEF_NONE}, - {"hectometer", "hectometers", "hm", NULL, "100 Meters", 100.0, 0.0, B_UNIT_DEF_SUPPRESS}, - {"dekameter", "dekameters", "dkm",NULL, "10 Meters", 10.0, 0.0, B_UNIT_DEF_SUPPRESS}, - {"meter", "meters", "m", NULL, "Meters", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */ - {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", 0.1, 0.0, B_UNIT_DEF_SUPPRESS}, - {"centimeter", "centimeters", "cm", NULL, "Centimeters", 0.01, 0.0, B_UNIT_DEF_NONE}, - {"millimeter", "millimeters", "mm", NULL, "Millimeters", 0.001, 0.0, B_UNIT_DEF_NONE}, - {"micrometer", "micrometers", "µm", "um", "Micrometers", 0.000001, 0.0, B_UNIT_DEF_NONE}, // micron too? + {"kilometer", "kilometers", "km", NULL, "Kilometers", UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, + {"hectometer", "hectometers", "hm", NULL, "100 Meters", UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"dekameter", "dekameters", "dam",NULL, "10 Meters", UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"meter", "meters", "m", NULL, "Meters", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"centimeter", "centimeters", "cm", NULL, "Centimeters", UN_SC_CM, 0.0, B_UNIT_DEF_NONE}, + {"millimeter", "millimeters", "mm", NULL, "Millimeters", UN_SC_MM, 0.0, B_UNIT_DEF_NONE}, + {"micrometer", "micrometers", "µm", "um", "Micrometers", UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, // micron too? /* These get displayed because of float precision problems in the transform header, * could work around, but for now probably people wont use these */ @@ -94,17 +127,121 @@ static struct bUnitDef buMetricLenDef[] = { static struct bUnitCollection buMetricLenCollecton = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef)/sizeof(bUnitDef)}; static struct bUnitDef buImperialLenDef[] = { - {"mile", "miles", "mi", "m", "Miles", 1609.344, 0.0, B_UNIT_DEF_NONE}, - {"furlong", "furlongs", "fur", NULL, "Furlongs",201.168, 0.0, B_UNIT_DEF_SUPPRESS}, - {"chain", "chains", "ch", NULL, "Chains", 0.9144*22.0, 0.0, B_UNIT_DEF_SUPPRESS}, - {"yard", "yards", "yd", NULL, "Yards", 0.9144, 0.0, B_UNIT_DEF_NONE}, - {"foot", "feet", "'", "ft", "Feet", 0.3048, 0.0, B_UNIT_DEF_NONE}, - {"inch", "inches", "\"", "in", "Inches", 0.0254, 0.0, B_UNIT_DEF_NONE}, /* base unit */ - {"thou", "thous", "mil", NULL, "Thous", 0.0000254, 0.0, B_UNIT_DEF_NONE}, + {"mile", "miles", "mi", "m", "Miles", UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, + {"furlong", "furlongs", "fur", NULL, "Furlongs",UN_SC_FUR, 0.0, B_UNIT_DEF_SUPPRESS}, + {"chain", "chains", "ch", NULL, "Chains", UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS}, + {"yard", "yards", "yd", NULL, "Yards", UN_SC_YD, 0.0, B_UNIT_DEF_NONE}, + {"foot", "feet", "'", "ft", "Feet", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"inch", "inches", "\"", "in", "Inches", UN_SC_IN, 0.0, B_UNIT_DEF_NONE}, + {"thou", "thous", "mil", NULL, "Thous", UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef)/sizeof(bUnitDef)}; +/* Areas */ +static struct bUnitDef buMetricAreaDef[] = { + {"square kilometer", "square kilometers", "km²", "km2", "Square Kilometers", UN_SC_KM*UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, + {"square hectometer","square hectometers", "hm²", "hm2", "Square Hectometers", UN_SC_HM*UN_SC_HM, 0.0, B_UNIT_DEF_NONE}, /* hectare */ + {"square dekameter", "square dekameters", "dam²","dam2", "Square Dekameters", UN_SC_DAM*UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, /* are */ + {"square meter", "square meters", "m²", "m2", "Square Meters", UN_SC_M*UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"square decimetre", "square decimetres", "dm²", "dm2", "Square Decimetres", UN_SC_DM*UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"square centimeter", "square centimeters", "cm²", "cm2", "Square Centimeters", UN_SC_CM*UN_SC_CM, 0.0, B_UNIT_DEF_NONE}, + {"square millimeter", "square millimeters", "mm²", "mm2", "Square Millimeters", UN_SC_MM*UN_SC_MM, 0.0, B_UNIT_DEF_NONE}, + {"square micrometer", "square micrometers", "µm²", "um2", "Square Micrometers", UN_SC_UM*UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricAreaCollecton = {buMetricAreaDef, 3, 0, sizeof(buMetricAreaDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialAreaDef[] = { + {"square mile", "square miles", "sq mi", "sq m","Square Miles", UN_SC_MI*UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, + {"square furlong", "square furlongs", "sq fur",NULL, "Square Furlongs", UN_SC_FUR*UN_SC_FUR, 0.0,B_UNIT_DEF_SUPPRESS}, + {"square chain", "square chains", "sq ch", NULL, "Square Chains", UN_SC_CH*UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS}, + {"square yard", "square yards", "sq yd", NULL, "Square Yards", UN_SC_YD*UN_SC_YD, 0.0, B_UNIT_DEF_NONE}, + {"square foot", "square feet", "sq ft", NULL, "Square Feet", UN_SC_FT*UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"square inch", "square inches", "sq in", NULL, "Square Inches", UN_SC_IN*UN_SC_IN, 0.0, B_UNIT_DEF_NONE}, + {"square thou", "square thous", "sq mil",NULL, "Square Thous", UN_SC_MIL*UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialAreaCollecton = {buImperialAreaDef, 4, 0, sizeof(buImperialAreaDef)/sizeof(bUnitDef)}; + +/* Volumes */ +static struct bUnitDef buMetricVolDef[] = { + {"cubic kilometer", "cubic kilometers", "km³", "km3", "Cubic Kilometers", UN_SC_KM*UN_SC_KM*UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, + {"cubic hectometer","cubic hectometers", "hm³", "hm3", "Cubic Hectometers", UN_SC_HM*UN_SC_HM*UN_SC_HM, 0.0, B_UNIT_DEF_NONE}, + {"cubic dekameter", "cubic dekameters", "dam³","dam3", "Cubic Dekameters", UN_SC_DAM*UN_SC_DAM*UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"cubic meter", "cubic meters", "m³", "m3", "Cubic Meters", UN_SC_M*UN_SC_M*UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"cubic decimetre", "cubic decimetres", "dm³", "dm3", "Cubic Decimetres", UN_SC_DM*UN_SC_DM*UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"cubic centimeter", "cubic centimeters", "cm³", "cm3", "Cubic Centimeters", UN_SC_CM*UN_SC_CM*UN_SC_CM, 0.0, B_UNIT_DEF_NONE}, + {"cubic millimeter", "cubic millimeters", "mm³", "mm3", "Cubic Millimeters", UN_SC_MM*UN_SC_MM*UN_SC_MM, 0.0, B_UNIT_DEF_NONE}, + {"cubic micrometer", "cubic micrometers", "µm³", "um3", "Cubic Micrometers", UN_SC_UM*UN_SC_UM*UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricVolCollecton = {buMetricVolDef, 3, 0, sizeof(buMetricVolDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialVolDef[] = { + {"cubic mile", "cubic miles", "cu mi", "cu m","Cubic Miles", UN_SC_MI*UN_SC_MI*UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, + {"cubic furlong", "cubic furlongs", "cu fur",NULL, "Cubic Furlongs", UN_SC_FUR*UN_SC_FUR*UN_SC_FUR, 0.0,B_UNIT_DEF_SUPPRESS}, + {"cubic chain", "cubic chains", "cu ch", NULL, "Cubic Chains", UN_SC_CH*UN_SC_CH*UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS}, + {"cubic yard", "cubic yards", "cu yd", NULL, "Cubic Yards", UN_SC_YD*UN_SC_YD*UN_SC_YD, 0.0, B_UNIT_DEF_NONE}, + {"cubic foot", "cubic feet", "cu ft", NULL, "Cubic Feet", UN_SC_FT*UN_SC_FT*UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"cubic inch", "cubic inches", "cu in", NULL, "Cubic Inches", UN_SC_IN*UN_SC_IN*UN_SC_IN, 0.0, B_UNIT_DEF_NONE}, + {"cubic thou", "cubic thous", "cu mil",NULL, "Cubic Thous", UN_SC_MIL*UN_SC_MIL*UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialVolCollecton = {buImperialVolDef, 4, 0, sizeof(buImperialVolDef)/sizeof(bUnitDef)}; + +/* Mass */ +static struct bUnitDef buMetricMassDef[] = { + {"ton", "tonnes", "ton", "t", "1000 Kilograms", UN_SC_MTON, 0.0, B_UNIT_DEF_NONE}, + {"quintal", "quintals", "ql", "q", "100 Kilograms", UN_SC_QL, 0.0, B_UNIT_DEF_NONE}, + {"kilogram", "kilograms", "kg", NULL, "Kilograms", UN_SC_KG, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"hectogram", "hectograms", "hg", NULL, "Hectograms", UN_SC_HG, 0.0, B_UNIT_DEF_NONE}, + {"dekagram", "dekagrams", "dag",NULL, "10 Grams", UN_SC_DAG, 0.0, B_UNIT_DEF_SUPPRESS}, + {"gram", "grams", "g", NULL, "Grams", UN_SC_G, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricMassCollecton = {buMetricMassDef, 2, 0, sizeof(buMetricMassDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialMassDef[] = { + {"ton", "tonnes", "ton", "t", "Tonnes", UN_SC_ITON, 0.0, B_UNIT_DEF_NONE}, + {"centum weight", "centum weights", "cwt", NULL, "Centum weights", UN_SC_CWT, 0.0, B_UNIT_DEF_NONE}, + {"stone", "stones", "st", NULL, "Stones", UN_SC_ST, 0.0, B_UNIT_DEF_NONE}, + {"pound", "pounds", "lb", NULL, "Pounds", UN_SC_LB, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"ounce", "ounces", "oz", NULL, "Ounces", UN_SC_OZ, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialMassCollecton = {buImperialMassDef, 3, 0, sizeof(buImperialMassDef)/sizeof(bUnitDef)}; + +/* Even if user scales the system to a point where km^3 is used, velocity and + * acceleration aren't scaled: that's why we have so few units for them */ + +/* Velocity */ +static struct bUnitDef buMetricVelDef[] = { + {"meter per second", "meters per second", "m/s", NULL, "Meters per second", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"kilometer per hour", "kilometers per hour", "km/h", NULL, "Kilometers per hour", UN_SC_KM/3600.0f, 0.0, B_UNIT_DEF_SUPPRESS}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricVelCollecton = {buMetricVelDef, 0, 0, sizeof(buMetricVelDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialVelDef[] = { + {"foot per second", "feet per second", "ft/s", "fps", "Feet per second", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"mile per hour", "miles per hour", "mph", NULL, "Miles per hour", UN_SC_MI/3600.0f, 0.0,B_UNIT_DEF_SUPPRESS}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialVelCollecton = {buImperialVelDef, 0, 0, sizeof(buImperialVelDef)/sizeof(bUnitDef)}; + +/* Acceleration */ +static struct bUnitDef buMetricAclDef[] = { + {"meter per second squared", "meters per second squared", "m/s²", "m/s2", "Meters per second squared", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricAclCollecton = {buMetricAclDef, 0, 0, sizeof(buMetricAclDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialAclDef[] = { + {"foot per second squared", "feet per second squared", "ft/s²", "ft/s2", "Feet per second squared", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialAclCollecton = {buImperialAclDef, 0, 0, sizeof(buImperialAclDef)/sizeof(bUnitDef)}; /* Time */ static struct bUnitDef buNaturalTimeDef[] = { @@ -114,7 +251,7 @@ static struct bUnitDef buNaturalTimeDef[] = { {"minute", "minutes", "min", "m", "Minutes", 60.0, 0.0, B_UNIT_DEF_NONE}, {"second", "seconds", "sec", "s", "Seconds", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */ {"millisecond", "milliseconds", "ms", NULL, "Milliseconds", 0.001, 0.0 , B_UNIT_DEF_NONE}, - {"microsecond", "microseconds", "us", NULL, "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE}, + {"microsecond", "microseconds", "µs", "us", "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef)/sizeof(bUnitDef)}; @@ -126,14 +263,16 @@ static struct bUnitDef buNaturalRotDef[] = { }; static struct bUnitCollection buNaturalRotCollection = {buNaturalRotDef, 0, 0, sizeof(buNaturalRotDef)/sizeof(bUnitDef)}; -#define UNIT_SYSTEM_MAX 3 -static struct bUnitCollection *bUnitSystems[][8] = { - {0,0,0,0,0,&buNaturalRotCollection,&buNaturalTimeCollecton,0}, - {0,&buMetricLenCollecton, 0,0,0, &buNaturalRotCollection, &buNaturalTimeCollecton,0}, /* metric */ - {0,&buImperialLenCollecton, 0,0,0,&buNaturalRotCollection, &buNaturalTimeCollecton,0}, /* imperial */ - {0,0,0,0,0,0,0,0} +#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / 9) / sizeof(void *)) - 1) +static struct bUnitCollection *bUnitSystems[][9] = { + {0, 0, 0, 0, 0, &buNaturalRotCollection, &buNaturalTimeCollecton, 0, 0}, + {0, &buMetricLenCollecton, &buMetricAreaCollecton, &buMetricVolCollecton, &buMetricMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buMetricVelCollecton, &buMetricAclCollecton}, /* metric */ + {0, &buImperialLenCollecton, &buImperialAreaCollecton, &buImperialVolCollecton, &buImperialMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buImperialVelCollecton, &buImperialAclCollecton}, /* imperial */ + {0, 0, 0, 0, 0, 0, 0, 0, 0} }; + + /* internal, has some option not exposed */ static bUnitCollection *unit_get_system(int system, int type) { @@ -256,8 +395,9 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system, if(usys==NULL || usys->units[0].name==NULL) usys= &buDummyCollecton; - - if(split) { + + /* split output makes sense only for length, mass and time */ + if(split && (type==B_UNIT_LENGTH || type==B_UNIT_MASS || type==B_UNIT_TIME)) { int i; bUnitDef *unit_a, *unit_b; double value_a, value_b; @@ -443,10 +583,6 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre for(unit= usys->units; unit->name; unit++) { - - if(unit->flag & B_UNIT_DEF_SUPPRESS) - continue; - /* incase there are multiple instances */ while(unit_replace(str, len_max, str_tmp, scale_pref, unit)) change= 1; @@ -458,18 +594,15 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre bUnitCollection *usys_iter; int system_iter; - for(system_iter= 0; system_iter<UNIT_SYSTEM_MAX; system_iter++) { + for(system_iter= 0; system_iter<UNIT_SYSTEM_TOT; system_iter++) { if (system_iter != system) { usys_iter= unit_get_system(system_iter, type); if (usys_iter) { for(unit= usys_iter->units; unit->name; unit++) { - - if((unit->flag & B_UNIT_DEF_SUPPRESS) == 0) { - int ofs = 0; - /* incase there are multiple instances */ - while((ofs=unit_replace(str+ofs, len_max-ofs, str_tmp, scale_pref, unit))) - change= 1; - } + int ofs = 0; + /* incase there are multiple instances */ + while((ofs=unit_replace(str+ofs, len_max-ofs, str_tmp, scale_pref, unit))) + change= 1; } } } @@ -482,10 +615,6 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre if(str_prev) { /* see which units the original value had */ for(unit= usys->units; unit->name; unit++) { - - if(unit->flag & B_UNIT_DEF_SUPPRESS) - continue; - if (unit_find(str_prev, unit)) break; } @@ -543,6 +672,49 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre return change; } +/* 45µm --> 45um */ +void bUnit_ToUnitAltName(char *str, int len_max, char *orig_str, int system, int type) +{ + bUnitCollection *usys = unit_get_system(system, type); + + bUnitDef *unit; + bUnitDef *unit_def= unit_default(usys); + + /* find and substitute all units */ + for(unit= usys->units; unit->name; unit++) { + if(len_max > 0 && (unit->name_alt || unit == unit_def)) + { + char *found= NULL; + + found= unit_find_str(orig_str, unit->name_short); + if(found) { + int offset= found - orig_str; + int len_name= 0; + + /* copy everything before the unit */ + offset= (offset<len_max? offset: len_max); + strncpy(str, orig_str, offset); + + str+= offset; + orig_str+= offset + strlen(unit->name_short); + len_max-= offset; + + /* print the alt_name */ + if(unit->name_alt) + len_name= snprintf(str, len_max, "%s", unit->name_alt); + else + len_name= 0; + + len_name= (len_name<len_max? len_name: len_max); + str+= len_name; + len_max-= len_name; + } + } + } + + /* finally copy the rest of the string */ + strncpy(str, orig_str, len_max); +} double bUnit_ClosestScalar(double value, int system, int type) { @@ -566,6 +738,12 @@ double bUnit_BaseScalar(int system, int type) } /* external access */ +int bUnit_IsValid(int system, int type) +{ + return !(type < 0 || type >= B_UNIT_MAXDEF || system < 0 || system > UNIT_SYSTEM_TOT); +} + + void bUnit_GetSystem(void **usys_pt, int *len, int system, int type) { bUnitCollection *usys = unit_get_system(system, type); diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 6cd207f628c..473c10d6ced 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -160,7 +160,7 @@ static int write_audio_frame(void) pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; if (av_interleaved_write_frame(outfile, &pkt) != 0) { - // XXX error("Error writing audio packet"); + fprintf(stderr, "Error writing audio packet!\n"); return -1; } return 0; @@ -290,7 +290,9 @@ static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports packet.data = video_buffer; packet.size = outsize; ret = av_interleaved_write_frame(outfile, &packet); - } else ret = 0; + } else { + ret = 0; + } if (ret != 0) { success= 0; @@ -778,6 +780,69 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report return 1; } +/** + * Writes any delayed frames in the encoder. This function is called before + * closing the encoder. + * + * <p> + * Since an encoder may use both past and future frames to predict + * inter-frames (H.264 B-frames, for example), it can output the frames + * in a different order from the one it was given. + * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write + * them in the order 1, 4, 2, 3 - first the two frames used for predition, + * and then the bidirectionally-predicted frames. What this means in practice + * is that the encoder may not immediately produce one output frame for each + * input frame. These delayed frames must be flushed before we close the + * stream. We do this by calling avcodec_encode_video with NULL for the last + * parameter. + * </p> + */ +void flush_ffmpeg(void) +{ + int outsize = 0; + int ret = 0; + + AVCodecContext* c = get_codec_from_stream(video_stream); + /* get the delayed frames */ + while (1) { + AVPacket packet; + av_init_packet(&packet); + + outsize = avcodec_encode_video(c, video_buffer, video_buffersize, NULL); + if (outsize < 0) { + fprintf(stderr, "Error encoding delayed frame %d\n", outsize); + break; + } + if (outsize == 0) { + break; + } + if (c->coded_frame->pts != AV_NOPTS_VALUE) { +#ifdef FFMPEG_CODEC_TIME_BASE + packet.pts = av_rescale_q(c->coded_frame->pts, + c->time_base, + video_stream->time_base); +#else + packet.pts = c->coded_frame->pts; +#endif + fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); + } else { + fprintf(stderr, "Video Frame PTS: not set\n"); + } + if (c->coded_frame->key_frame) { + packet.flags |= PKT_FLAG_KEY; + } + packet.stream_index = video_stream->index; + packet.data = video_buffer; + packet.size = outsize; + ret = av_interleaved_write_frame(outfile, &packet); + if (ret != 0) { + fprintf(stderr, "Error writing delayed frame %d\n", ret); + break; + } + } + avcodec_flush_buffers(get_codec_from_stream(video_stream)); +} + /* ********************************************************************** * public interface ********************************************************************** */ @@ -888,7 +953,6 @@ int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, return success; } - void end_ffmpeg(void) { int i; @@ -905,6 +969,11 @@ void end_ffmpeg(void) audio_mixdown_device = 0; } + if (video_stream && get_codec_from_stream(video_stream)) { + fprintf(stderr, "Flushing delayed frames...\n"); + flush_ffmpeg (); + } + if (outfile) { av_write_trailer(outfile); } @@ -913,8 +982,8 @@ void end_ffmpeg(void) if (video_stream && get_codec_from_stream(video_stream)) { avcodec_close(get_codec_from_stream(video_stream)); - video_stream = 0; printf("zero video stream %p\n", video_stream); + video_stream = 0; } @@ -1195,20 +1264,47 @@ void ffmpeg_set_preset(RenderData *rd, int preset) rd->ffcodecdata.mux_packet_size = 2048; rd->ffcodecdata.mux_rate = 10080000; + /* + * All options here are for x264, but must be set via ffmpeg. + * The names are therefore different - Search for "x264 to FFmpeg option mapping" + * to get a list. + */ + + /* + * Use CABAC coder. Using "coder:1", which should be equivalent, + * crashes Blender for some reason. Either way - this is no big deal. + */ ffmpeg_property_add_string(rd, "video", "coder:vlc"); + + /* + * The other options were taken from the libx264-default.preset + * included in the ffmpeg distribution. + */ ffmpeg_property_add_string(rd, "video", "flags:loop"); ffmpeg_property_add_string(rd, "video", "cmp:chroma"); ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); ffmpeg_property_add_string(rd, "video", "me:hex"); - ffmpeg_property_add_string(rd, "video", "subq:5"); + ffmpeg_property_add_string(rd, "video", "subq:6"); ffmpeg_property_add_string(rd, "video", "me_range:16"); + ffmpeg_property_add_string(rd, "video", "qdiff:4"); ffmpeg_property_add_string(rd, "video", "keyint_min:25"); ffmpeg_property_add_string(rd, "video", "sc_threshold:40"); ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71"); ffmpeg_property_add_string(rd, "video", "b_strategy:1"); - + ffmpeg_property_add_string(rd, "video", "bf:3"); + ffmpeg_property_add_string(rd, "video", "refs:2"); + ffmpeg_property_add_string(rd, "video", "qcomp:0.6"); + ffmpeg_property_add_string(rd, "video", "directpred:3"); + ffmpeg_property_add_string(rd, "video", "trellis:0"); + ffmpeg_property_add_string(rd, "video", "flags2:wpred"); + ffmpeg_property_add_string(rd, "video", "flags2:dct8x8"); + ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); + ffmpeg_property_add_string(rd, "video", "wpredp:2"); + + // This makes x264 output lossless. Will be a separate option later. + //ffmpeg_property_add_string(rd, "video", "cqp:0"); break; case FFMPEG_PRESET_THEORA: |