Index: mesh_navmesh.c =================================================================== --- mesh_navmesh.c (revision 49732) +++ mesh_navmesh.c (working copy) @@ -65,7 +65,56 @@ #include "mesh_intern.h" #include "recast-capi.h" +#include "DNA_group_types.h" +// info: since this step is done for common objects and group objects I tried to extract a method so the code +// keeps nicer...but as soon as I have 2 group objects it dies. note sure what I'm doing wrong here. +static void createObjectVertsTrisData(Object* ob, DerivedMesh* dm, float* verts, int* basenverts, int* tri) { + + MVert *mvert; + int i, curnverts, curnfaces; + MFace *mface; + float co[3], wco[3]; + + curnverts = dm->getNumVerts(dm); + mvert = dm->getVertArray(dm); + + /* copy verts */ + for (i = 0; i < curnverts; i++) { + MVert *v = &mvert[i]; + + copy_v3_v3(co, v->co); + mul_v3_m4v3(wco, ob->obmat, co); + + verts[3 * (*basenverts + i) + 0] = wco[0]; + verts[3 * (*basenverts + i) + 1] = wco[2]; + verts[3 * (*basenverts + i) + 2] = wco[1]; + } + + /* create tris */ + curnfaces = dm->getNumTessFaces(dm); + mface = dm->getTessFaceArray(dm); + + for (i = 0; i < curnfaces; i++) { + MFace *mf = &mface[i]; + + tri[0] = *basenverts + mf->v1; + tri[1] = *basenverts + mf->v3; + tri[2] = *basenverts + mf->v2; + tri += 3; + + if (mf->v4) { + tri[0] = *basenverts + mf->v1; + tri[1] = *basenverts + mf->v4; + tri[2] = *basenverts + mf->v3; + tri += 3; + } + } + + *basenverts += curnverts; + +} + static void createVertsTrisData(bContext *C, LinkNode *obs, int *nverts_r, float **verts_r, int *ntris_r, int **tris_r) { MVert *mvert; @@ -73,6 +122,11 @@ MFace *mface; float co[3], wco[3]; Object *ob; + GroupObject *gobj; + + float mat4[4][4]; + + LinkNode *oblink, *dmlink; DerivedMesh *dm; Scene *scene = CTX_data_scene(C); @@ -87,20 +141,48 @@ /* calculate number of verts and tris */ for (oblink = obs; oblink; oblink = oblink->next) { ob = (Object *) oblink->link; - dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH); - BLI_linklist_append(&dms, (void *)dm); - nverts += dm->getNumVerts(dm); - nfaces = dm->getNumTessFaces(dm); - ntris += nfaces; + // is it a group-instance? + if (ob->type == OB_EMPTY && ob->dup_group) { + Group *gr = ob->dup_group; + /* printf("group detected '%s'\n", gr->id.name+2); */ + for (gobj = (GroupObject *)(gr->gobject.first); gobj; gobj = gobj->next) { + // create a function for this!? + dm = mesh_create_derived_no_virtual(scene, gobj->ob, NULL, CD_MASK_MESH); + BLI_linklist_append(&dms, (void *)dm); - /* resolve quad faces */ - mface = dm->getTessFaceArray(dm); - for (i = 0; i < nfaces; i++) { - MFace *mf = &mface[i]; - if (mf->v4) - ntris += 1; + nverts += dm->getNumVerts(dm); + nfaces = dm->getNumTessFaces(dm); + ntris += nfaces; + + /* resolve quad faces */ + mface = dm->getTessFaceArray(dm); + for (i = 0; i < nfaces; i++) { + MFace *mf = &mface[i]; + if (mf->v4) + ntris += 1; + } + //----- + + } } + else { + // and reuse it here...same code! Yeah, sry! This could have been done better + dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH); + BLI_linklist_append(&dms, (void *)dm); + + nverts += dm->getNumVerts(dm); + nfaces = dm->getNumTessFaces(dm); + ntris += nfaces; + + /* resolve quad faces */ + mface = dm->getTessFaceArray(dm); + for (i = 0; i < nfaces; i++) { + MFace *mf = &mface[i]; + if (mf->v4) + ntris += 1; + } + } } /* create data */ @@ -113,46 +195,111 @@ oblink = oblink->next, dmlink = dmlink->next) { ob = (Object *) oblink->link; - dm = (DerivedMesh *) dmlink->link; - curnverts = dm->getNumVerts(dm); - mvert = dm->getVertArray(dm); - /* copy verts */ - for (i = 0; i < curnverts; i++) { - MVert *v = &mvert[i]; + // dupli-groups + if (ob->type == OB_EMPTY && ob->dup_group) { - copy_v3_v3(co, v->co); - mul_v3_m4v3(wco, ob->obmat, co); + Group *gr = ob->dup_group; + /* printf("group detected '%s'\n", gr->id.name+2); */ + for (gobj = (GroupObject *)(gr->gobject.first); gobj; gobj = gobj->next) { + // actually this is more or less the same as for the common objects + // with the difference that additionally you have to apply the group-object-position and the object-position + // (hmm, there is something like an offset for group-instances?!..if yes, this needs to be done yet) + dm = (DerivedMesh *) dmlink->link; - verts[3 * (basenverts + i) + 0] = wco[0]; - verts[3 * (basenverts + i) + 1] = wco[2]; - verts[3 * (basenverts + i) + 2] = wco[1]; + curnverts = dm->getNumVerts(dm); + mvert = dm->getVertArray(dm); + + // combine positioning of the group-instance and the group-objects + mult_m4_m4m4(mat4,ob->obmat,gobj->ob->obmat); + /* copy verts */ + for (i = 0; i < curnverts; i++) { + MVert *v = &mvert[i]; + + + copy_v3_v3(co, v->co); + mul_v3_m4v3(wco, mat4, co); + + + verts[3 * (basenverts + i) + 0] = wco[0]; + verts[3 * (basenverts + i) + 1] = wco[2]; + verts[3 * (basenverts + i) + 2] = wco[1]; + } + + /* create tris */ + curnfaces = dm->getNumTessFaces(dm); + mface = dm->getTessFaceArray(dm); + + for (i = 0; i < curnfaces; i++) { + MFace *mf = &mface[i]; + + tri[0] = basenverts + mf->v1; + tri[1] = basenverts + mf->v3; + tri[2] = basenverts + mf->v2; + tri += 3; + + if (mf->v4) { + tri[0] = basenverts + mf->v1; + tri[1] = basenverts + mf->v4; + tri[2] = basenverts + mf->v3; + tri += 3; + } + } + + basenverts += curnverts; + + + if (gobj->next) + dmlink = dmlink->next; + } } + // common objects with mesh + else { + // again the same code. hurts a bit in the eye. feel free to merge these to a function ;D + dm = (DerivedMesh *) dmlink->link; - /* create tris */ - curnfaces = dm->getNumTessFaces(dm); - mface = dm->getTessFaceArray(dm); + curnverts = dm->getNumVerts(dm); + mvert = dm->getVertArray(dm); - for (i = 0; i < curnfaces; i++) { - MFace *mf = &mface[i]; + /* copy verts */ + for (i = 0; i < curnverts; i++) { + MVert *v = &mvert[i]; - tri[0] = basenverts + mf->v1; - tri[1] = basenverts + mf->v3; - tri[2] = basenverts + mf->v2; - tri += 3; + copy_v3_v3(co, v->co); + mul_v3_m4v3(wco, ob->obmat, co); - if (mf->v4) { + verts[3 * (basenverts + i) + 0] = wco[0]; + verts[3 * (basenverts + i) + 1] = wco[2]; + verts[3 * (basenverts + i) + 2] = wco[1]; + } + + /* create tris */ + curnfaces = dm->getNumTessFaces(dm); + mface = dm->getTessFaceArray(dm); + + for (i = 0; i < curnfaces; i++) { + MFace *mf = &mface[i]; + tri[0] = basenverts + mf->v1; - tri[1] = basenverts + mf->v4; - tri[2] = basenverts + mf->v3; + tri[1] = basenverts + mf->v3; + tri[2] = basenverts + mf->v2; tri += 3; + + if (mf->v4) { + tri[0] = basenverts + mf->v1; + tri[1] = basenverts + mf->v4; + tri[2] = basenverts + mf->v3; + tri += 3; + } } + + basenverts += curnverts; + } - - basenverts += curnverts; } + /* release derived mesh */ for (dmlink = dms; dmlink; dmlink = dmlink->next) { dm = (DerivedMesh *) dmlink->link; @@ -433,7 +580,9 @@ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - if (base->object->type == OB_MESH) { + if (base->object->type == OB_MESH + || ((base->object->type == OB_EMPTY) + && (base->object->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && base->object->dup_group)) { if (base->object->body_type == OB_BODY_TYPE_NAVMESH) { if (!navmeshBase || base == scene->basact) { navmeshBase = base;