diff options
Diffstat (limited to 'source/blender/blenkernel')
27 files changed, 1175 insertions, 2726 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 6c415010953..7e9f531162b 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -53,7 +53,7 @@ extern "C" { /* can be left blank, otherwise a,b,c... etc with no quotes */ #define BLENDER_VERSION_CHAR b /* alpha/beta/rc/release, docs use this */ -#define BLENDER_VERSION_CYCLE release +#define BLENDER_VERSION_CYCLE beta struct ListBase; struct MemFile; diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 1ee51cd2122..a5c88000db2 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -35,6 +35,7 @@ */ #include <float.h> +#include "BLI_math_inline.h" struct Object; struct ListBase; @@ -44,16 +45,7 @@ struct DerivedMesh; struct ClothModifierData; struct CollisionTree; -// this is needed for inlining behaviour -#if defined _WIN32 -# define DO_INLINE __inline -#elif defined (__sgi) -# define DO_INLINE -#elif defined (__sun) || defined (__sun__) -# define DO_INLINE -#else -# define DO_INLINE static inline -#endif +#define DO_INLINE MALWAYS_INLINE #define CLOTH_MAX_THREAD 2 diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index b54d4275719..4048ee2f457 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -63,7 +63,11 @@ struct LinkNode; /* COLLISION FLAGS */ typedef enum { - COLLISION_IN_FUTURE = ( 1 << 1 ), + COLLISION_IN_FUTURE = (1 << 1), +#ifdef WITH_ELTOPO + COLLISION_USE_COLLFACE = (1 << 2), + COLLISION_IS_EDGES = (1 << 3), +#endif } COLLISION_FLAGS; @@ -81,7 +85,13 @@ typedef struct CollPair float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 int flag; float time; // collision time, from 0 up to 1 +#ifdef WITH_ELTOPO /*either ap* or bp* can be set, but not both*/ + float bary[3]; + int ap1, ap2, ap3, collp, bp1, bp2, bp3; + int collface; +#else int ap1, ap2, ap3, bp1, bp2, bp3; +#endif int pointsb[4]; } CollPair; @@ -109,6 +119,7 @@ typedef struct FaceCollPair float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 } FaceCollPair; + //////////////////////////////////////// diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h deleted file mode 100644 index 870dd7cb4d5..00000000000 --- a/source/blender/blenkernel/BKE_exotic.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef BKE_EXOTIC_H -#define BKE_EXOTIC_H - -/** \file BKE_exotic.h - * \ingroup bke - * \brief dxf/vrml/stl external file io function prototypes. - * \attention is this used still? Candidate for removal? - */ -struct Mesh; -struct Scene; - -/** - * Reads all 3D fileformats other than Blender fileformat - * @retval 0 The file could not be read. - * @retval 1 The file was read succesfully. - * @attention Used in filesel.c - */ -int BKE_read_exotic(struct Scene *scene, const char *name); - -/* return codes */ -#define BKE_READ_EXOTIC_FAIL_PATH -3 /* file format is not supported */ -#define BKE_READ_EXOTIC_FAIL_FORMAT -2 /* file format is not supported */ -#define BKE_READ_EXOTIC_FAIL_OPEN -1 /* Can't open the file */ -#define BKE_READ_EXOTIC_OK_BLEND 0 /* .blend file */ -#define BKE_READ_EXOTIC_OK_OTHER 1 /* other supported formats */ - -void write_dxf(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 64c29158bd4..10910493ec9 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -133,6 +133,7 @@ void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); /* called on frame change or before render */ void BKE_image_user_calc_frame(struct ImageUser *iuser, int cfra, int fieldnr); +int BKE_image_user_get_frame(const struct ImageUser *iuser, int cfra, int fieldnr); /* fix things in ImageUser when new image gets assigned */ void BKE_image_user_new_image(struct Image *ima, struct ImageUser *iuser); diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 136ce416037..20e5bc27146 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -58,7 +58,7 @@ void write_text(struct Text *text, const char *str); char* txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); void txt_order_cursors (struct Text *text); -int txt_find_string (struct Text *text, char *findstr, int wrap); +int txt_find_string (struct Text *text, char *findstr, int wrap, int match_case); int txt_has_sel (struct Text *text); int txt_get_span (struct TextLine *from, struct TextLine *to); void txt_move_up (struct Text *text, short sel); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index a619be07b6a..0da260c3f2a 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -92,7 +92,6 @@ set(SRC intern/depsgraph.c intern/displist.c intern/effect.c - intern/exotic.c intern/fcurve.c intern/fluidsim.c intern/fmodifier.c @@ -147,7 +146,7 @@ set(SRC intern/writeavi.c intern/writeffmpeg.c intern/writeframeserver.c - + BKE_DerivedMesh.h BKE_action.h BKE_anim.h @@ -178,7 +177,6 @@ set(SRC BKE_displist.h BKE_effect.h BKE_endian.h - BKE_exotic.h BKE_fcurve.h BKE_fluidsim.h BKE_font.h @@ -242,6 +240,11 @@ if(WITH_BULLET) add_definitions(-DUSE_BULLET) endif() +if(WITH_MOD_CLOTH_ELTOPO) + list(APPEND INC ../../../extern/eltopo) + add_definitions(-DWITH_ELTOPO) +endif() + if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index d865912f5e0..52b8b535038 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -27,6 +27,10 @@ if env['WITH_BF_PYTHON']: if env['BF_DEBUG']: defs.append('DEBUG') +if env['WITH_BF_ELTOPO']: + incs += ' ../../../extern/eltopo' + defs.append('WITH_ELTOPO') + if env['WITH_BF_QUICKTIME']: incs += ' ../quicktime' diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 7d3219d917e..d9c98bc0200 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1772,11 +1772,20 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos modifier_setError(md, "Modifier requires original data, bad stack position."); continue; } - if(sculpt_mode && (!has_multires || multires_applied)) - if(mti->type != eModifierTypeType_OnlyDeform || multires_applied) { + if(sculpt_mode && (!has_multires || multires_applied)) { + int unsupported= 0; + + if(scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) + unsupported|= mti->type != eModifierTypeType_OnlyDeform; + + unsupported|= md->type == eModifierType_Multires && ((MultiresModifierData*)md)->sculptlvl==0; + unsupported|= multires_applied; + + if(unsupported) { modifier_setError(md, "Not supported in sculpt mode."); continue; } + } if(needMapping && !modifier_supportsMapping(md)) continue; if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; @@ -1815,7 +1824,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos * to avoid giving bogus normals to the next modifier see: [#23673] */ if(isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { /* XXX, this covers bug #23673, but we may need normal calc for other types */ - if(dm->type == DM_TYPE_CDDM) { + if(dm && dm->type == DM_TYPE_CDDM) { CDDM_apply_vert_coords(dm, deformedVerts); CDDM_calc_normals(dm); } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index ce6a95430e3..75c6303d800 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -619,24 +619,14 @@ void BKE_reset_undo(void) /* based on index nr it does a restore */ void BKE_undo_number(bContext *C, int nr) { - UndoElem *uel; - int a=1; - - for(uel= undobase.first; uel; uel= uel->next, a++) { - if(a==nr) break; - } - curundo= uel; + curundo= BLI_findlink(&undobase, nr - 1); BKE_undo_step(C, 0); } /* go back to the last occurance of name in stack */ void BKE_undo_name(bContext *C, const char *name) { - UndoElem *uel; - - for(uel= undobase.last; uel; uel= uel->prev) - if(strcmp(name, uel->name)==0) - break; + UndoElem *uel= BLI_rfindstring(&undobase, name, offsetof(UndoElem, name)); if(uel && uel->prev) { curundo= uel->prev; @@ -648,12 +638,7 @@ void BKE_undo_name(bContext *C, const char *name) int BKE_undo_valid(const char *name) { if(name) { - UndoElem *uel; - - for(uel= undobase.last; uel; uel= uel->prev) - if(strcmp(name, uel->name)==0) - break; - + UndoElem *uel= BLI_rfindstring(&undobase, name, offsetof(UndoElem, name)); return uel && uel->prev; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 8bd650b1a42..72ee9b55800 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -231,19 +231,21 @@ static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) this derivedmesh is just original mesh. it's the multires subsurf dm that this is actually for, to support a pbvh on a modified mesh */ if(!cddm->pbvh && ob->type == OB_MESH) { + SculptSession *ss= ob->sculpt; Mesh *me= ob->data; cddm->pbvh = BLI_pbvh_new(); cddm->pbvh_draw = can_pbvh_draw(ob, dm); BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert, me->totface, me->totvert); - if(ob->sculpt->modifiers_active) { + if(ss->modifiers_active && ob->derivedDeform) { + DerivedMesh *deformdm= ob->derivedDeform; float (*vertCos)[3]; int totvert; - totvert= dm->getNumVerts(dm); + totvert= deformdm->getNumVerts(deformdm); vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos"); - dm->getVertCos(dm, vertCos); + deformdm->getVertCos(deformdm, vertCos); BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos); MEM_freeN(vertCos); } @@ -594,26 +596,26 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha glBegin(glmode = new_glmode); } - glColor3ub(cp1[0], cp1[1], cp1[2]); + glColor3ubv(cp1+0); glVertex3fv(mvert[mface->v1].co); - glColor3ub(cp1[4], cp1[5], cp1[6]); + glColor3ubv(cp1+4); glVertex3fv(mvert[mface->v2].co); - glColor3ub(cp1[8], cp1[9], cp1[10]); + glColor3ubv(cp1+8); glVertex3fv(mvert[mface->v3].co); if(mface->v4) { - glColor3ub(cp1[12], cp1[13], cp1[14]); + glColor3ubv(cp1+12); glVertex3fv(mvert[mface->v4].co); } if(useTwoSided) { - glColor3ub(cp2[8], cp2[9], cp2[10]); + glColor3ubv(cp2+8); glVertex3fv(mvert[mface->v3].co ); - glColor3ub(cp2[4], cp2[5], cp2[6]); + glColor3ubv(cp2+4); glVertex3fv(mvert[mface->v2].co ); - glColor3ub(cp2[0], cp2[1], cp2[2]); + glColor3ubv(cp2+0); glVertex3fv(mvert[mface->v1].co ); if(mface->v4) { - glColor3ub(cp2[12], cp2[13], cp2[14]); + glColor3ubv(cp2+12); glVertex3fv(mvert[mface->v4].co ); } } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 5eccf724256..ea055e90b45 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -919,7 +919,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if(!first) implicit_set_positions(clmd); - clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); + clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, MAX2(clmd->coll_parms->epsilon, clmd->coll_parms->distance_repel) ); for(i = 0; i < dm->getNumVerts(dm); i++) { diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index ebdbbfcf7b4..e2a1b0dfb33 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -48,6 +48,9 @@ #include "BLI_math.h" #include "BLI_edgehash.h" #include "BLI_utildefines.h" +#include "BLI_ghash.h" +#include "BLI_memarena.h" +#include "BLI_rand.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" @@ -63,6 +66,10 @@ #include "BLI_kdopbvh.h" #include "BKE_collision.h" +#ifdef WITH_ELTOPO +#include "eltopo-capi.h" +#endif + /*********************************** Collision modifier code start @@ -486,7 +493,7 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float VECADDMUL ( to, v3, w3 ); } - +#ifndef WITH_ELTOPO static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; @@ -601,12 +608,799 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM } return result; } +#endif /* !WITH_ELTOPO */ + +#ifdef WITH_ELTOPO +typedef struct edgepairkey { + int a1, a2, b1, b2; +} edgepairkey; + +unsigned int edgepair_hash(void *vkey) +{ + edgepairkey *key = vkey; + int keys[4] = {key->a1, key->a2, key->b1, key->b2}; + int i, j; + + for (i=0; i<4; i++) { + for (j=0; j<3; j++) { + if (keys[j] >= keys[j+1]) { + SWAP(int, keys[j], keys[j+1]); + } + } + } + + return keys[0]*101 + keys[1]*72 + keys[2]*53 + keys[3]*34; +} + +int edgepair_cmp(const void *va, const void *vb) +{ + edgepairkey *a = va, *b = vb; + int keysa[4] = {a->a1, a->a2, a->b1, a->b2}; + int keysb[4] = {b->a1, b->a2, b->b1, b->b2}; + int i; + + for (i=0; i<4; i++) { + int j, ok=0; + for (j=0; j<4; j++) { + if (keysa[i] == keysa[j]) { + ok = 1; + break; + } + } + if (!ok) + return -1; + } + + return 0; +} + +static void get_edgepairkey(edgepairkey *key, int a1, int a2, int b1, int b2) +{ + key->a1 = a1; + key->a2 = a2; + key->b1 = b1; + key->b2 = b2; +} + +/*an immense amount of duplication goes on here. . .a major performance hit, I'm sure*/ +static CollPair* cloth_edge_collision ( ModifierData *md1, ModifierData *md2, + BVHTreeOverlap *overlap, CollPair *collpair, + GHash *visithash, MemArena *arena) +{ + ClothModifierData *clmd = ( ClothModifierData * ) md1; + CollisionModifierData *collmd = ( CollisionModifierData * ) md2; + MFace *face1=NULL, *face2 = NULL; + ClothVertex *verts1 = clmd->clothObject->verts; + double distance = 0; + edgepairkey *key, tstkey; + float epsilon1 = clmd->coll_parms->epsilon; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + float no[3], uv[3], t, relnor; + int i, i1, i2, i3, i4, i5, i6; + Cloth *cloth = clmd->clothObject; + float n1[3], n2[3], off[3], v1[2][3], v2[2][3], v3[2][3], v4[2][3], v5[2][3], v6[2][3]; + void **verts[] = {v1, v2, v3, v4, v5, v6}; + int j, ret, bp1, bp2, bp3, ap1, ap2, ap3, table[6]; + + face1 = & ( clmd->clothObject->mfaces[overlap->indexA] ); + face2 = & ( collmd->mfaces[overlap->indexB] ); + + // check all 4 possible collisions + for ( i = 0; i < 4; i++ ) + { + if ( i == 0 ) + { + // fill faceA + ap1 = face1->v1; + ap2 = face1->v2; + ap3 = face1->v3; + + // fill faceB + bp1 = face2->v1; + bp2 = face2->v2; + bp3 = face2->v3; + } + else if ( i == 1 ) + { + if ( face1->v4 ) + { + // fill faceA + ap1 = face1->v1; + ap2 = face1->v3; + ap3 = face1->v4; + + // fill faceB + bp1 = face2->v1; + bp2 = face2->v2; + bp3 = face2->v3; + } + else { + continue; + } + } + if ( i == 2 ) + { + if ( face2->v4 ) + { + // fill faceA + ap1 = face1->v1; + ap2 = face1->v2; + ap3 = face1->v3; + + // fill faceB + bp1 = face2->v1; + bp2 = face2->v3; + bp3 = face2->v4; + } + else { + continue; + } + } + else if ( i == 3 ) + { + if ( face1->v4 && face2->v4 ) + { + // fill faceA + ap1 = face1->v1; + ap2 = face1->v3; + ap3 = face1->v4; + + // fill faceB + bp1 = face2->v1; + bp2 = face2->v3; + bp3 = face2->v4; + } + else { + continue; + } + } + + copy_v3_v3(v1[0], cloth->verts[ap1].txold); + copy_v3_v3(v1[1], cloth->verts[ap1].tx); + copy_v3_v3(v2[0], cloth->verts[ap2].txold); + copy_v3_v3(v2[1], cloth->verts[ap2].tx); + copy_v3_v3(v3[0], cloth->verts[ap3].txold); + copy_v3_v3(v3[1], cloth->verts[ap3].tx); + + copy_v3_v3(v4[0], collmd->current_x[bp1].co); + copy_v3_v3(v4[1], collmd->current_xnew[bp1].co); + copy_v3_v3(v5[0], collmd->current_x[bp2].co); + copy_v3_v3(v5[1], collmd->current_xnew[bp2].co); + copy_v3_v3(v6[0], collmd->current_x[bp3].co); + copy_v3_v3(v6[1], collmd->current_xnew[bp3].co); + + normal_tri_v3(n2, v4[1], v5[1], v6[1]); + + /*offset new positions a bit, to account for margins*/ + i1 = ap1; i2 = ap2; i3 = ap3; + i4 = bp1; i5 = bp2; i6 = bp3; + + for (j=0; j<3; j++) { + int collp1, collp2, k, j2 = (j+1)%3; + + table[0] = ap1; table[1] = ap2; table[2] = ap3; + table[3] = bp1; table[4] = bp2; table[5] = bp3; + for (k=0; k<3; k++) { + float p1[3], p2[3]; + int k2 = (k+1)%3; + + get_edgepairkey(&tstkey, table[j], table[j2], table[k+3], table[k2+3]); + //if (BLI_ghash_haskey(visithash, &tstkey)) + // continue; + + key = BLI_memarena_alloc(arena, sizeof(edgepairkey)); + *key = tstkey; + BLI_ghash_insert(visithash, key, NULL); + + sub_v3_v3v3(p1, verts[j], verts[j2]); + sub_v3_v3v3(p2, verts[k+3], verts[k2+3]); + + cross_v3_v3v3(off, p1, p2); + normalize_v3(off); + + if (dot_v3v3(n2, off) < 0.0) + negate_v3(off); + + mul_v3_fl(off, epsilon1 + epsilon2 + ALMOST_ZERO); + copy_v3_v3(p1, verts[k+3]); + copy_v3_v3(p2, verts[k2+3]); + add_v3_v3(p1, off); + add_v3_v3(p2, off); + + ret = eltopo_line_line_moving_isect_v3v3_f(verts[j], table[j], verts[j2], table[j2], + p1, table[k+3], p2, table[k2+3], + no, uv, &t, &relnor); + /*cloth vert versus coll face*/ + if (ret) { + collpair->ap1 = table[j]; collpair->ap2 = table[j2]; + collpair->bp1 = table[k+3]; collpair->bp2 = table[k2+3]; + + /*I'm not sure if this is correct, but hopefully it's + better then simply ignoring back edges*/ + if (dot_v3v3(n2, no) < 0.0) { + negate_v3(no); + } + + copy_v3_v3(collpair->normal, no); + mul_v3_v3fl(collpair->vector, collpair->normal, relnor); + collpair->distance = relnor; + collpair->time = t; + + copy_v2_v2(collpair->bary, uv); + + collpair->flag = COLLISION_IS_EDGES; + collpair++; + } + } + } + } + + return collpair; +} + +static int cloth_edge_collision_response_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +{ + int result = 0; + Cloth *cloth1; + float w1, w2; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel, pimpulse[3]; + + cloth1 = clmd->clothObject; + + for ( ; collpair != collision_end; collpair++ ) + { + if (!(collpair->flag & COLLISION_IS_EDGES)) + continue; + + // was: txold + w1 = collpair->bary[0]; w2 = collpair->bary[1]; + + // Calculate relative "velocity". + VECADDFAC(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, w1); + VECADDFAC(v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, w2); + + VECSUB ( relativeVelocity, v2, v1); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR ( relativeVelocity, collpair->normal ); + + // If v_n_mag < 0 the edges are approaching each other. + if ( magrelVel > ALMOST_ZERO ) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + float magtangent = 0, repulse = 0, d = 0; + double impulse = 0.0; + float vrel_t_pre[3]; + float temp[3], spf; + + zero_v3(pimpulse); + + // calculate tangential velocity + VECCOPY ( temp, collpair->normal ); + mul_v3_fl( temp, magrelVel ); + VECSUB ( vrel_t_pre, relativeVelocity, temp ); + + // Decrease in magnitude of relative tangential velocity due to coulomb friction + // in original formula "magrelVel" should be the "change of relative velocity in normal direction" + magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) ); + + // Apply friction impulse. + if ( magtangent > ALMOST_ZERO ) + { + normalize_v3( vrel_t_pre ); + + impulse = magtangent; + VECADDMUL ( pimpulse, vrel_t_pre, impulse); + } + + // Apply velocity stopping impulse + // I_c = m * v_N / 2.0 + // no 2.0 * magrelVel normally, but looks nicer DG + impulse = magrelVel; + + mul_v3_fl(collpair->normal, 0.5); + VECADDMUL ( pimpulse, collpair->normal, impulse); + + // Apply repulse impulse if distance too short + // I_r = -min(dt*kd, m(0,1d/dt - v_n)) + spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; + + d = collpair->distance; + if ( ( magrelVel < 0.1*d*spf && ( d > ALMOST_ZERO ) ) ) + { + repulse = MIN2 ( d*1.0/spf, 0.1*d*spf - magrelVel ); + + // stay on the safe side and clamp repulse + if ( impulse > ALMOST_ZERO ) + repulse = MIN2 ( repulse, 5.0*impulse ); + repulse = MAX2 ( impulse, repulse ); + + impulse = repulse / ( 5.0 ); // original 2.0 / 0.25 + VECADDMUL ( pimpulse, collpair->normal, impulse); + } + + w2 = 1.0f-w1; + if (w1 < 0.5) + w1 *= 2.0; + else + w2 *= 2.0; + + VECADDFAC(cloth1->verts[collpair->ap1].impulse, cloth1->verts[collpair->ap1].impulse, pimpulse, w1*2.0); + VECADDFAC(cloth1->verts[collpair->ap2].impulse, cloth1->verts[collpair->ap2].impulse, pimpulse, w2*2.0); + + cloth1->verts[collpair->ap1].impulse_count++; + cloth1->verts[collpair->ap2].impulse_count++; + + result = 1; + } + } + + return result; +} + +static int cloth_collision_response_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +{ + int result = 0; + Cloth *cloth1; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + + cloth1 = clmd->clothObject; + + for ( ; collpair != collision_end; collpair++ ) + { + if (collpair->flag & COLLISION_IS_EDGES) + continue; + + if ( collpair->flag & COLLISION_USE_COLLFACE ) { + // was: txold + w1 = collpair->bary[0]; w2 = collpair->bary[1]; w3 = collpair->bary[2]; + + // Calculate relative "velocity". + collision_interpolateOnTriangle ( v1, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, w1, w2, w3); + + VECSUB ( relativeVelocity, v1, cloth1->verts[collpair->collp].tv); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR ( relativeVelocity, collpair->normal ); + + // If v_n_mag < 0 the edges are approaching each other. + if ( magrelVel > ALMOST_ZERO ) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + float magtangent = 0, repulse = 0, d = 0; + double impulse = 0.0; + float vrel_t_pre[3]; + float temp[3], spf; + + // calculate tangential velocity + VECCOPY ( temp, collpair->normal ); + mul_v3_fl( temp, magrelVel ); + VECSUB ( vrel_t_pre, relativeVelocity, temp ); + + // Decrease in magnitude of relative tangential velocity due to coulomb friction + // in original formula "magrelVel" should be the "change of relative velocity in normal direction" + magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) ); + + // Apply friction impulse. + if ( magtangent > ALMOST_ZERO ) + { + normalize_v3( vrel_t_pre ); + + impulse = magtangent; // 2.0 * + VECADDMUL ( cloth1->verts[collpair->collp].impulse, vrel_t_pre, impulse); + } + + // Apply velocity stopping impulse + // I_c = m * v_N / 2.0 + // no 2.0 * magrelVel normally, but looks nicer DG + impulse = magrelVel/2.0; + + VECADDMUL ( cloth1->verts[collpair->collp].impulse, collpair->normal, impulse); + cloth1->verts[collpair->collp].impulse_count++; + + // Apply repulse impulse if distance too short + // I_r = -min(dt*kd, m(0,1d/dt - v_n)) + spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; + + d = -collpair->distance; + if ( ( magrelVel < 0.1*d*spf ) && ( d > ALMOST_ZERO ) ) + { + repulse = MIN2 ( d*1.0/spf, 0.1*d*spf - magrelVel ); + + // stay on the safe side and clamp repulse + if ( impulse > ALMOST_ZERO ) + repulse = MIN2 ( repulse, 5.0*impulse ); + repulse = MAX2 ( impulse, repulse ); + + impulse = repulse / ( 5.0 ); // original 2.0 / 0.25 + VECADDMUL ( cloth1->verts[collpair->collp].impulse, collpair->normal, impulse); + } + + result = 1; + } + } else { + w1 = collpair->bary[0]; w2 = collpair->bary[1]; w3 = collpair->bary[2]; + + // Calculate relative "velocity". + collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); + + VECSUB ( relativeVelocity, collmd->current_v[collpair->collp].co, v1); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR ( relativeVelocity, collpair->normal ); + + // If v_n_mag < 0 the edges are approaching each other. + if ( magrelVel > ALMOST_ZERO ) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + float magtangent = 0, repulse = 0, d = 0; + double impulse = 0.0; + float vrel_t_pre[3], pimpulse[3] = {0.0f, 0.0f, 0.0f}; + float temp[3], spf; + + // calculate tangential velocity + VECCOPY ( temp, collpair->normal ); + mul_v3_fl( temp, magrelVel ); + VECSUB ( vrel_t_pre, relativeVelocity, temp ); + + // Decrease in magnitude of relative tangential velocity due to coulomb friction + // in original formula "magrelVel" should be the "change of relative velocity in normal direction" + magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) ); + + // Apply friction impulse. + if ( magtangent > ALMOST_ZERO ) + { + normalize_v3( vrel_t_pre ); + + impulse = magtangent; // 2.0 * + VECADDMUL ( pimpulse, vrel_t_pre, impulse); + } + + // Apply velocity stopping impulse + // I_c = m * v_N / 2.0 + // no 2.0 * magrelVel normally, but looks nicer DG + impulse = magrelVel/2.0; + + VECADDMUL ( pimpulse, collpair->normal, impulse); + + // Apply repulse impulse if distance too short + // I_r = -min(dt*kd, m(0,1d/dt - v_n)) + spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; + + d = -collpair->distance; + if ( ( magrelVel < 0.1*d*spf ) && ( d > ALMOST_ZERO ) ) + { + repulse = MIN2 ( d*1.0/spf, 0.1*d*spf - magrelVel ); + + // stay on the safe side and clamp repulse + if ( impulse > ALMOST_ZERO ) + repulse = MIN2 ( repulse, 5.0*impulse ); + repulse = MAX2 ( impulse, repulse ); + + impulse = repulse / ( 2.0 ); // original 2.0 / 0.25 + VECADDMUL ( pimpulse, collpair->normal, impulse); + } + + if (w1 < 0.5) w1 *= 2.0; + if (w2 < 0.5) w2 *= 2.0; + if (w3 < 0.5) w3 *= 2.0; + + VECADDMUL(cloth1->verts[collpair->ap1].impulse, pimpulse, w1*2.0); + VECADDMUL(cloth1->verts[collpair->ap2].impulse, pimpulse, w2*2.0); + VECADDMUL(cloth1->verts[collpair->ap3].impulse, pimpulse, w3*2.0);; + cloth1->verts[collpair->ap1].impulse_count++; + cloth1->verts[collpair->ap2].impulse_count++; + cloth1->verts[collpair->ap3].impulse_count++; + + result = 1; + } + } + } + + return result; +} + + +typedef struct tripairkey { + int p, a1, a2, a3; +} tripairkey; + +unsigned int tripair_hash(void *vkey) +{ + tripairkey *key = vkey; + int keys[4] = {key->p, key->a1, key->a2, key->a3}; + int i, j; + + for (i=0; i<4; i++) { + for (j=0; j<3; j++) { + if (keys[j] >= keys[j+1]) { + SWAP(int, keys[j], keys[j+1]); + } + } + } + + return keys[0]*101 + keys[1]*72 + keys[2]*53 + keys[3]*34; +} + +int tripair_cmp(const void *va, const void *vb) +{ + tripairkey *a = va, *b = vb; + int keysa[4] = {a->p, a->a1, a->a2, a->a3}; + int keysb[4] = {b->p, b->a1, b->a2, b->a3}; + int i; + + for (i=0; i<4; i++) { + int j, ok=0; + for (j=0; j<4; j++) { + if (keysa[i] == keysa[j]) { + ok = 1; + break; + } + } + if (!ok) + return -1; + } + + return 0; +} + +static void get_tripairkey(tripairkey *key, int p, int a1, int a2, int a3) +{ + key->a1 = a1; + key->a2 = a2; + key->a3 = a3; + key->p = p; +} + +static int checkvisit(MemArena *arena, GHash *gh, int p, int a1, int a2, int a3) +{ + tripairkey key, *key2; + + get_tripairkey(&key, p, a1, a2, a3); + if (BLI_ghash_haskey(gh, &key)) + return 1; + + key2 = BLI_memarena_alloc(arena, sizeof(*key2)); + *key2 = key; + BLI_ghash_insert(gh, key2, NULL); + + return 0; +} + +int cloth_point_tri_moving_v3v3_f(float v1[2][3], int i1, float v2[2][3], int i2, + float v3[2][3], int i3, float v4[2][3], int i4, + float normal[3], float bary[3], float *t, + float *relnor, GHash *gh, MemArena *arena) +{ + if (checkvisit(arena, gh, i1, i2, i3, i4)) + return 0; + + return eltopo_point_tri_moving_v3v3_f(v1, i1, v2, i2, v3, i3, v4, i4, normal, bary, t, relnor); +} + +static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, + CollPair *collpair, double dt, GHash *gh, MemArena *arena) +{ + ClothModifierData *clmd = ( ClothModifierData * ) md1; + CollisionModifierData *collmd = ( CollisionModifierData * ) md2; + MFace *face1=NULL, *face2 = NULL; + ClothVertex *verts1 = clmd->clothObject->verts; + double distance = 0; + float epsilon1 = clmd->coll_parms->epsilon; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + float no[3], uv[3], t, relnor; + int i, i1, i2, i3, i4, i5, i6; + Cloth *cloth = clmd->clothObject; + float n1[3], sdis, p[3], l, n2[3], off[3], v1[2][3], v2[2][3], v3[2][3], v4[2][3], v5[2][3], v6[2][3]; + int j, ret, bp1, bp2, bp3, ap1, ap2, ap3; + + face1 = & ( clmd->clothObject->mfaces[overlap->indexA] ); + face2 = & ( collmd->mfaces[overlap->indexB] ); + + // check all 4 possible collisions + for ( i = 0; i < 4; i++ ) + { + if ( i == 0 ) + { + // fill faceA + ap1 = face1->v1; + ap2 = face1->v2; + ap3 = face1->v3; + + // fill faceB + bp1 = face2->v1; + bp2 = face2->v2; + bp3 = face2->v3; + } + else if ( i == 1 ) + { + if ( face1->v4 ) + { + // fill faceA + ap1 = face1->v1; + ap2 = face1->v3; + ap3 = face1->v4; + + // fill faceB + bp1 = face2->v1; + bp2 = face2->v2; + bp3 = face2->v3; + } + else { + continue; + } + } + if ( i == 2 ) + { + if ( face2->v4 ) + { + // fill faceA + ap1 = face1->v1; + ap2 = face1->v2; + ap3 = face1->v3; + + // fill faceB + bp1 = face2->v1; + bp2 = face2->v3; + bp3 = face2->v4; + } + else { + continue; + } + } + else if ( i == 3 ) + { + if ( face1->v4 && face2->v4 ) + { + // fill faceA + ap1 = face1->v1; + ap2 = face1->v3; + ap3 = face1->v4; + + // fill faceB + bp1 = face2->v1; + bp2 = face2->v3; + bp3 = face2->v4; + } + else { + continue; + } + } + + copy_v3_v3(v1[0], cloth->verts[ap1].txold); + copy_v3_v3(v1[1], cloth->verts[ap1].tx); + copy_v3_v3(v2[0], cloth->verts[ap2].txold); + copy_v3_v3(v2[1], cloth->verts[ap2].tx); + copy_v3_v3(v3[0], cloth->verts[ap3].txold); + copy_v3_v3(v3[1], cloth->verts[ap3].tx); + + copy_v3_v3(v4[0], collmd->current_x[bp1].co); + copy_v3_v3(v4[1], collmd->current_xnew[bp1].co); + copy_v3_v3(v5[0], collmd->current_x[bp2].co); + copy_v3_v3(v5[1], collmd->current_xnew[bp2].co); + copy_v3_v3(v6[0], collmd->current_x[bp3].co); + copy_v3_v3(v6[1], collmd->current_xnew[bp3].co); + + normal_tri_v3(n2, v4[1], v5[1], v6[1]); + + sdis = clmd->coll_parms->distance_repel + epsilon2 + FLT_EPSILON; + + /*apply a repulsion force, to help the solver along*/ + copy_v3_v3(off, n2); + negate_v3(off); + if (isect_ray_plane_v3(v1[1], off, v4[1], v5[1], v6[1], &l, 0)) { + if (l >= 0.0 && l < sdis) { + mul_v3_fl(off, (l-sdis)*cloth->verts[ap1].mass*dt*clmd->coll_parms->repel_force*0.1); + + add_v3_v3(cloth->verts[ap1].tv, off); + add_v3_v3(cloth->verts[ap2].tv, off); + add_v3_v3(cloth->verts[ap3].tv, off); + } + } + + /*offset new positions a bit, to account for margins*/ + copy_v3_v3(off, n2); + mul_v3_fl(off, epsilon1 + epsilon2 + ALMOST_ZERO); + add_v3_v3(v4[1], off); add_v3_v3(v5[1], off); add_v3_v3(v6[1], off); + + i1 = ap1; i2 = ap2; i3 = ap3; + i4 = bp1+cloth->numverts; i5 = bp2+cloth->numverts; i6 = bp3+cloth->numverts; + + for (j=0; j<6; j++) { + int collp; + + switch (j) { + case 0: + ret = cloth_point_tri_moving_v3v3_f(v1, i1, v4, i4, v5, i5, v6, i6, no, uv, &t, &relnor, gh, arena); + collp = ap1; + break; + case 1: + collp = ap2; + ret = cloth_point_tri_moving_v3v3_f(v2, i2, v4, i4, v5, i5, v6, i6, no, uv, &t, &relnor, gh, arena); + break; + case 2: + collp = ap3; + ret = cloth_point_tri_moving_v3v3_f(v3, i3, v4, i4, v5, i5, v6, i6, no, uv, &t, &relnor, gh, arena); + break; + case 3: + collp = bp1; + ret = cloth_point_tri_moving_v3v3_f(v4, i4, v1, i1, v2, i2, v3, i3, no, uv, &t, &relnor, gh, arena); + break; + case 4: + collp = bp2; + ret = cloth_point_tri_moving_v3v3_f(v5, i5, v1, i1, v2, i2, v3, i3, no, uv, &t, &relnor, gh, arena); + break; + case 5: + collp = bp3; + ret = cloth_point_tri_moving_v3v3_f(v6, i6, v1, i1, v2, i2, v3, i3, no, uv, &t, &relnor, gh, arena); + break; + } + + /*cloth vert versus coll face*/ + if (ret && j < 3) { + collpair->bp1 = bp1; collpair->bp2 = bp2; collpair->bp3 = bp3; + collpair->collp = collp; + + copy_v3_v3(collpair->normal, no); + mul_v3_v3fl(collpair->vector, collpair->normal, relnor); + collpair->distance = relnor; + collpair->time = t; + + copy_v3_v3(collpair->bary, uv); + + collpair->flag = COLLISION_USE_COLLFACE; + collpair++; + } else if (ret && j >= 3) { /*coll vert versus cloth face*/ + collpair->ap1 = ap1; collpair->ap2 = ap2; collpair->ap3 = ap3; + collpair->collp = collp; + + copy_v3_v3(collpair->normal, no); + mul_v3_v3fl(collpair->vector, collpair->normal, relnor); + collpair->distance = relnor; + collpair->time = t; + + copy_v3_v3(collpair->bary, uv); + + collpair->flag = 0; + collpair++; + } + } + } + + return collpair; +} + +static void machine_epsilon_offset(Cloth *cloth) { + ClothVertex *cv; + int i, j; + + cv = cloth->verts; + for (i=0; i<cloth->numverts; i++, cv++) { + /*aggrevatingly enough, it's necassary to offset the coordinates + by a multiple of the 32-bit floating point epsilon when switching + into doubles*/ + #define RNDSIGN (float)(-1*(BLI_rand()%2==0)|1) + for (j=0; j<3; j++) { + cv->tx[j] += FLT_EPSILON*30.0f*RNDSIGN; + cv->txold[j] += FLT_EPSILON*30.0f*RNDSIGN; + cv->tv[j] += FLT_EPSILON*30.0f*RNDSIGN; + } + } +} + +#else /* !WITH_ELTOPO */ //Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned -static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair ) +static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, + BVHTreeOverlap *overlap, CollPair *collpair, float dt ) { ClothModifierData *clmd = ( ClothModifierData * ) md1; CollisionModifierData *collmd = ( CollisionModifierData * ) md2; + Cloth *cloth = clmd->clothObject; MFace *face1=NULL, *face2 = NULL; #ifdef USE_BULLET ClothVertex *verts1 = clmd->clothObject->verts; @@ -614,6 +1408,7 @@ static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTree double distance = 0; float epsilon1 = clmd->coll_parms->epsilon; float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + float n2[3], sdis, l; int i; face1 = & ( clmd->clothObject->mfaces[overlap->indexA] ); @@ -685,7 +1480,28 @@ static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTree else break; } + + normal_tri_v3(n2, collmd->current_xnew[collpair->bp1].co, + collmd->current_xnew[collpair->bp2].co, + collmd->current_xnew[collpair->bp3].co); + + sdis = clmd->coll_parms->distance_repel + epsilon2 + FLT_EPSILON; + + /*apply a repulsion force, to help the solver along. + this is kindof crude, it only tests one vert of the triangle*/ + if (isect_ray_plane_v3(cloth->verts[collpair->ap1].tx, n2, collmd->current_xnew[collpair->bp1].co, + collmd->current_xnew[collpair->bp2].co, + collmd->current_xnew[collpair->bp3].co, &l, 0)) + { + if (l >= 0.0 && l < sdis) { + mul_v3_fl(n2, (l-sdis)*cloth->verts[collpair->ap1].mass*dt*clmd->coll_parms->repel_force*0.1); + add_v3_v3(cloth->verts[collpair->ap1].tv, n2); + add_v3_v3(cloth->verts[collpair->ap2].tv, n2); + add_v3_v3(cloth->verts[collpair->ap3].tv, n2); + } + } + #ifdef USE_BULLET // calc distance + normal distance = plNearestPoints ( @@ -741,6 +1557,8 @@ static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTree } return collpair; } +#endif /* WITH_ELTOPO */ + #if 0 static int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) @@ -1446,17 +2264,45 @@ void free_collider_cache(ListBase **colliders) } } -static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap) + +static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, + CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap, double dt) { int i; +#ifdef WITH_ELTOPO + GHash *visithash = BLI_ghash_new(edgepair_hash, edgepair_cmp, "visthash, collision.c"); + GHash *tri_visithash = BLI_ghash_new(tripair_hash, tripair_cmp, "tri_visthash, collision.c"); + MemArena *arena = BLI_memarena_new(1<<16, "edge hash arena, collision.c"); +#endif - *collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * numresult * 4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision + *collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * numresult * 64, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision *collisions_index = *collisions; + +#ifdef WITH_ELTOPO + machine_epsilon_offset(clmd->clothObject); + + for ( i = 0; i < numresult; i++ ) + { + *collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, + overlap+i, *collisions_index, dt, tri_visithash, arena ); + } for ( i = 0; i < numresult; i++ ) { - *collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, *collisions_index ); + *collisions_index = cloth_edge_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, + overlap+i, *collisions_index, visithash, arena ); } + BLI_ghash_free(visithash, NULL, NULL); + BLI_ghash_free(tri_visithash, NULL, NULL); + BLI_memarena_free(arena); +#else /* WITH_ELTOPO */ + for ( i = 0; i < numresult; i++ ) + { + *collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, + overlap+i, *collisions_index, dt ); + } +#endif /* WITH_ELTOPO */ + } static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) @@ -1481,11 +2327,19 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision if ( collmd->bvhtree ) { +#ifdef WITH_ELTOPO + result += cloth_collision_response_moving(clmd, collmd, collisions, collisions_index); + result += cloth_edge_collision_response_moving(clmd, collmd, collisions, collisions_index); +#else result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index ); - +#endif +#ifdef WITH_ELTOPO + { +#else // apply impulses in parallel if ( result ) { +#endif for ( i = 0; i < numverts; i++ ) { // calculate "velocities" (just xnew = xold + v; no dt in v) @@ -1518,7 +2372,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh==NULL) return 0; - + verts = cloth->verts; numfaces = cloth->numfaces; numverts = cloth->numverts; @@ -1557,6 +2411,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl continue; /* move object to position (step) in time */ + collision_move_object ( collmd, step + dt, step ); /* search for overlapping collision pairs */ @@ -1565,7 +2420,8 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl // go to next object if no overlap is there if( result && overlap ) { /* check if collisions really happen (costly near check) */ - cloth_bvh_objcollisions_nearcheck ( clmd, collmd, &collisions[i], &collisions_index[i], result, overlap); + cloth_bvh_objcollisions_nearcheck ( clmd, collmd, &collisions[i], + &collisions_index[i], result, overlap, dt/(float)clmd->coll_parms->loop_count); // resolve nearby collisions ret += cloth_bvh_objcollisions_resolve ( clmd, collmd, collisions[i], collisions_index[i]); @@ -1721,5 +2577,5 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl if(collobjs) MEM_freeN(collobjs); - return MIN2 ( ret, 1 ); + return 1|MIN2 ( ret, 1 ); } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index d2e48edc7ce..d3c14a9dd12 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4019,7 +4019,9 @@ bConstraintTypeInfo *constraint_get_typeinfo (bConstraint *con) /* ---------- Data Management ------- */ -/* Free data of a specific constraint if it has any info */ +/* Free data of a specific constraint if it has any info. + * be sure to run BIK_clear_data() when freeing an IK constraint, + * unless DAG_scene_sort is called. */ void free_constraint_data (bConstraint *con) { if (con->data) { diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 55d455bc5d3..2aeb726f623 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -451,7 +451,7 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res C->data.recursion= 1; - entry= BLI_findstring(&C->wm.store->entries, member, offsetof(bContextStoreEntry, name)); + entry= BLI_rfindstring(&C->wm.store->entries, member, offsetof(bContextStoreEntry, name)); if(entry) { result->ptr= entry->ptr; done= 1; diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c deleted file mode 100644 index ae773818438..00000000000 --- a/source/blender/blenkernel/intern/exotic.c +++ /dev/null @@ -1,2485 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * - * Contributor(s): - * - Martin DeMello - * Added dxf_read_arc, dxf_read_ellipse and dxf_read_lwpolyline - * Copyright (C) 2004 by Etheract Software Labs - * - * - Blender Foundation - * - * ***** END GPL LICENSE BLOCK **** - */ - -/** \file blender/blenkernel/intern/exotic.c - * \ingroup bke - */ - - -#include <stddef.h> -#include "BLI_storage.h" - -#include <stdlib.h> -#include <ctype.h> /* isdigit, isspace */ -#include <math.h> -#include <stdio.h> - -#include <fcntl.h> -#include <string.h> -#include <errno.h> - -#ifndef _WIN32 -#include <unistd.h> -#else -#include <io.h> -#define open _open -#define read _read -#define close _close -#define write _write -#endif - -#include "MEM_guardedalloc.h" - -#include "DNA_object_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_material_types.h" -#include "DNA_curve_types.h" -#include "DNA_camera_types.h" -#include "DNA_scene_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_storage.h" -#include "BLI_utildefines.h" - - -#include "BKE_blender.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_mesh.h" -#include "BKE_library.h" -#include "BKE_object.h" -#include "BKE_material.h" -#include "BKE_report.h" -#include "BKE_exotic.h" -#include "BKE_displist.h" -#include "BKE_DerivedMesh.h" -#include "BKE_curve.h" - -#ifdef WITH_PYTHON -#include "BPY_extern.h" -#endif - -#include "zlib.h" - -static int is_dxf(const char *str); -static void dxf_read(Scene *scene, const char *filename); -static int is_stl(const char *str); - -static int is_stl_ascii(const char *str) -{ - FILE *fpSTL; - char buffer[1000]; - int numread, i; - - fpSTL = fopen(str, "rb"); - if ( (numread = fread( (void *) buffer, sizeof(char), 1000, fpSTL)) <= 0 ) - { fclose(fpSTL); return 0; } - - for (i=0; i < numread; ++i) { - /* if bit 8 is set we assume binary */ - if (buffer[i] & 0x80) - { fclose(fpSTL); return 0; } - } - - buffer[5] = '\0'; - if ( !(strstr(buffer, "solid")) && !(strstr(buffer, "SOLID")) ) - { fclose(fpSTL); return 0; } - - fclose(fpSTL); - - return 1; -} - -static int is_stl(const char *str) -{ - int i; - i = strlen(str) - 3; - if ( (str[i] !='s') && (str[i] !='S')) - return 0; - i++; - if ( (str[i] !='t') && (str[i] !='T')) - return 0; - i++; - if ( (str[i] !='l') && (str[i] !='L')) - return 0; - - return 1; -} - -#define READSTLVERT { \ - if (fread(mvert->co, sizeof(float), 3, fpSTL) != 3) { \ - char error_msg[255]; \ - MEM_freeN(vertdata); \ - MEM_freeN(facedata); \ - fclose(fpSTL); \ - sprintf(error_msg, "Problems reading face %d!", i); \ - return; \ - } \ - else { \ - if (ENDIAN_ORDER==B_ENDIAN) { \ - SWITCH_INT(mvert->co[0]); \ - SWITCH_INT(mvert->co[1]); \ - SWITCH_INT(mvert->co[2]); \ - } \ - } \ -} - -static void simple_vertex_normal_blend(short *no, short *ble) -{ - if(no[0]==0 && no[1]==0 && no[2]==0) { - VECCOPY(no, ble); - } - else { - no[0]= (2*no[0] + ble[0])/3; - no[1]= (2*no[1] + ble[1])/3; - no[2]= (2*no[2] + ble[2])/3; - } -} - -static void mesh_add_normals_flags(Mesh *me) -{ - MVert *v1, *v2, *v3, *v4; - MFace *mface; - float nor[3]; - int a; - short sno[3]; - - mface= me->mface; - for(a=0; a<me->totface; a++, mface++) { - v1= me->mvert+mface->v1; - v2= me->mvert+mface->v2; - v3= me->mvert+mface->v3; - v4= me->mvert+mface->v4; - - normal_tri_v3( nor,v1->co, v2->co, v3->co); - normal_float_to_short_v3(sno, nor); - - simple_vertex_normal_blend(v1->no, sno); - simple_vertex_normal_blend(v2->no, sno); - simple_vertex_normal_blend(v3->no, sno); - if(mface->v4) { - simple_vertex_normal_blend(v4->no, sno); - } - mface->edcode= ME_V1V2|ME_V2V3; - } -} - -static void read_stl_mesh_binary(Scene *scene, const char *str) -{ - FILE *fpSTL; - Object *ob; - Mesh *me; - MVert *mvert, *vertdata; - MFace *mface, *facedata; - unsigned int numfacets = 0, i, j, vertnum; - unsigned int maxmeshsize, nummesh, lastmeshsize; - unsigned int totvert, totface; - ReportList *reports= NULL; /* XXX */ - - fpSTL= fopen(str, "rb"); - if(fpSTL==NULL) { - BKE_reportf(reports, RPT_ERROR, "Can't read file: %s.", strerror(errno)); - return; - } - - if(fseek(fpSTL, 80, SEEK_SET) != 0) { - BKE_reportf(reports, RPT_ERROR, "Failed reading file: %s.", strerror(errno)); - fclose(fpSTL); - return; - } - - if(fread(&numfacets, 4*sizeof(char), 1, fpSTL) != 1) { - if(feof(fpSTL)) - BKE_reportf(reports, RPT_ERROR, "Failed reading file: premature end of file."); - else - BKE_reportf(reports, RPT_ERROR, "Failed reading file: %s.", strerror(errno)); - fclose(fpSTL); - return; - } - if (ENDIAN_ORDER==B_ENDIAN) { - SWITCH_INT(numfacets); - } - - maxmeshsize = MESH_MAX_VERTS/3; - - nummesh = (numfacets / maxmeshsize) + 1; - lastmeshsize = numfacets % maxmeshsize; - - if (numfacets) { - for (j=0; j < nummesh; ++j) { - /* new object */ - if (j == nummesh-1) { - totface = lastmeshsize; - } - else { - totface = maxmeshsize; - } - totvert = 3 * totface; - - vertdata = MEM_callocN(totvert*sizeof(MVert), "mverts"); - facedata = MEM_callocN(totface*sizeof(MFace), "mface"); - - vertnum = 0; - mvert= vertdata; - mface = facedata; - for (i=0; i < totface; i++) { - fseek(fpSTL, 12, SEEK_CUR); /* skip the face normal */ - READSTLVERT; - mvert++; - READSTLVERT; - mvert++; - READSTLVERT; - mvert++; - - mface->v1 = vertnum++; - mface->v2 = vertnum++; - mface->v3 = vertnum++; - mface++; - - fseek(fpSTL, 2, SEEK_CUR); - } - - ob= add_object(scene, OB_MESH); - me= ob->data; - me->totvert = totvert; - me->totface = totface; - me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, - vertdata, totvert); - me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, - facedata, totface); - - mesh_add_normals_flags(me); - make_edges(me, 0); - } - //XXX waitcursor(1); - } - fclose(fpSTL); - -} -#undef READSTLVERT - -#define STLALLOCERROR { \ - char error_msg[255]; \ - fclose(fpSTL); \ - sprintf(error_msg, "Can't allocate storage for %d faces!", \ - numtenthousand * 10000); \ - return; \ -} - -#define STLBAILOUT(message) { \ - char error_msg[255]; \ - fclose(fpSTL); \ - free(vertdata); \ - sprintf(error_msg, "Line %d: %s", linenum, message); \ - return; \ -} - -#define STLREADLINE { \ - if (!fgets(buffer, 2048, fpSTL)) STLBAILOUT("Can't read line!"); \ - linenum++; \ -} - -#define STLREADVERT { \ - STLREADLINE; \ - if ( !(cp = strstr(buffer, "vertex")) && \ - !(cp = strstr(buffer, "VERTEX")) ) STLBAILOUT("Bad vertex!"); \ - vp = vertdata + 3 * totvert; \ - if (sscanf(cp + 6, "%f %f %f", vp, vp+1, vp+2) != 3) \ - STLBAILOUT("Bad vertex!"); \ - ++totvert; \ -} -static void read_stl_mesh_ascii(Scene *scene, const char *str) -{ - FILE *fpSTL; - char buffer[2048], *cp; - Object *ob; - Mesh *me; - MVert *mvert; - MFace *mface; - float *vertdata, *vp; - unsigned int numtenthousand, linenum; - unsigned int i, vertnum; - unsigned int totvert, totface; - ReportList *reports= NULL; /* XXX */ - - /* ASCII stl sucks ... we don't really know how many faces there - are until the file is done, so lets allocate faces 10000 at a time */ - - fpSTL= fopen(str, "r"); - if(fpSTL==NULL) { - BKE_reportf(reports, RPT_ERROR, "Can't read file: %s.", strerror(errno)); - return; - } - - /* we'll use the standard malloc/realloc for now ... - * lets allocate enough storage to hold 10000 triangles, - * i.e. 30000 verts, i.e., 90000 floats. - */ - numtenthousand = 1; - vertdata = malloc(numtenthousand*3*30000*sizeof(float)); // uses realloc! - if (!vertdata) { STLALLOCERROR; } - - linenum = 1; - /* Get rid of the first line */ - STLREADLINE; - - totvert = 0; - totface = 0; - while(1) { - /* Read in the next line */ - STLREADLINE; - - /* lets check if this is the end of the file */ - if ( strstr(buffer, "endsolid") || strstr(buffer, "ENDSOLID") ) - break; - - /* Well, guess that wasn't the end, so lets make - * sure we have enough storage for some more faces - */ - if ( (totface) && ( (totface % 10000) == 0 ) ) { - float *vertdata_old= vertdata; - ++numtenthousand; - vertdata = realloc(vertdata, - numtenthousand*3*30000*sizeof(float)); - if (!vertdata) { - if(vertdata_old) { - free(vertdata_old); - } - STLALLOCERROR; - } - } - - /* Don't read normal, but check line for proper syntax anyway - */ - if ( !(cp = strstr(buffer, "facet")) && - !(cp = strstr(buffer, "FACET")) ) STLBAILOUT("Bad normal line!"); - if ( !(strstr(cp+5, "normal")) && - !(strstr(cp+5, "NORMAL")) ) STLBAILOUT("Bad normal line!"); - - /* Read in what should be the outer loop line - */ - STLREADLINE; - if ( !(cp = strstr(buffer, "outer")) && - !(cp = strstr(buffer, "OUTER")) ) STLBAILOUT("Bad outer loop!"); - if ( !(strstr(cp+5, "loop")) && - !(strstr(cp+5, "LOOP")) ) STLBAILOUT("Bad outer loop!"); - - /* Read in the face */ - STLREADVERT; - STLREADVERT; - STLREADVERT; - - /* Read in what should be the endloop line - */ - STLREADLINE; - if ( !strstr(buffer, "endloop") && !strstr(buffer, "ENDLOOP") ) - STLBAILOUT("Bad endloop!"); - - /* Read in what should be the endfacet line - */ - STLREADLINE; - if ( !strstr(buffer, "endfacet") && !strstr(buffer, "ENDFACET") ) - STLBAILOUT("Bad endfacet!"); - - /* Made it this far? Increment face count */ - ++totface; - } - fclose(fpSTL); - - /* OK, lets create our mesh */ - ob = add_object(scene, OB_MESH); - me = ob->data; - - me->totface = totface; - me->totvert = totvert; - me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, - NULL, totvert); - me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, - NULL, totface); - - /* Copy vert coords and create topology */ - mvert = me->mvert; - mface = me->mface; - vertnum = 0; - for (i=0; i < totface; ++i) { - memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) ); - mface->v1 = vertnum; - mvert++; - vertnum++; - - memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) ); - mface->v2 = vertnum; - mvert++; - vertnum++; - - memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) ); - mface->v3 = vertnum; - mvert++; - vertnum++; - - mface++; - } - free(vertdata); - - mesh_add_normals_flags(me); - make_edges(me, 0); - - //XXX waitcursor(1); -} - -#undef STLALLOCERROR -#undef STLBAILOUT -#undef STLREADLINE -#undef STLREADVERT - -/* ************************************************************ */ - -int BKE_read_exotic(Scene *scene, const char *name) -{ - int len; - gzFile gzfile; - char header[7]; - int retval; - - // make sure we're not trying to read a directory.... - - len= strlen(name); - if (ELEM(name[len-1], '/', '\\')) { - retval= BKE_READ_EXOTIC_FAIL_PATH; - } - else { - gzfile = gzopen(name,"rb"); - - if (gzfile == NULL) { - retval= BKE_READ_EXOTIC_FAIL_OPEN; - } - else { - len= gzread(gzfile, header, sizeof(header)); - gzclose(gzfile); - if (len == sizeof(header) && strncmp(header, "BLENDER", 7) == 0) { - retval= BKE_READ_EXOTIC_OK_BLEND; - } - else { - //XXX waitcursor(1); - if(is_dxf(name)) { - dxf_read(scene, name); - retval= BKE_READ_EXOTIC_OK_OTHER; - } - else if(is_stl(name)) { - if (is_stl_ascii(name)) - read_stl_mesh_ascii(scene, name); - else - read_stl_mesh_binary(scene, name); - retval= BKE_READ_EXOTIC_OK_OTHER; - } - else { - retval= BKE_READ_EXOTIC_FAIL_FORMAT; - } - //XXX waitcursor(0); - } - } - } - - return retval; -} - - -/* ************************ WRITE ************************** */ - -static void write_vert_stl(Object *ob, MVert *verts, int index, FILE *fpSTL) -{ - float vert[3]; - - VECCOPY(vert, verts[(index)].co); - mul_m4_v3(ob->obmat, vert); - - if (ENDIAN_ORDER==B_ENDIAN) { - SWITCH_INT(vert[0]); - SWITCH_INT(vert[1]); - SWITCH_INT(vert[2]); - } - - fwrite(vert, sizeof(float), 3, fpSTL); -} - -static int write_derivedmesh_stl(FILE *fpSTL, Object *ob, DerivedMesh *dm) -{ - MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getFaceArray(dm); - int i, numfacets = 0, totface = dm->getNumFaces(dm); - float zero[3] = {0.0f, 0.0f, 0.0f}; - - for (i=0; i<totface; i++, mface++) { - fwrite(zero, sizeof(float), 3, fpSTL); - write_vert_stl(ob, mvert, mface->v1, fpSTL); - write_vert_stl(ob, mvert, mface->v2, fpSTL); - write_vert_stl(ob, mvert, mface->v3, fpSTL); - fprintf(fpSTL, " "); - numfacets++; - - if(mface->v4) { /* quad = 2 tri's */ - fwrite(zero, sizeof(float), 3, fpSTL); - write_vert_stl(ob, mvert, mface->v1, fpSTL); - write_vert_stl(ob, mvert, mface->v3, fpSTL); - write_vert_stl(ob, mvert, mface->v4, fpSTL); - fprintf(fpSTL, " "); - numfacets++; - } - } - - return numfacets; -} - -static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob) -{ - int numfacets = 0; - DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); - - numfacets += write_derivedmesh_stl(fpSTL, ob, dm); - - dm->release(dm); - - return numfacets; -} - -void write_stl(Scene *scene, char *str) -{ - Object *ob; - Base *base; - FILE *fpSTL; - int numfacets = 0; - ReportList *reports= NULL; /* XXX */ - - /* XXX, operator needs to manage filename extension */ - - fpSTL= fopen(str, "wb"); - - if(fpSTL==NULL) { - BKE_reportf(reports, RPT_ERROR, "Can't open file: %s.", strerror(errno)); - return; - } - - //XXX waitcursor(1); - - /* The header part of the STL */ - /* First 80 characters are a title or whatever you want. - Lets make the first 32 of those spam and the rest the filename. - Those first 80 characters will be followed by 4 bytes - which will be overwritten later with an integer holding - how many facets are written (we set them to ' ' for now). - */ - fprintf(fpSTL, "Binary STL output from Blender: %-48.48s ", str); - - /* Write all selected mesh objects */ - base= scene->base.first; - while(base) { - if (base->flag & SELECT) { - ob = base->object; - if (ob->type == OB_MESH) { - if(ob->data) - numfacets += write_object_stl(fpSTL, scene, ob); - } - } - base= base->next; - } - - /* time to write the number of facets in the 4 bytes - starting at byte 81 - */ - fseek(fpSTL, 80, SEEK_SET); - - if (ENDIAN_ORDER==B_ENDIAN) { - SWITCH_INT(numfacets); - } - fwrite(&numfacets, 4*sizeof(char), 1, fpSTL); - - fclose(fpSTL); - - //XXX waitcursor(0); -} - - -static void replace_chars(char *str1, char *str2) -{ - int a= strlen(str2); - - str1[a]= 0; - while(a--) { - if(str2[a]=='.' || str2[a]==' ') str1[a]= '_'; - else str1[a]= str2[a]; - } -} - -/* ******************************* WRITE DXF ***************************** */ - -#define write_group(id,data) fprintf(fp, "%d\n%s\n", id, data) - -/* A completely wacky function to try and make good -indexed (AutoCAD index) values out of straight rgb -ones... crazy */ - -static int rgb_to_dxf_col (float rf, float gf, float bf) -{ - int r= (int) (rf*255.0f); - int g= (int) (gf*255.0f); - int b= (int) (bf*255.0f); - float h,s,v; - int ret; - - /* Grayscale value */ - if (((int)r/10)==((int)g/10) && ((int)g/10)==((int)b/10)) ret= 250+((int)r/51); - /* A nice chroma value */ - else { - rgb_to_hsv (rf,gf,bf,&h,&s,&v); - - ret= (int) (10.0f + (h*239.0f)); - CLAMP(ret,10,249); - - /* If its whitish make the index odd */ - if (s<.5 || v>.5) if(ret%2) ret++; - } - - return ret; -} - -/* And its completely wacky complement */ - -static void dxf_col_to_rgb (int cid, float *rf, float *gf, float *bf) -{ - float h, s, v; - - /* Grayscale values */ - if (cid>=250 && cid <= 255) { - *rf= *gf= *bf= (float) ((cid-250)*51)/255; - CLAMP(*rf, 0.0, 1.0); - CLAMP(*gf, 0.0, 1.0); - CLAMP(*bf, 0.0, 1.0); - - /* Pure values */ - } else if (cid<10) { - switch (cid) { - case 1: - *rf=1.0; - *gf=0.0; - *bf=0.0; - break; - case 2: - *rf=1.0; - *gf=1.0; - *bf=0.0; - break; - case 3: - *gf=1.0; - *rf=0.0; - *bf=0.0; - break; - case 4: - *rf=0.0; - *gf=1.0; - *bf=1.0; - break; - case 5: - *rf=0.0; - *gf=0.0; - *bf=1.0; - break; - case 6: - *rf=1.0; - *gf=0.0; - *bf=1.0; - break; - case 7: - default: - *rf= *gf= *bf= 1.0; - break; - } - } else { - /* Get chroma values */ - - h= (float) (cid-10)/239; - CLAMP(h, 0.0, 1.0); - - /* If its odd make it a bit whitish */ - if (cid%2) { s=.75; v= 0.25; - } else { s= 0.25; v= 0.75;} - - hsv_to_rgb (h, s, v, rf, gf, bf); - } -} - -static void write_mesh_dxf(FILE *fp, Mesh *me) -{ - Material *ma; - MVert *mvert; - MFace *mface; - int a; - char str[32]; - - replace_chars(str, me->id.name+2); - - write_group(0, "BLOCK"); - - write_group(2, str); /* The name */ - - write_group(8, "Meshes"); /* DXF Layer */ - write_group(70, "64"); /* DXF block flags */ - - write_group(10, "0.0"); /* X of base */ - write_group(20, "0.0"); /* Y of base */ - write_group(30, "0.0"); /* Z of base */ - - write_group(3, str); /* The name (again) */ - - write_group(0, "POLYLINE"); /* Start the mesh */ - write_group(66, "1"); /* Vertices follow flag */ - write_group(8,"Meshes"); /* DXF Layer */ - - if (me->totcol) { - ma= me->mat[0]; - if(ma) { - sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b)); - write_group(62, str); /* Color index */ - } - } - - write_group(70, "64"); /* Polymesh mesh flag */ - - fprintf(fp, "71\n%d\n", me->totvert); /* Total vertices */ - fprintf(fp, "72\n%d\n", me->totface); /* Total faces */ - - /* Write the vertices */ - a= me->totvert; - mvert= me->mvert; - while(a--) { - write_group(0, "VERTEX"); /* Start a new vertex */ - write_group(8, "Meshes"); /* DXF Layer */ - fprintf (fp, "10\n%f\n", mvert->co[0]); /* X cord */ - fprintf (fp, "20\n%f\n", mvert->co[1]); /* Y cord */ - fprintf (fp, "30\n%f\n", mvert->co[2]); /* Z cord */ - write_group(70, "192"); /* Polymesh vertex flag */ - - mvert++; - } - - /* Write the face entries */ - a= me->totface; - mface= me->mface; - while(a--) { - write_group(0, "VERTEX"); /* Start a new face */ - write_group(8, "Meshes"); - - /* Write a face color */ - if (me->totcol) { - ma= me->mat[(int)mface->mat_nr]; - if(ma) { - sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b)); - write_group(62, str); /* Color index */ - } - } - else write_group(62, "254"); /* Color Index */ - - /* Not sure what this really corresponds too */ - write_group(10, "0.0"); /* X of base */ - write_group(20, "0.0"); /* Y of base */ - write_group(30, "0.0"); /* Z of base */ - - write_group(70, "128"); /* Polymesh face flag */ - - if(mface->v4) { - fprintf (fp, "71\n%d\n", mface->v1+1); - fprintf (fp, "72\n%d\n", mface->v2+1); - fprintf (fp, "73\n%d\n", mface->v3+1); - fprintf (fp, "74\n%d\n", mface->v4+1); - } else { - fprintf (fp, "71\n%d\n", mface->v1+1); - fprintf (fp, "72\n%d\n", mface->v2+1); - fprintf (fp, "73\n%d\n", mface->v3+1); - } - mface++; - } - - write_group(0, "SEQEND"); - - write_group(0, "ENDBLK"); -} - -static void write_object_dxf(FILE *fp, Object *ob, int layer) -{ - ID *id; - char str[32]; - - id= ob->data; - - write_group(0, "INSERT"); /* Start an insert group */ - - sprintf(str, "%d", layer); - write_group(8, str); - - replace_chars(str, id->name+2); - write_group(2, str); - - fprintf (fp, "10\n%f\n", ob->loc[0]); /* X of base */ - fprintf (fp, "20\n%f\n", ob->loc[1]); /* Y of base */ - fprintf (fp, "30\n%f\n", ob->loc[2]); /* Z of base */ - - fprintf (fp, "41\n%f\n", ob->size[0]); /* X scale */ - fprintf (fp, "42\n%f\n", ob->size[1]); /* Y scale */ - fprintf (fp, "43\n%f\n", ob->size[2]); /* Z scale */ - - fprintf (fp, "50\n%f\n", (float) ob->rot[2]*180/M_PI); /* Can only write the Z rot */ -} - -void write_dxf(struct Scene *scene, char *str) -{ - Mesh *me; - Base *base; - FILE *fp; - - /* XXX, operator needs to handle overwrite & rename */ - - fp= fopen(str, "w"); - - if(fp==NULL) { - //XXX error("Can't write file"); - return; - } - - //XXX waitcursor(1); - - /* The header part of the DXF */ - - write_group(0, "SECTION"); - write_group(2, "HEADER"); - write_group(0, "ENDSEC"); - - /* The blocks part of the DXF */ - - write_group(0, "SECTION"); - write_group(2, "BLOCKS"); - - - /* 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; - - /* Write all the meshes */ - me= G.main->mesh.first; - while(me) { - if(me->id.flag & LIB_DOIT) { /* is the mesh used in this scene ? */ - write_mesh_dxf(fp, me); - } - me= me->id.next; - } - - write_group(0, "ENDSEC"); - - /* The entities part of the DXF */ - - write_group(0, "SECTION"); - write_group(2, "ENTITIES"); - - /* Write all the mesh objects */ - base= scene->base.first; - while(base) { - if(base->object->type== OB_MESH) { - write_object_dxf(fp, base->object, base->lay); - } - base= base->next; - } - - write_group(0, "ENDSEC"); - - /* Thats all */ - - write_group(0, "EOF"); - fclose(fp); - - //XXX waitcursor(0); -} - - -static int dxf_line= 0; -static FILE *dxf_fp= NULL; - -/* exotic.c(2863) : note C6311: c:/Program Files/Microsoft Visual - * Studio/VC98/include\ctype.h(268) : see previous definition of - * 'iswspace' */ -#define ton_iswspace(c) (c==' '||c=='\n'||c=='\t') - -static void clean_wspace (char *str) -{ - char *from, *to; - char t; - - from= str; - to=str; - - while (*from!=0) { - t= *from; - *to= t; - - if(!ton_iswspace(*from)) to++; - from++; - } - *to=0; -} - -static int all_wspace(char *str) -{ - while(*str != 0) { - if (!ton_iswspace(*str)) return 0; - str++; - } - - return 1; -} - -static int all_digits(char *str) -{ - while(*str != 0) { - if (!isdigit(*str)) return 0; - str++; - } - - return 1; -} - -static int dxf_get_layer_col(char *UNUSED(layer)) -{ - return 1; -} - -static int dxf_get_layer_num(Scene *scene, char *layer) -{ - int ret = 0; - - if (all_digits(layer) && atoi(layer)<(1<<20)) ret= atoi(layer); - if (ret == 0) ret = scene->lay; - - return ret; -} - -static void dos_clean(char *str) -{ - while (*str) { - if (*str == 0x0d) { - *str='\n'; - *(++str)= 0; - break; - } - str++; - } -} - -static void myfgets(char *str, int len, FILE *fp) -{ - char c; - - while(len>0 && (c=getc(dxf_fp)) ) { - *str= c; - str++; - len--; - /* three types of enters, \n \r and \r\n */ - if(c == '\n') break; - if(c=='\r') { - c= getc(fp); // read the linefeed from stream - if(c != 10) ungetc(c, fp); // put back, if it's not one... - break; - } - } -} - -static int read_groupf(char *str) -{ - short c; - int ret=-1; - char tmp[256]; - - strcpy(str, " "); - - while ((c=getc(dxf_fp)) && ton_iswspace(c)); - ungetc(c, dxf_fp); - if (c==EOF) return -1; - - myfgets(tmp, 255, dxf_fp); - - dos_clean(tmp); - - if(sscanf(tmp, "%d\n", &ret)!=1) return -2; - - myfgets(tmp, 255, dxf_fp); - - dos_clean(tmp); - - if (!all_wspace(tmp)) { - if (sscanf(tmp, "%s\n", str)!=1) return -2; - } - - clean_wspace(str); - dxf_line+=2; - - return ret; -} - -//XXX error() is now printf until we have a callback error -#define id_test(id) if(id<0) {char errmsg[128];fclose(dxf_fp); if(id==-1) sprintf(errmsg, "Error inputting dxf, near line %d", dxf_line); else if(id==-2) sprintf(errmsg, "Error reading dxf, near line %d", dxf_line);printf("%s", errmsg); return;} - -#define read_group(id,str) {id= read_groupf(str); id_test(id);} - -#define group_is(idtst,str) (id==idtst&&strcmp(val,str)==0) -#define group_isnt(idtst,str) (id!=idtst||strcmp(val,str)!=0) -#define id_check(idtst,str) if(group_isnt(idtst,str)) { fclose(dxf_fp); printf("Error parsing dxf, near line %d", dxf_line); return;} - -static int id; -static char val[256]; - -static short error_exit=0; -static short hasbumped=0; - -static int is_dxf(const char *str) -{ - dxf_line=0; - - dxf_fp= fopen(str, "r"); - if (dxf_fp==NULL) return 0; - - id= read_groupf(val); - if ((id==0 && strcmp(val, "SECTION")==0)||id==999) return 1; - - fclose(dxf_fp); - - return 0; -} - -/* NOTES ON THE READER */ -/* - -- - It turns out that most DXF writers like (LOVE) to - write meshes as a long string of 3DFACE entities. - This means the natural way to read a DXF file - (every entity corresponds to an object) is completely - unusable, reading in 10,000 faces each as an - object just doesn't cut it. Thus the 3DFACE - entry reader holds state, and only finalizes to - an object when a) the layer name changes, b) the - entry type changes, c) we are done reading. - - PS... I decided to do the same thing with LINES, - apparently the same thing happens sometimes as - well. - - PPS... I decided to do the same thing with everything. - Now it is all really nasty and should be rewritten. - -- - - Added circular and elliptical arcs and lwpolylines. - These are all self-contained and have the size known - in advance, and so I haven't used the held state. -- martin -*/ - -static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer) -{ - Material *ma; - - if (!me) return; - - if(ob) { - ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat"); - ob->matbits= MEM_callocN(sizeof(char)*1, "ob->matbits"); - ob->actcol= 1; - } - - me->totcol= 1; - me->mat= MEM_callocN(sizeof(void *)*1, "me->mat"); - - if (color[0]<0) { - if (strlen(layer)) dxf_col_to_rgb(dxf_get_layer_col(layer), &color[0], &color[1], &color[2]); - color[0]= color[1]= color[2]= 0.8f; - } - - ma= G.main->mat.first; - while(ma) { - if(ma->mtex[0]==NULL) { - if(color[0]==ma->r && color[1]==ma->g && color[2]==ma->b) { - me->mat[0]= ma; - ma->id.us++; - break; - } - } - ma= ma->id.next; - } - if(ma==NULL) { - ma= add_material("ext"); - me->mat[0]= ma; - ma->r= color[0]; - ma->g= color[1]; - ma->b= color[2]; - automatname(ma); - } -} - - /* General DXF vars */ -static float cent[3]={0.0, 0.0, 0.0}; -static char layname[32]=""; -static char entname[32]=""; -static float color[3]={-1.0, -1.0, -1.0}; -static float *vcenter; -static float zerovec[3]= {0.0, 0.0, 0.0}; - -#define reset_vars cent[0]= cent[1]= cent[2]=0.0; strcpy(layname, ""); color[0]= color[1]= color[2]= -1.0 - - -static void dxf_get_mesh(Scene *scene, Mesh** m, Object** o, int noob) -{ - Mesh *me = NULL; - Object *ob; - - if (!noob) { - *o = add_object(scene, OB_MESH); - ob = *o; - - if (entname[0]) new_id(&G.main->object, (ID *)ob, entname); - else if (layname[0]) new_id(&G.main->object, (ID *)ob, layname); - - if (layname[0]) ob->lay= dxf_get_layer_num(scene, layname); - else ob->lay= scene->lay; - // not nice i know... but add_object() sets active base, which needs layer setting too (ton) - scene->basact->lay= ob->lay; - - *m = ob->data; - me= *m; - - vcenter= ob->loc; - } - else { - *o = NULL; - *m = add_mesh("Mesh"); - - me = *m; - ob = *o; - - ((ID *)me)->us=0; - - if (entname[0]) new_id(&G.main->mesh, (ID *)me, entname); - else if (layname[0]) new_id(&G.main->mesh, (ID *)me, layname); - - vcenter = zerovec; - } - me->totvert=0; - me->totface=0; - me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, 0); - me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0); -} - -static void dxf_read_point(Scene *scene, int noob) { - /* Blender vars */ - Object *ob; - Mesh *me; - MVert *mvert; - - reset_vars; - - read_group(id, val); - while(id!=0) { - if (id==8) { - BLI_strncpy(layname, val, sizeof(layname)); - } else if (id==10) { - cent[0]= (float) atof(val); - } else if (id==20) { - cent[1]= (float) atof(val); - } else if (id==30) { - cent[2]= (float) atof(val); - } else if (id==60) { - /* short invisible= atoi(val); */ - } else if (id==62) { - int colorid= atoi(val); - - CLAMP(colorid, 1, 255); - dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]); - } - read_group(id, val); - } - - dxf_get_mesh(scene, &me, &ob, noob); - me->totvert= 1; - me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts"); - CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert); - - dxf_add_mat (ob, me, color, layname); - - mvert= me->mvert; - mvert->co[0]= mvert->co[1]= mvert->co[2]= 0; - - if (ob) VECCOPY(ob->loc, cent); - - hasbumped=1; -} - - /* Line state vars */ -static Object *linehold=NULL; -static Mesh *linemhold=NULL; - -static char oldllay[32]; -static short lwasline=0; /* last was face 3d? */ - -static void dxf_close_line(void) -{ - linemhold=NULL; - if (linehold==NULL) return; - - linehold=NULL; -} - -static void dxf_read_line(Scene *scene, int noob) { - /* Entity specific vars */ - float epoint[3]={0.0, 0.0, 0.0}; - short vspace=0; /* Whether or not coords are relative */ - - /* Blender vars */ - Object *ob; - Mesh *me; - MVert *mvert, *vtmp; - MFace *mface, *ftmp; - - reset_vars; - - read_group(id, val); - while(id!=0) { - if (id==8) { - BLI_strncpy(layname, val, sizeof(layname)); - } else if (id==10) { - cent[0]= (float) atof(val); - } else if (id==20) { - cent[1]= (float) atof(val); - } else if (id==30) { - cent[2]= (float) atof(val); - } else if (id==11) { - epoint[0]= (float) atof(val); - } else if (id==21) { - epoint[1]= (float) atof(val); - } else if (id==31) { - epoint[2]= (float) atof(val); - } else if (id==60) { - /* short invisible= atoi(val); */ - } else if (id==62) { - int colorid= atoi(val); - - CLAMP(colorid, 1, 255); - dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]); - } else if (id==67) { - vspace= atoi(val); - } - read_group(id, val); - } - - /* Check to see if we need to make a new object */ - - if(!lwasline || strcmp(layname, oldllay)!=0) - dxf_close_line(); - if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS) - dxf_close_line(); - - if (linemhold==NULL) { - dxf_get_mesh(scene, &me, &ob, noob); - - if(ob) VECCOPY(ob->loc, cent); - - dxf_add_mat (ob, me, color, layname); - - linehold= ob; - linemhold= me; - } else { - ob= linehold; - me= linemhold; - } - - me->totvert+= 2; - me->totface++; - - vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts"); - ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface"); - - if(me->mvert) { - memcpy(vtmp, me->mvert, (me->totvert-2)*sizeof(MVert)); - MEM_freeN(me->mvert); - } - me->mvert= CustomData_set_layer(&me->vdata, CD_MVERT, vtmp); - vtmp=NULL; - - if(me->mface) { - memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace)); - MEM_freeN(me->mface); - } - me->mface= CustomData_set_layer(&me->fdata, CD_MFACE, ftmp); - ftmp=NULL; - - mvert= &me->mvert[(me->totvert-2)]; - - sub_v3_v3v3(mvert->co, cent, vcenter); - mvert++; - if (vspace) { VECCOPY(mvert->co, epoint); - } else sub_v3_v3v3(mvert->co, epoint, vcenter); - - mface= &(((MFace*)me->mface)[me->totface-1]); - mface->v1= me->totvert-2; - mface->v2= me->totvert-1; - mface->mat_nr= 0; - - hasbumped=1; -} - - /* 2D Polyline state vars */ -static Object *p2dhold=NULL; -static Mesh *p2dmhold=NULL; -static char oldplay[32]; -static short lwasp2d=0; - -static void dxf_close_2dpoly(void) -{ - p2dmhold= NULL; - if (p2dhold==NULL) return; - - p2dhold=NULL; -} - -static void dxf_read_ellipse(Scene *scene, int noob) -{ - - /* - * The Parameter option of the ELLIPSE command uses the following equation to define an elliptical arc. - * - * p(u)=c+a*cos(u)+b*sin(u) - * - * The variables a, b, c are determined when you select the endpoints for the - * first axis and the distance for the second axis. a is the negative of 1/2 - * of the major axis length, b is the negative of 1/2 the minor axis length, - * and c is the center point (2-D) of the ellipse. - * - * Because this is actually a vector equation and the variable c is actually - * a point with X and Y values, it really should be written as: - * - * p(u)=(Cx+a*cos(u))*i+(Cy+b*sin(u))*j - * - * where - * - * Cx is the X value of the point c - * Cy is the Y value of the point c - * a is -(1/2 of the major axis length) - * b is -(1/2 of the minor axis length) - * i and j represent unit vectors in the X and Y directions - * - * http://astronomy.swin.edu.au/~pbourke/geomformats/dxf2000/ellipse_command39s_parameter_option_dxf_06.htm - * (reproduced with permission) - * - * NOTE: The start and end angles ('parameters') are in radians, whereas those for the circular arc are - * in degrees. The 'sense' of u appears to be determined by the extrusion direction (see more detailed comment - * in the code) - * - * TODO: The code is specific to ellipses in the x-y plane right now. - * - */ - - /* Entity specific vars */ - float epoint[3]={0.0, 0.0, 0.0}; - float center[3]={0.0, 0.0, 0.0}; - float extrusion[3]={0.0, 0.0, 1.0}; - float axis_endpoint[3] = {0.0, 0.0, 0.0}; /* major axis endpoint */ - short vspace=0; /* Whether or not coords are relative */ - float a, b, x, y, z; - float phid = 0.0f, phi = 0.0f, theta = 0.0f; - float start_angle = 0.0f; - float end_angle = 2*M_PI; - float axis_ratio = 1.0f; - float temp; - int v, tot; - int isArc=0; - /* Blender vars */ - Object *ob; - Mesh *me; - MVert *mvert; - MFace *mface; - - reset_vars; - read_group(id, val); - while(id!=0) { - if (id==8) { - BLI_strncpy(layname, val, sizeof(layname)); - } else if (id==10) { - center[0]= (float) atof(val); - } else if (id==20) { - center[1]= (float) atof(val); - } else if (id==30) { - center[2]= (float) atof(val); - } else if (id==11) { - axis_endpoint[0]= (float) atof(val); - } else if (id==21) { - axis_endpoint[1]= (float) atof(val); - } else if (id==31) { - axis_endpoint[2]= (float) atof(val); - } else if (id==40) { - axis_ratio = (float) atof(val); - } else if (id==41) { - printf("dxf: start = %f", atof(val) * 180/M_PI); - start_angle = -atof(val) + M_PI_2; - } else if (id==42) { - printf("dxf: end = %f", atof(val) * 180/M_PI); - end_angle = -atof(val) + M_PI_2; - } else if (id==62) { - int colorid= atoi(val); - CLAMP(colorid, 1, 255); - dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]); - } else if (id==67) { - vspace= atoi(val); - } else if (id==100) { - isArc = 1; - } else if (id==210) { - extrusion[0] = atof(val); - } else if (id==220) { - extrusion[1] = atof(val); - } else if (id==230) { - extrusion[2] = atof(val); - } - read_group(id, val); - } - - if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line(); - if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS) - dxf_close_line(); - - /* The 'extrusion direction' seems akin to a face normal, - * insofar as it determines the direction of increasing phi. - * This is again x-y plane specific; it should be fixed at - * some point. */ - - if (extrusion[2] < 0) { - temp = start_angle; - start_angle = M_PI - end_angle; - end_angle = M_PI - temp; - } - - if(end_angle > start_angle) - end_angle -= 2 * M_PI; - - phi = start_angle; - - x = axis_endpoint[0]; - y = axis_endpoint[1]; - z = axis_endpoint[2]; - a = sqrt(x*x + y*y + z*z); - b = a * axis_ratio; - - theta = atan2(y, x); - - x = a * sin(phi); - y = b * cos(phi); - -#ifndef DEBUG_CENTER - epoint[0] = center[0] + x*cos(theta) - y*sin(theta); - epoint[1] = center[1] + x*sin(theta) + y*cos(theta); - epoint[2] = center[2]; - - - cent[0]= epoint[0]; - cent[1]= epoint[1]; - cent[2]= epoint[2]; -#else - cent[0]= center[0]; - cent[1]= center[1]; - cent[2]= center[2]; -#endif - - dxf_get_mesh(scene, &me, &ob, noob); - strcpy(oldllay, layname); - if(ob) VECCOPY(ob->loc, cent); - dxf_add_mat (ob, me, color, layname); - - tot = 32; /* # of line segments to divide the arc into */ - - phid = (end_angle - start_angle)/tot; - - me->totvert += tot+1; - me->totface += tot+1; - - me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts"); - me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface"); - - CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert); - CustomData_set_layer(&me->fdata, CD_MFACE, me->mface); - - printf("vertex and face buffers allocated\n"); - - for(v = 0; v <= tot; v++) { - - x = a * sin(phi); - y = b * cos(phi); - epoint[0] = center[0] + x*cos(theta) - y*sin(theta); - epoint[1] = center[1] + x*sin(theta) + y*cos(theta); - epoint[2] = center[2]; - - mvert= &me->mvert[v]; - - if (vspace) { - VECCOPY(mvert->co, epoint); - } else { - sub_v3_v3v3(mvert->co, epoint, vcenter); - } - - if (v > 0) { - mface= &(((MFace*)me->mface)[v-1]); - mface->v1 = v-1; - mface->v2 = v; - mface->mat_nr = 0; - } - - hasbumped = 1; - - VECCOPY(cent, epoint); - phi+=phid; - } -} - -static void dxf_read_arc(Scene *scene, int noob) -{ - /* Entity specific vars */ - float epoint[3]={0.0, 0.0, 0.0}; - float center[3]={0.0, 0.0, 0.0}; - float extrusion[3]={0.0, 0.0, 1.0}; - short vspace=0; /* Whether or not coords are relative */ - float dia = 0.0f; - float phid = 0.0f, phi = 0.0f; - float start_angle = 0.0f; - float end_angle = 2*M_PI; - float temp; - int v, tot = 32; - int isArc=0; - /* Blender vars */ - Object *ob; - Mesh *me; - MVert *mvert; - MFace *mface; - - reset_vars; - read_group(id, val); - while(id!=0) { - if (id==8) { - BLI_strncpy(layname, val, sizeof(layname)); - } else if (id==10) { - center[0]= (float) atof(val); - } else if (id==20) { - center[1]= (float) atof(val); - } else if (id==30) { - center[2]= (float) atof(val); - } else if (id==40) { - dia = (float) atof(val); - } else if (id==62) { - int colorid= atoi(val); - - CLAMP(colorid, 1, 255); - dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]); - } else if (id==67) { - vspace= atoi(val); - } else if (id==100) { - isArc = 1; - } else if (id==50) { - start_angle = (90 - atoi(val)) * M_PI/180.0; - } else if (id==51) { - end_angle = (90 - atoi(val)) * M_PI/180.0; - } else if (id==210) { - extrusion[0] = atof(val); - } else if (id==220) { - extrusion[1] = atof(val); - } else if (id==230) { - extrusion[2] = atof(val); - } - read_group(id, val); - } - - if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line(); - if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS) - dxf_close_line(); - - /* Same xy-plane-specific extrusion direction code as in read_ellipse - * (read_arc and read_ellipse should ideally be rewritten to share code) - */ - - if (extrusion[2] < 0) { - temp = start_angle; - start_angle = M_PI - end_angle; - end_angle = M_PI - temp; - } - - phi = start_angle; - if(end_angle > start_angle) - end_angle -= 2 * M_PI; - - cent[0]= center[0]+dia*sin(phi); - cent[1]= center[1]+dia*cos(phi); - cent[2]= center[2]; - - dxf_get_mesh(scene, &me, &ob, noob); - BLI_strncpy(oldllay, layname, sizeof(oldllay)); - if(ob) VECCOPY(ob->loc, cent); - dxf_add_mat (ob, me, color, layname); - - tot = 32; /* # of line segments to divide the arc into */ - phid = (end_angle - start_angle)/tot; /* fix so that arcs have the same 'resolution' as circles? */ - - me->totvert += tot+1; - me->totface += tot+1; - - me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts"); - me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface"); - - CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert); - CustomData_set_layer(&me->fdata, CD_MFACE, me->mface); - - for(v = 0; v <= tot; v++) { - - epoint[0]= center[0]+dia*sin(phi); - epoint[1]= center[1]+dia*cos(phi); - epoint[2]= center[2]; - - mvert= &me->mvert[v]; - - if (vspace) { - VECCOPY(mvert->co, epoint); - } else { - sub_v3_v3v3(mvert->co, epoint, vcenter); - } - - if (v > 0) { - mface= &(((MFace*)me->mface)[v-1]); - mface->v1 = v-1; - mface->v2 = v; - mface->mat_nr = 0; - } - - hasbumped=1; - - VECCOPY(cent, epoint); - phi+=phid; - } -} - -static void dxf_read_polyline(Scene *scene, int noob) { - /* Entity specific vars */ - short vspace=0; /* Whether or not coords are relative */ - int flag=0; - int vflags=0; - int vids[4]; - int nverts; - - /* Blender vars */ - Object *ob; - Mesh *me; - float vert[3] = {0}; - - MVert *mvert, *vtmp; - MFace *mface, *ftmp; - - reset_vars; - - read_group(id, val); - while(id!=0) { - if (id==8) { - BLI_strncpy(layname, val, sizeof(layname)); - } else if (id==10) { - cent[0]= (float) atof(val); - } else if (id==20) { - cent[1]= (float) atof(val); - } else if (id==30) { - cent[2]= (float) atof(val); - } else if (id==60) { - /* short invisible= atoi(val); */ - } else if (id==62) { - int colorid= atoi(val); - - CLAMP(colorid, 1, 255); - dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]); - } else if (id==67) { - vspace= atoi(val); - } else if (id==70) { - flag= atoi(val); - } - read_group(id, val); - } - - if (flag & 9) { // 1= closed curve, 8= 3d curve - if(!lwasp2d || strcmp(layname, oldplay)!=0) dxf_close_2dpoly(); - if(p2dmhold != NULL && p2dmhold->totvert>MESH_MAX_VERTS) - dxf_close_2dpoly(); - - if (p2dmhold==NULL) { - dxf_get_mesh(scene, &me, &ob, noob); - - strcpy(oldplay, layname); - - if(ob) VECCOPY(ob->loc, cent); - - dxf_add_mat (ob, me, color, layname); - - p2dhold= ob; - p2dmhold= me; - } - else { - ob= p2dhold; - me= p2dmhold; - } - - nverts=0; - while (group_is(0, "VERTEX")) { - read_group(id, val); - while(id!=0) { - if (id==10) { - vert[0]= (float) atof(val); - } else if (id==20) { - vert[1]= (float) atof(val); - } else if (id==30) { - vert[2]= (float) atof(val); - } - read_group(id, val); - } - nverts++; - me->totvert++; - - vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts"); - - if (me->mvert) { - memcpy (vtmp, me->mvert, (me->totvert-1)*sizeof(MVert)); - MEM_freeN(me->mvert); - } - me->mvert= CustomData_set_layer(&me->vdata, CD_MVERT, vtmp); - vtmp= NULL; - - mvert= &me->mvert[me->totvert-1]; - - if (vspace) { VECCOPY(mvert->co, vert); - } else sub_v3_v3v3(mvert->co, vert, vcenter); - } - - /* make edges */ - if(nverts>1) { - int a, oldtotface; - - oldtotface= me->totface; - me->totface+= nverts-1; - - ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface"); - - if(me->mface) { - memcpy(ftmp, me->mface, oldtotface*sizeof(MFace)); - MEM_freeN(me->mface); - } - me->mface= CustomData_set_layer(&me->fdata, CD_MFACE, ftmp); - ftmp=NULL; - - mface= me->mface; - mface+= oldtotface; - - for(a=1; a<nverts; a++, mface++) { - mface->v1= (me->totvert-nverts)+a-1; - mface->v2= (me->totvert-nverts)+a; - mface->mat_nr= 0; - } - } - - lwasp2d=1; - } - else if (flag&64) { - dxf_get_mesh(scene, &me, &ob, noob); - - if(ob) VECCOPY(ob->loc, cent); - - dxf_add_mat (ob, me, color, layname); - - while (group_is(0, "VERTEX")) { - vflags= 0; - vids[0]= vids[1]= vids[2]= vids[3]= 0; - - vflags=0; - read_group(id, val); - while(id!=0) { - if(id==8) { - ; /* Layer def, skip */ - } else if (id==10) { - vert[0]= (float) atof(val); - } else if (id==20) { - vert[1]= (float) atof(val); - } else if (id==30) { - vert[2]= (float) atof(val); - } else if (id==70) { - vflags= atoi(val); - } else if (id==71) { - vids[0]= abs(atoi(val)); - } else if (id==72) { - vids[1]= abs(atoi(val)); - } else if (id==73) { - vids[2]= abs(atoi(val)); - } else if (id==74) { - vids[3]= abs(atoi(val)); - } - read_group(id, val); - } - - if (vflags & 128 && vflags & 64) { - me->totvert++; - - /* If we are nearing the limit scan to the next entry */ - if(me->totvert > MESH_MAX_VERTS) - while(group_isnt(0, "SEQEND")) read_group(id, val); - - vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts"); - - if(me->mvert) { - memcpy(vtmp, me->mvert, (me->totvert-1)*sizeof(MVert)); - MEM_freeN(me->mvert); - } - me->mvert= CustomData_set_layer(&me->vdata, CD_MVERT, vtmp); - vtmp=NULL; - - mvert= &me->mvert[(me->totvert-1)]; - - if (vspace) { VECCOPY(mvert->co, vert); - } else sub_v3_v3v3(mvert->co, vert, vcenter); - - } else if (vflags & 128) { - if(vids[2]==0) { - //XXX error("(PL) Error parsing dxf, not enough vertices near line %d", dxf_line); - - error_exit=1; - fclose(dxf_fp); - return; - } - - me->totface++; - - ftmp= MEM_callocN(me->totface*sizeof(MFace), "mfaces"); - - if(me->mface) { - memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace)); - MEM_freeN(me->mface); - } - me->mface= CustomData_set_layer(&me->fdata, CD_MFACE, ftmp); - ftmp=NULL; - - mface= &(((MFace*)me->mface)[me->totface-1]); - mface->v1= vids[0]-1; - mface->v2= vids[1]-1; - mface->v3= vids[2]-1; - - if(vids[3] && vids[3]!=vids[0]) { - mface->v4= vids[3]-1; - test_index_face(mface, NULL, 0, 4); - } - else test_index_face(mface, NULL, 0, 3); - - mface->mat_nr= 0; - - } else { - //XXX error("Error parsing dxf, unknown polyline information near %d", dxf_line); - - error_exit=1; - fclose(dxf_fp); - return; - } - - } - } -} - -static void dxf_read_lwpolyline(Scene *scene, int noob) { - /* Entity specific vars */ - short vspace=0; /* Whether or not coords are relative */ - int flag=0; - int nverts=0; - int v; - - /* Blender vars */ - Object *ob; - Mesh *me; - float vert[3] = {0}; - - MVert *mvert; - MFace *mface; - - reset_vars; - - id = -1; - - /* block structure is - * {...} - * 90 => nverts - * 70 => flags - * nverts.times { 10 => x, 20 => y } - */ - while(id!=70) { - read_group(id, val); - if (id==8) { - BLI_strncpy(layname, val, sizeof(layname)); - } else if (id==38) { - vert[2]= (float) atof(val); - } else if (id==60) { - /* short invisible= atoi(val); */ - } else if (id==62) { - int colorid= atoi(val); - - CLAMP(colorid, 1, 255); - dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]); - } else if (id==67) { - vspace= atoi(val); - } else if (id==70) { - flag= atoi(val); - } else if (id==90) { - nverts= atoi(val); - } - } - printf("nverts %d\n", nverts); - if (nverts == 0) - return; - - dxf_get_mesh(scene, &me, &ob, noob); - strcpy(oldllay, layname); - if(ob) VECCOPY(ob->loc, cent); - dxf_add_mat (ob, me, color, layname); - - me->totvert += nverts; - me->totface += nverts; - - me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts"); - me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface"); - - CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert); - CustomData_set_layer(&me->fdata, CD_MFACE, me->mface); - - for (v = 0; v < nverts; v++) { - read_group(id,val); - if (id == 10) { - vert[0]= (float) atof(val); - } else { - //XXX error("Error parsing dxf, expected (10, <x>) at line %d", dxf_line); - } - - read_group(id,val); - if (id == 20) { - vert[1]= (float) atof(val); - } else { - //XXX error("Error parsing dxf, expected (20, <y>) at line %d", dxf_line); - } - - mvert = &me->mvert[v]; - - if (vspace) { - VECCOPY(mvert->co, vert); - } else { - sub_v3_v3v3(mvert->co, vert, vcenter); - } - - if (v > 0) { - mface= &(((MFace*)me->mface)[v-1]); - mface->v1 = v-1; - mface->v2 = v; - mface->mat_nr = 0; - } - } - - /* flag & 1 -> closed polyline - * TODO: give the polyline actual 2D faces if it is closed */ - - if (flag&1) { - if(me->mface) { - mface= &(((MFace*)me->mface)[nverts - 1]); - mface->v1 = nverts-1; - mface->v2 = 0; - mface->mat_nr = 0; - } - } -} - - - /* 3D Face state vars */ -static Object *f3dhold=NULL; -static Mesh *f3dmhold=NULL; -static char oldflay[32]; -static short lwasf3d=0; /* last was face 3d? */ - -/* how can this function do anything useful (ton)? */ -static void dxf_close_3dface(void) -{ - f3dmhold= NULL; - if (f3dhold==NULL) return; - - f3dhold=NULL; -} - -static void dxf_read_3dface(Scene *scene, int noob) -{ - /* Entity specific vars */ - float vert2[3]={0.0, 0.0, 0.0}; - float vert3[3]={0.0, 0.0, 0.0}; - float vert4[3]={0.0, 0.0, 0.0}; - short vspace=0; - - int nverts=0; - - /* Blender vars */ - Object *ob; - Mesh *me; - MVert *mvert, *vtmp; - MFace *mface, *ftmp; - - reset_vars; - - read_group(id, val); - while(id!=0) { - if (id==8) { - BLI_strncpy(layname, val, sizeof(layname)); - - /* First vert/origin */ - } else if (id==10) { - cent[0]= (float) atof(val); - if (nverts<1)nverts++; - } else if (id==20) { - cent[1]= (float) atof(val); - if (nverts<1)nverts++; - } else if (id==30) { - cent[2]= (float) atof(val); - if (nverts<1)nverts++; - - /* Second vert */ - } else if (id==11) { - vert2[0]= (float) atof(val); - if (nverts<2)nverts++; - } else if (id==21) { - vert2[1]= (float) atof(val); - if (nverts<2)nverts++; - } else if (id==31) { - vert2[2]= (float) atof(val); - if (nverts<2)nverts++; - - /* Third vert */ - } else if (id==12) { - vert3[0]= (float) atof(val); - if (nverts<3)nverts++; - } else if (id==22) { - vert3[1]= (float) atof(val); - if (nverts<3)nverts++; - } else if (id==32) { - vert3[2]= (float) atof(val); - if (nverts<3)nverts++; - - /* Fourth vert */ - } else if (id==13) { - vert4[0]= (float) atof(val); - if (nverts<4)nverts++; - } else if (id==23) { - vert4[1]= (float) atof(val); - if (nverts<4)nverts++; - } else if (id==33) { - vert4[2]= (float) atof(val); - if (nverts<4)nverts++; - - /* Other */ - } else if (id==60) { - /* short invisible= atoi(val); */ - } else if (id==62) { - int colorid= atoi(val); - - CLAMP(colorid, 1, 255); - dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]); - } else if (id==67) { - vspace= atoi(val); - } - read_group(id, val); - } - - /* Check to see if we need to make a new object */ - - if(!lwasf3d || strcmp(layname, oldflay)!=0) dxf_close_3dface(); - if(f3dmhold != NULL && f3dmhold->totvert>MESH_MAX_VERTS) - dxf_close_3dface(); - - if(nverts<3) { - //XXX error("(3DF) Error parsing dxf, not enough vertices near line %d", dxf_line); - - error_exit=1; - fclose(dxf_fp); - return; - } - - if (f3dmhold==NULL) { - dxf_get_mesh(scene, &me, &ob, noob); - - strcpy(oldflay, layname); - - if(ob) VECCOPY(ob->loc, cent); - - dxf_add_mat (ob, me, color, layname); - - f3dhold= ob; - f3dmhold= me; - } else { - ob= f3dhold; - me= f3dmhold; - } - - me->totvert+= nverts; - me->totface++; - - vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts"); - ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface"); - - if(me->mvert) { - memcpy(vtmp, me->mvert, (me->totvert-nverts)*sizeof(MVert)); - MEM_freeN(me->mvert); - } - me->mvert= CustomData_set_layer(&me->vdata, CD_MVERT, vtmp); - vtmp=NULL; - - if(me->mface) { - memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace)); - MEM_freeN(me->mface); - } - me->mface= CustomData_set_layer(&me->fdata, CD_MFACE, ftmp); - ftmp=NULL; - - mvert= &me->mvert[(me->totvert-nverts)]; - sub_v3_v3v3(mvert->co, cent, vcenter); - - mvert++; - if (vspace) { VECCOPY(mvert->co, vert2); - } else sub_v3_v3v3(mvert->co, vert2, vcenter); - - mvert++; - if (vspace) { VECCOPY(mvert->co, vert3); - } else sub_v3_v3v3(mvert->co, vert3, vcenter); - - if (nverts==4) { - mvert++; - if (vspace) { VECCOPY(mvert->co, vert4); - } else sub_v3_v3v3(mvert->co, vert4, vcenter); - } - - mface= &(((MFace*)me->mface)[me->totface-1]); - mface->v1= (me->totvert-nverts)+0; - mface->v2= (me->totvert-nverts)+1; - mface->v3= (me->totvert-nverts)+2; - - if (nverts==4) - mface->v4= (me->totvert-nverts)+3; - - mface->mat_nr= 0; - - test_index_face(mface, NULL, 0, nverts); - - hasbumped=1; -} - -static void dxf_read(Scene *scene, const char *filename) -{ - Mesh *lastMe = G.main->mesh.last; - - /* clear ugly global variables, that can hang because on error the code - below returns... tsk (ton) */ - dxf_line=0; - dxf_close_3dface(); - dxf_close_2dpoly(); - dxf_close_line(); - - dxf_fp= fopen(filename, "r"); - if (dxf_fp==NULL) return; - - while (1) { - read_group(id, val); - if (group_is(0, "EOF")) break; - - if (id==999) continue; - id_check(0, "SECTION"); - - read_group(id, val); - if (group_is(2, "HEADER")) { - } else if (group_is(2, "TABLES")) { - } else if (group_is(2, "OBJECTS")) { - } else if (group_is(2, "CLASSES")) { - } else if (group_is(2, "BLOCKS")) { - while(1) { - read_group(id, val); - if (group_is(0, "BLOCK")) { - while(group_isnt(0, "ENDBLK")) { - read_group(id, val); - - if(id==2) { - BLI_strncpy(entname, val, sizeof(entname)); - } else if (id==3) { - /* Now the object def should follow */ - if(strlen(entname)==0) { - //XXX error("Error parsing dxf, no mesh name near %d", dxf_line); - fclose(dxf_fp); - return; - } - - /* Now the object def should follow */ - while(group_isnt(0, "ENDBLK")) { - read_group(id, val); - - if(group_is(0, "POLYLINE")) { - dxf_read_polyline(scene, 1); - if(error_exit) return; - lwasf3d=0; - lwasline=0; - - while(group_isnt(0, "SEQEND")) read_group(id, val); - - } else if(group_is(0, "LWPOLYLINE")) { - dxf_read_lwpolyline(scene, 1); - if(error_exit) return; - lwasf3d=0; - lwasline=0; - - while(group_isnt(0, "SEQEND")) read_group(id, val); - } else if(group_is(0, "ATTRIB")) { - while(group_isnt(0, "SEQEND")) read_group(id, val); - lwasf3d=0; - lwasp2d=0; - lwasline=0; - } else if(group_is(0, "POINT")) { - dxf_read_point(scene, 1); - if(error_exit) return; - lwasf3d=0; - lwasp2d=0; - lwasline=0; - } else if(group_is(0, "LINE")) { - dxf_read_line(scene, 1); - if(error_exit) return; - lwasline=1; - lwasp2d=0; - lwasf3d=0; - } else if(group_is(0, "3DFACE")) { - dxf_read_3dface(scene, 1); - if(error_exit) return; - lwasf3d=1; - lwasp2d=0; - lwasline=0; - } else if (group_is(0, "CIRCLE")) { - dxf_read_arc(scene, 1); - } else if (group_is(0, "ELLIPSE")) { - dxf_read_ellipse(scene, 1); - } else if (group_is(0, "ENDBLK")) { - break; - } - } - } else if (group_is(0, "ENDBLK")) { - break; - } - } - while(id!=0) read_group(id, val); - - } else if(group_is(0, "ENDSEC")) { - break; - } - } - } else if (group_is(2, "ENTITIES")) { - while(group_isnt(0, "ENDSEC")) { - char obname[32]=""; - char layname[32]=""; - float cent[3]={0.0, 0.0, 0.0}; - float obsize[3]={1.0, 1.0, 1.0}; - float obrot[3]={0.0, 0.0, 0.0}; - - if(!hasbumped) read_group(id, val); - hasbumped=0; - if (group_is(0, "INSERT")) { - Base *base; - Object *ob; - void *obdata; - - read_group(id, val); - - while(id!=0) { - if(id==2) { - BLI_strncpy(obname, val, sizeof(obname)); - } else if (id==8) { - BLI_strncpy(layname, val, sizeof(layname)); - } else if (id==10) { - cent[0]= (float) atof(val); - } else if (id==20) { - cent[1]= (float) atof(val); - } else if (id==30) { - cent[2]= (float) atof(val); - } else if (id==41) { - obsize[0]= (float) atof(val); - } else if (id==42) { - obsize[1]= (float) atof(val); - } else if (id==43) { - obsize[2]= (float) atof(val); - } else if (id==50) { - obrot[2]= (float) (atof(val)*M_PI/180.0); - } else if (id==60) { - /* short invisible= atoi(val); */ - } - - read_group(id, val); - - } - - if(strlen(obname)==0) { - //XXX error("Error parsing dxf, no object name near %d", dxf_line); - fclose(dxf_fp); - return; - } - - obdata= find_id("ME", obname); - - if (obdata) { - ob= alloc_libblock(&G.main->object, ID_OB, obname); - - ob->type= OB_MESH; - - ob->dt= OB_TEXTURE; - - ob->trackflag= OB_POSY; - ob->upflag= OB_POSZ; - - ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT; - - ob->dupon= 1; ob->dupoff= 0; - ob->dupsta= 1; ob->dupend= 100; - ob->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; /* needed because of weird way of adding libdata directly */ - - ob->data= obdata; - ((ID*)ob->data)->us++; - - VECCOPY(ob->loc, cent); - VECCOPY(ob->size, obsize); - VECCOPY(ob->rot, obrot); - - ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat"); - ob->matbits= MEM_callocN(sizeof(char)*1, "ob->matbits"); - ob->totcol= (unsigned char) ((Mesh*)ob->data)->totcol; - ob->actcol= 1; - - /* note: materials are either linked to mesh or object, if both then - you have to increase user counts. below line is not needed. - I leave it commented out here as warning (ton) */ - //for (i=0; i<ob->totcol; i++) ob->mat[i]= ((Mesh*)ob->data)->mat[i]; - - if (layname[0]) ob->lay= dxf_get_layer_num(scene, layname); - else ob->lay= scene->lay; - - /* link to scene */ - base= MEM_callocN( sizeof(Base), "add_base"); - BLI_addhead(&scene->base, base); - - base->lay= ob->lay; - - base->object= ob; - } - - hasbumped=1; - - lwasf3d=0; - lwasp2d=0; - lwasline=0; - } else if(group_is(0, "POLYLINE")) { - dxf_read_polyline(scene, 0); - if(error_exit) return; - lwasf3d=0; - lwasline=0; - - while(group_isnt(0, "SEQEND")) read_group(id, val); - - } else if(group_is(0, "LWPOLYLINE")) { - dxf_read_lwpolyline(scene, 0); - if(error_exit) return; - lwasf3d=0; - lwasline=0; - //while(group_isnt(0, "SEQEND")) read_group(id, val); - - } else if(group_is(0, "ATTRIB")) { - while(group_isnt(0, "SEQEND")) read_group(id, val); - lwasf3d=0; - lwasp2d=0; - lwasline=0; - } else if(group_is(0, "POINT")) { - dxf_read_point(scene, 0); - if(error_exit) return; - lwasf3d=0; - lwasp2d=0; - lwasline=0; - } else if(group_is(0, "LINE")) { - dxf_read_line(scene, 0); - if(error_exit) return; - lwasline=1; - lwasp2d=0; - lwasf3d=0; - } else if(group_is(0, "3DFACE")) { - dxf_read_3dface(scene, 0); - if(error_exit) return; - lwasline=0; - lwasp2d=0; - lwasf3d=1; - } else if (group_is(0, "CIRCLE") || group_is(0, "ARC")) { - dxf_read_arc(scene, 0); - } else if (group_is(0, "ELLIPSE")) { - dxf_read_ellipse(scene, 0); - } else if(group_is(0, "ENDSEC")) { - break; - } - } - } - - while(group_isnt(0, "ENDSEC")) read_group(id, val); - } - id_check(0, "EOF"); - - fclose (dxf_fp); - - /* Close any remaining state held stuff */ - dxf_close_3dface(); - dxf_close_2dpoly(); - dxf_close_line(); - - if (lastMe) { - lastMe = lastMe->id.next; - } else { - lastMe = G.main->mesh.first; - } - for (; lastMe; lastMe=lastMe->id.next) { - mesh_add_normals_flags(lastMe); - make_edges(lastMe, 0); - } -} diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 28559812f4d..22d19c5484f 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -675,8 +675,10 @@ void BKE_image_all_free_anim_ibufs(int cfra) int BKE_imtype_to_ftype(int imtype) { - if(imtype==0) + if(imtype==R_TARGA) return TGA; + else if(imtype==R_RAWTGA) + return RAWTGA; else if(imtype== R_IRIS) return IMAGIC; #ifdef WITH_HDR @@ -703,10 +705,6 @@ int BKE_imtype_to_ftype(int imtype) else if (imtype==R_DPX) return DPX; #endif - else if (imtype==R_TARGA) - return TGA; - else if(imtype==R_RAWTGA) - return RAWTGA; #ifdef WITH_OPENJPEG else if(imtype==R_JP2) return JP2; @@ -1013,7 +1011,10 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec int x, y, y_ofs; float h_fixed; const int mono= blf_mono_font_render; // XXX - + +#define BUFF_MARGIN_X 2 +#define BUFF_MARGIN_Y 1 + if (!rect && !rectf) return; @@ -1028,24 +1029,11 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_buffer(mono, rectf, rect, width, height, channels); BLF_buffer_col(mono, scene->r.fg_stamp[0], scene->r.fg_stamp[1], scene->r.fg_stamp[2], 1.0); - pad= BLF_width(mono, "--"); + pad= BLF_width_max(mono); /* use 'h_fixed' rather then 'h', aligns better */ - // BLF_width_and_height(mono, "^|/_AgPpJjlYy", &w, &h_fixed); - { - rctf box; - float baseline; - BLF_boundbox(mono, "^|/_AgPpJjlYy", &box); - h_fixed= box.ymax - box.ymin; - - /* crude way to get the decent line from A->j*/ - BLF_boundbox(mono, "A", &box); - baseline= box.ymin; - BLF_boundbox(mono, "j", &box); - y_ofs = (int)(baseline - box.ymin); - if(y_ofs < 0) y_ofs= 0; /* should never happen */ - y_ofs++; - } + h_fixed= BLF_height_max(mono); + y_ofs = -BLF_descender(mono); x= 0; y= height; @@ -1056,14 +1044,14 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* also a little of space to the background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y-3, w+3, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-BUFF_MARGIN_X, y-BUFF_MARGIN_Y, w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); /* and draw the text. */ BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.file); /* the extra pixel for background. */ - y -= 4; + y -= BUFF_MARGIN_Y * 2; } /* Top left corner, below File */ @@ -1072,13 +1060,13 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, 0, y-3, w+3, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, 0, y-BUFF_MARGIN_Y, w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.note); /* the extra pixel for background. */ - y -= 4; + y -= BUFF_MARGIN_Y * 2; } /* Top left corner, below File (or Note) */ @@ -1087,13 +1075,13 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, 0, y-3, w+3, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, 0, y-BUFF_MARGIN_Y, w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.date); /* the extra pixel for background. */ - y -= 4; + y -= BUFF_MARGIN_Y * 2; } /* Top left corner, below File, Date or Note */ @@ -1102,7 +1090,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, 0, y-3, w+3, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, 0, y-BUFF_MARGIN_Y, w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.rendertime); @@ -1116,7 +1104,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.marker, &w, &h); h= h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, w+2, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-BUFF_MARGIN_X, y-BUFF_MARGIN_Y, w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1131,7 +1119,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.time, &w, &h); h= h_fixed; /* extra space for background */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+2, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-BUFF_MARGIN_X, y, x+w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1145,7 +1133,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.frame, &w, &h); h= h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+2, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-BUFF_MARGIN_X, y-BUFF_MARGIN_Y, x+w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1159,7 +1147,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.camera, &w, &h); h= h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+2, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-BUFF_MARGIN_X, y-BUFF_MARGIN_Y, x+w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.camera); @@ -1171,7 +1159,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.cameralens, &w, &h); h= h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+2, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-BUFF_MARGIN_X, y-BUFF_MARGIN_Y, x+w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.cameralens); } @@ -1183,7 +1171,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec x= width - w - 2; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+3, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-BUFF_MARGIN_X, y-BUFF_MARGIN_Y, x+w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y+y_ofs, 0.0); @@ -1198,7 +1186,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y= height - h; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y-3, x+w+pad, y+h+2); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-BUFF_MARGIN_X, y-BUFF_MARGIN_Y, x+w+BUFF_MARGIN_X, y+h+BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.strip); @@ -1206,6 +1194,9 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* cleanup the buffer. */ BLF_buffer(mono, NULL, NULL, 0, 0, 0); + +#undef BUFF_MARGIN_X +#undef BUFF_MARGIN_Y } void BKE_stamp_info(Scene *scene, Object *camera, struct ImBuf *ibuf) @@ -1674,8 +1665,15 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) /* read ibuf */ ibuf = IMB_loadiffname(name, flag); - if(G.f & G_DEBUG) printf("loaded %s\n", name); - + +#if 0 + if(ibuf) { + printf(AT" loaded %s\n", name); + } else { + printf(AT" missed %s\n", name); + } +#endif + if (ibuf) { #ifdef WITH_OPENEXR /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ @@ -2231,21 +2229,19 @@ void BKE_image_release_ibuf(Image *ima, void *lock) /* warning, this can allocate generated images */ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) { + /* here (+fie_ima/2-1) makes sure that division happens correctly */ return BKE_image_acquire_ibuf(ima, iuser, NULL); } -void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr) +int BKE_image_user_get_frame(const ImageUser *iuser, int cfra, int fieldnr) { - int len; - - /* here (+fie_ima/2-1) makes sure that division happens correctly */ - len= (iuser->fie_ima*iuser->frames)/2; - + const int len= (iuser->fie_ima*iuser->frames)/2; + if(len==0) { - iuser->framenr= 0; + return 0; } else { - int imanr; + int framenr; cfra= cfra - iuser->sfra+1; /* cyclic */ @@ -2254,31 +2250,38 @@ void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr) if(cfra < 0) cfra+= len; if(cfra==0) cfra= len; } - + if(cfra<0) cfra= 0; else if(cfra>len) cfra= len; - + /* convert current frame to current field */ cfra= 2*(cfra); if(fieldnr) cfra++; - + /* transform to images space */ - imanr= (cfra+iuser->fie_ima-2)/iuser->fie_ima; - if(imanr>iuser->frames) imanr= iuser->frames; - imanr+= iuser->offset; - + framenr= (cfra+iuser->fie_ima-2)/iuser->fie_ima; + if(framenr>iuser->frames) framenr= iuser->frames; + framenr+= iuser->offset; + if(iuser->cycl) { - imanr= ( (imanr) % len ); - while(imanr < 0) imanr+= len; - if(imanr==0) imanr= len; + framenr= ( (framenr) % len ); + while(framenr < 0) framenr+= len; + if(framenr==0) framenr= len; } - - /* allows image users to handle redraws */ - if(iuser->flag & IMA_ANIM_ALWAYS) - if(imanr!=iuser->framenr) - iuser->flag |= IMA_ANIM_REFRESHED; - - iuser->framenr= imanr; - if(iuser->ok==0) iuser->ok= 1; + + return framenr; } } + +void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr) +{ + const int framenr= BKE_image_user_get_frame(iuser, cfra, fieldnr); + + /* allows image users to handle redraws */ + if(iuser->flag & IMA_ANIM_ALWAYS) + if(framenr!=iuser->framenr) + iuser->flag |= IMA_ANIM_REFRESHED; + + iuser->framenr= framenr; + if(iuser->ok==0) iuser->ok= 1; +} diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 7f0292b2f22..099661f7914 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -50,7 +50,7 @@ #include "BKE_global.h" -#define CLOTH_OPENMP_LIMIT 25 +#define CLOTH_OPENMP_LIMIT 512 #ifdef _WIN32 #include <windows.h> @@ -939,7 +939,7 @@ static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z s = dot_lfvector(r, r, numverts); starget = s * sqrt(conjgrad_epsilon); - while((s>starget && conjgrad_loopcount < conjgrad_looplimit)) + while(s>starget && conjgrad_loopcount < conjgrad_looplimit) { // Mul(q,A,d); // q = A*d; mul_bfmatrix_lfvector(q, lA, d); @@ -1749,15 +1749,93 @@ static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVect del_lfvector(dFdXmV); } +/*computes where the cloth would be if it were subject to perfectly stiff edges + (edge distance constraints) in a lagrangian solver. then add forces to help + guide the implicit solver to that state. this function is called after + collisions*/ +int cloth_calc_helper_forces(Object *UNUSED(ob), ClothModifierData * clmd, float (*initial_cos)[3], float UNUSED(step), float dt) +{ + Cloth *cloth= clmd->clothObject; + float (*cos)[3] = MEM_callocN(sizeof(float)*3*cloth->numverts, "cos cloth_calc_helper_forces"); + float *masses = MEM_callocN(sizeof(float)*cloth->numverts, "cos cloth_calc_helper_forces"); + LinkNode *node; + ClothSpring *spring; + ClothVertex *cv; + int i, steps; + + cv = cloth->verts; + for (i=0; i<cloth->numverts; i++, cv++) { + copy_v3_v3(cos[i], cv->tx); + + if (cv->goal == 1.0f || len_v3v3(initial_cos[i], cv->tx) != 0.0) { + masses[i] = 1e+10; + } else { + masses[i] = cv->mass; + } + } + + steps = 55; + for (i=0; i<steps; i++) { + for (node=cloth->springs; node; node=node->next) { + ClothVertex *cv1, *cv2; + int v1, v2; + float len, c, l, vec[3]; + + spring = node->link; + if (spring->type != CLOTH_SPRING_TYPE_STRUCTURAL && spring->type != CLOTH_SPRING_TYPE_SHEAR) + continue; + + v1 = spring->ij; v2 = spring->kl; + cv1 = cloth->verts + v1; + cv2 = cloth->verts + v2; + len = len_v3v3(cos[v1], cos[v2]); + + sub_v3_v3v3(vec, cos[v1], cos[v2]); + normalize_v3(vec); + + c = (len - spring->restlen); + if (c == 0.0) + continue; + + l = c / ((1.0/masses[v1]) + (1.0/masses[v2])); + + mul_v3_fl(vec, -(1.0/masses[v1])*l); + add_v3_v3(cos[v1], vec); + + sub_v3_v3v3(vec, cos[v2], cos[v1]); + normalize_v3(vec); + + mul_v3_fl(vec, -(1.0/masses[v2])*l); + add_v3_v3(cos[v2], vec); + } + } + + cv = cloth->verts; + for (i=0; i<cloth->numverts; i++, cv++) { + float vec[3]; + + /*compute forces*/ + sub_v3_v3v3(vec, cos[i], cv->tx); + mul_v3_fl(vec, cv->mass*dt*20.0); + add_v3_v3(cv->tv, vec); + //copy_v3_v3(cv->tx, cos[i]); + } + + MEM_freeN(cos); + MEM_freeN(masses); + + return 1; +} int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { unsigned int i=0; float step=0.0f, tf=clmd->sim_parms->timescale; Cloth *cloth = clmd->clothObject; - ClothVertex *verts = cloth->verts; + ClothVertex *verts = cloth->verts, *cv; unsigned int numverts = cloth->numverts; float dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; + float (*initial_cos)[3] = MEM_callocN(sizeof(float)*3*cloth->numverts, "initial_cos implicit.c"); Implicit_Data *id = cloth->implicit; int do_extra_solve; @@ -1817,15 +1895,26 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase VECCOPY(verts[i].v, verts[i].tv); } + for (i=0, cv=cloth->verts; i<cloth->numverts; i++, cv++) { + copy_v3_v3(initial_cos[i], cv->tx); + } + // call collision function // TODO: check if "step" or "step+dt" is correct - dg do_extra_solve = cloth_bvh_objcollision(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale); - + // copy corrected positions back to simulation for(i = 0; i < numverts; i++) { // correct velocity again, just to be sure we had to change it due to adaptive collisions VECSUB(verts[i].tv, verts[i].tx, id->X[i]); + } + + //if (do_extra_solve) + // cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale); + + for(i = 0; i < numverts; i++) + { if(do_extra_solve) { @@ -1886,6 +1975,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } } + MEM_freeN(initial_cos); + return 1; } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index a9bd72f43fa..cddac4db739 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1395,7 +1395,7 @@ void text_idbutton(struct ID *id, char *text) if(id) { if(GS(id->name)==ID_SCE) strcpy(text, "SCE: "); - else if(GS(id->name)==ID_SCE) + else if(GS(id->name)==ID_SCR) strcpy(text, "SCR: "); else if(GS(id->name)==ID_MA && ((Material*)id)->use_nodes) strcpy(text, "NT: "); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 4b40c07b7a9..ba2434bba23 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1193,7 +1193,9 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree) newtree= MEM_dupallocN(ntree); copy_libblock_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */ } - + + id_us_plus((ID *)newtree->gpd); + /* in case a running nodetree is copied */ newtree->init &= ~(NTREE_EXEC_INIT); newtree->threadstack= NULL; @@ -1435,6 +1437,8 @@ void ntreeFreeTree(bNodeTree *ntree) BKE_free_animdata((ID *)ntree); + id_us_min((ID *)ntree->gpd); + BLI_freelistN(&ntree->links); /* do first, then unlink_node goes fast */ for(node= ntree->nodes.first; node; node= next) { @@ -2324,13 +2328,18 @@ static void tex_end_exec(bNodeTree *ntree) bNodeStack *ns; int th, a; - if(ntree->threadstack) - for(th=0; th<BLENDER_MAX_THREADS; th++) - for(nts=ntree->threadstack[th].first; nts; nts=nts->next) - for(ns= nts->stack, a=0; a<ntree->stacksize; a++, ns++) - if(ns->data) + if(ntree->threadstack) { + for(th=0; th<BLENDER_MAX_THREADS; th++) { + for(nts=ntree->threadstack[th].first; nts; nts=nts->next) { + for(ns= nts->stack, a=0; a<ntree->stacksize; a++, ns++) { + if(ns->data) { MEM_freeN(ns->data); - + ns->data= NULL; + } + } + } + } + } } void ntreeBeginExecTree(bNodeTree *ntree) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 2721d02eab6..15c4028478c 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1613,6 +1613,10 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) armature_set_id_extern(ob); } + else if (target->type == OB_EMPTY) { + ob->empty_drawtype = target->empty_drawtype; + ob->empty_drawsize = target->empty_drawsize; + } /* copy IDProperties */ if(ob->id.properties) { @@ -2559,10 +2563,7 @@ void object_handle_update(Scene *scene, Object *ob) invert_m4_m4(obg->imat, obg->obmat); mul_m4_m4m4(ob->obmat, ob->proxy_from->obmat, obg->imat); if(obg->dup_group) { /* should always be true */ - float tvec[3]; - copy_v3_v3(tvec, obg->dup_group->dupli_ofs); - mul_mat3_m4_v3(ob->obmat, tvec); - sub_v3_v3(ob->obmat[3], tvec); + add_v3_v3(ob->obmat[3], obg->dup_group->dupli_ofs); } } else diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 666ba31faed..c2aa297b174 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2553,7 +2553,7 @@ static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, floa /* damp affects final velocity */ if(part->dampfac != 0.f) - mul_v3_fl(pa->state.vel, 1.f - part->dampfac * efdata.ptex.damp); + mul_v3_fl(pa->state.vel, 1.f - part->dampfac * efdata.ptex.damp * 25.f * dtime); //VECCOPY(pa->state.ave, states->ave); diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index aa91cff03b9..6f49155c0fd 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -37,7 +37,7 @@ #include <stdlib.h> #include "MEM_guardedalloc.h" -#include "PIL_dynlib.h" +#include "BLI_dynlib.h" #include "BLI_math.h" /* windows needs for M_PI */ #include "BLI_utildefines.h" @@ -138,18 +138,18 @@ static void open_plugin_seq(PluginSeq *pis, const char *seqname) pis->instance_private_data = NULL; /* clear the error list */ - PIL_dynlib_get_error_as_string(NULL); + BLI_dynlib_get_error_as_string(NULL); - /* if(pis->handle) PIL_dynlib_close(pis->handle); */ + /* if(pis->handle) BLI_dynlib_close(pis->handle); */ /* pis->handle= 0; */ /* open the needed object */ - pis->handle= PIL_dynlib_open(pis->name); + pis->handle= BLI_dynlib_open(pis->name); if(test_dlerr(pis->name, pis->name)) return; if (pis->handle != NULL) { /* find the address of the version function */ - version= (int (*)(void))PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion"); + version= (int (*)(void))BLI_dynlib_find_symbol(pis->handle, "plugin_seq_getversion"); if (test_dlerr(pis->name, "plugin_seq_getversion")) return; if (version != NULL) { @@ -158,7 +158,7 @@ static void open_plugin_seq(PluginSeq *pis, const char *seqname) int (*info_func)(PluginInfo *); PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info"); - info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo"); + info_func= (int (*)(PluginInfo *))BLI_dynlib_find_symbol(pis->handle, "plugin_getinfo"); if(info_func == NULL) error("No info func"); else { @@ -176,21 +176,21 @@ static void open_plugin_seq(PluginSeq *pis, const char *seqname) } MEM_freeN(info); - cp= PIL_dynlib_find_symbol(pis->handle, "seqname"); + cp= BLI_dynlib_find_symbol(pis->handle, "seqname"); if(cp) strncpy(cp, seqname, 21); } else { printf ("Plugin returned unrecognized version number\n"); return; } } - alloc_private = (void* (*)(void))PIL_dynlib_find_symbol( + alloc_private = (void* (*)(void))BLI_dynlib_find_symbol( pis->handle, "plugin_seq_alloc_private_data"); if (alloc_private) { pis->instance_private_data = alloc_private(); } pis->current_private_data = (void**) - PIL_dynlib_find_symbol( + BLI_dynlib_find_symbol( pis->handle, "plugin_private_data"); } } @@ -229,12 +229,12 @@ static void free_plugin_seq(PluginSeq *pis) { if(pis==NULL) return; - /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */ + /* no BLI_dynlib_close: same plugin can be opened multiple times with 1 handle */ if (pis->instance_private_data) { void (*free_private)(void *); - free_private = (void (*)(void *))PIL_dynlib_find_symbol( + free_private = (void (*)(void *))BLI_dynlib_find_symbol( pis->handle, "plugin_seq_free_private_data"); if (free_private) { free_private(pis->instance_private_data); @@ -301,7 +301,7 @@ static struct ImBuf * do_plugin_effect( if(seq->plugin->cfra) *(seq->plugin->cfra)= cfra; - cp = PIL_dynlib_find_symbol( + cp = BLI_dynlib_find_symbol( seq->plugin->handle, "seqname"); if(cp) strncpy(cp, seq->name+2, 22); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 53b66238ec0..e3639dd1c51 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1917,7 +1917,7 @@ static ImBuf * seq_render_scene_strip_impl( camera= scene->camera; } - if(scene && have_seq==FALSE && camera==NULL) { + if(have_seq==FALSE && camera==NULL) { scene->r.cfra= oldcfra; return NULL; } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 33094313acd..5d44841df8b 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -74,6 +74,7 @@ static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v); static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e); static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f); +static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm); /// @@ -1157,7 +1158,7 @@ static void ccgDM_drawVerts(DerivedMesh *dm) { static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm) { - if(ccgdm->pbvh) { + if(ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) { CCGFace **faces; int totface; @@ -2249,10 +2250,22 @@ static ListBase *ccgDM_getFaceMap(Object *ob, DerivedMesh *dm) return ccgdm->fmap; } +static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm) +{ + MultiresModifierData *mmd= ccgdm->multires.mmd; + + /* both of multires and subsurm modifiers are CCG, but + grids should only be used when sculpting on multires */ + if(!mmd) + return 0; + + return 1; +} + static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) { CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - int gridSize, numGrids; + int gridSize, numGrids, grid_pbvh; if(!ob) { ccgdm->pbvh= NULL; @@ -2262,13 +2275,17 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) if(!ob->sculpt) return NULL; + grid_pbvh= ccgDM_use_grid_pbvh(ccgdm); + if(ob->sculpt->pbvh) { - /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm - but this can be freed on ccgdm release, this updates the pointers - when the ccgdm gets remade, the assumption is that the topology - does not change. */ - ccgdm_create_grids(dm); - BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void**)ccgdm->gridFaces); + if(grid_pbvh) { + /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm + but this can be freed on ccgdm release, this updates the pointers + when the ccgdm gets remade, the assumption is that the topology + does not change. */ + ccgdm_create_grids(dm); + BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void**)ccgdm->gridFaces); + } ccgdm->pbvh = ob->sculpt->pbvh; } @@ -2279,14 +2296,21 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) /* no pbvh exists yet, we need to create one. only in case of multires we build a pbvh over the modified mesh, in other cases the base mesh is being sculpted, so we build a pbvh from that. */ - ccgdm_create_grids(dm); + if(grid_pbvh) { + ccgdm_create_grids(dm); - gridSize = ccgDM_getGridSize(dm); - numGrids = ccgDM_getNumGrids(dm); + gridSize = ccgDM_getGridSize(dm); + numGrids = ccgDM_getNumGrids(dm); - ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new(); - BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, - numGrids, gridSize, (void**)ccgdm->gridFaces); + ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new(); + BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, + numGrids, gridSize, (void**)ccgdm->gridFaces); + } else if(ob->type == OB_MESH) { + Mesh *me= ob->data; + ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new(); + BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert, + me->totface, me->totvert); + } return ccgdm->pbvh; } diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index ba5d4282416..512914e2c52 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -1232,7 +1232,7 @@ char *txt_to_buf (Text *text) return buf; } -int txt_find_string(Text *text, char *findstr, int wrap) +int txt_find_string(Text *text, char *findstr, int wrap, int match_case) { TextLine *tl, *startl; char *s= NULL; @@ -1246,7 +1246,8 @@ int txt_find_string(Text *text, char *findstr, int wrap) oldsl= txt_get_span(text->lines.first, text->sell); tl= startl= text->sell; - s= strstr(&tl->line[text->selc], findstr); + if(match_case) s= strstr(&tl->line[text->selc], findstr); + else s= BLI_strcasestr(&tl->line[text->selc], findstr); while (!s) { tl= tl->next; if (!tl) { @@ -1256,7 +1257,8 @@ int txt_find_string(Text *text, char *findstr, int wrap) break; } - s= strstr(tl->line, findstr); + if(match_case) s= strstr(tl->line, findstr); + else s= BLI_strcasestr(tl->line, findstr); if (tl==startl) break; } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 866874ee5c8..9cd07de31dc 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -41,9 +41,8 @@ #include "MEM_guardedalloc.h" -#include "PIL_dynlib.h" - #include "BLI_blenlib.h" +#include "BLI_dynlib.h" #include "BLI_math.h" #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" @@ -82,7 +81,7 @@ int test_dlerr(const char *name, const char *symbol) { char *err; - err= PIL_dynlib_get_error_as_string(NULL); + err= BLI_dynlib_get_error_as_string(NULL); if(err) { printf("var1: %s, var2: %s, var3: %s\n", name, symbol, err); return 1; @@ -108,19 +107,19 @@ void open_plugin_tex(PluginTex *pit) pit->instance_init= NULL; /* clear the error list */ - PIL_dynlib_get_error_as_string(NULL); + BLI_dynlib_get_error_as_string(NULL); - /* no PIL_dynlib_close! multiple opened plugins... */ - /* if(pit->handle) PIL_dynlib_close(pit->handle); */ + /* no BLI_dynlib_close! multiple opened plugins... */ + /* if(pit->handle) BLI_dynlib_close(pit->handle); */ /* pit->handle= 0; */ /* open the needed object */ - pit->handle= PIL_dynlib_open(pit->name); + pit->handle= BLI_dynlib_open(pit->name); if(test_dlerr(pit->name, pit->name)) return; if (pit->handle != NULL) { /* find the address of the version function */ - version= (int (*)(void)) PIL_dynlib_find_symbol(pit->handle, "plugin_tex_getversion"); + version= (int (*)(void)) BLI_dynlib_find_symbol(pit->handle, "plugin_tex_getversion"); if (test_dlerr(pit->name, "plugin_tex_getversion")) return; if (version != NULL) { @@ -129,7 +128,7 @@ void open_plugin_tex(PluginTex *pit) int (*info_func)(PluginInfo *); PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info"); - info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pit->handle, "plugin_getinfo"); + info_func= (int (*)(PluginInfo *))BLI_dynlib_find_symbol(pit->handle, "plugin_getinfo"); if (!test_dlerr(pit->name, "plugin_getinfo")) { info->instance_init = NULL; @@ -200,7 +199,7 @@ void free_plugin_tex(PluginTex *pit) { if(pit==NULL) return; - /* no PIL_dynlib_close: same plugin can be opened multiple times, 1 handle */ + /* no BLI_dynlib_close: same plugin can be opened multiple times, 1 handle */ MEM_freeN(pit); } |