Duplicator feature:
authorTon Roosendaal <ton@blender.org>
Wed, 29 Nov 2006 12:44:48 +0000 (12:44 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 29 Nov 2006 12:44:48 +0000 (12:44 +0000)
Vertex/Face/Frame duplication now draws using OpenGL display lists. Makes
drawing go much faster (2-5 times, depending on size of duplicated object).
This system uses boundbox checks too, so outside of view it draws faster.

Note for face duplication: I've fixe a bug for incorrect alignment when
the parent was rotated when a parenting happened, the 'inverse parent
correction matrix' then messed up alignment. For face duplication it now
works OK, but for vertex-dupli not... need a way to fix this backwards
compatible.

source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/object.c
source/blender/makesdna/DNA_object_types.h
source/blender/src/drawview.c
source/blender/src/view.c

index fde33723cc47fe1b333e0418eae3f733ba474124..9ad20b6a586a9b963c122fba2f93ef623059adeb 100644 (file)
@@ -109,6 +109,7 @@ void what_does_parent(struct Object *ob);
 struct BoundBox *unit_boundbox(void);
 void boundbox_set_from_min_max(struct BoundBox *bb, float min[3], float max[3]);
 struct BoundBox *object_get_boundbox(struct Object *ob);
+void object_boundbox_flag(struct Object *ob, int flag, int set);
 void minmax_object(struct Object *ob, float *min, float *max);
 void solve_tracking (struct Object *ob, float targetmat[][4]);
 void solve_constraints (struct Object *ob, short obtype, void *obdata, float ctime);
index 11099ac0d72a5b0fc4193f3906d123a2b18ab23d..ad97128bb379e25595bc4e9eb9889bc649ea5b47 100644 (file)
@@ -464,7 +464,7 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
        DerivedMesh *dm;
        MFace *mface;
        MVert *mvert;
-       float pmat[4][4];
+       float pmat[4][4], imat[3][3];
        int lay, totface, a;
        
        Mat4CpyMat4(pmat, par->obmat);
@@ -499,6 +499,7 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
                                if(ob==par) {
                                        
                                        ob= base->object;
+                                       Mat3CpyMat4(imat, ob->parentinv);
                                        
                                        /* mballs have a different dupli handling */
                                        if(ob->type!=OB_MBALL) ob->flag |= OB_DONE;     /* doesnt render */
@@ -508,7 +509,7 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
                                                float *v2= mvert[ mface[a].v2 ].co;
                                                float *v3= mvert[ mface[a].v3 ].co;
                                                float *v4= mface[a].v4?mvert[ mface[a].v4 ].co:NULL;
-                                               float cent[3], quat[4], mat[3][3], tmat[4][4], obmat[4][4];
+                                               float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4];
 
                                                /* translation */
                                                if(v4)
@@ -534,6 +535,9 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
                                                        Mat3MulFloat(mat[0], size);
                                                }
                                                
+                                               Mat3CpyMat3(mat3, mat);
+                                               Mat3MulMat3(mat, imat, mat3);
+                                               
                                                Mat4CpyMat4(tmat, obmat);
                                                Mat4MulMat43(obmat, tmat, mat);
                                                
index c75c2a0238cf8b352105d6a9f6d13623a1b8615f..abe7cd4d38dd923988ab53c1280cb7385bdf0b0a 100644 (file)
@@ -1890,6 +1890,16 @@ BoundBox *object_get_boundbox(Object *ob)
        return bb;
 }
 
+/* used to temporally disable/enable boundbox */
+void object_boundbox_flag(Object *ob, int flag, int set)
+{
+       BoundBox *bb= object_get_boundbox(ob);
+       if(bb) {
+               if(set) bb->flag |= flag;
+               else bb->flag &= ~flag;
+       }
+}
+
 void minmax_object(Object *ob, float *min, float *max)
 {
        BoundBox bb;
index dd79835b0331f2d0fe21205e8702b2132ff7a7e2..e58e6d7aa791640bacb812eef5801d4f06c01c6e 100644 (file)
@@ -63,8 +63,12 @@ typedef struct bDeformGroup {
 
 typedef struct BoundBox {
        float vec[8][3];
+       int flag, pad;
 } BoundBox;
 
+/* boundbox flag */
+#define OB_BB_DISABLED 1
+
 /* OcInfo and LBuf structs are for the Enji gameengine */
 
 typedef struct OcInfo {
index 47da7dfb07be496e9b5cc4c59438c287f220d573..279f2de627781857c119ce82bc54cc55f3371a9f 100644 (file)
@@ -2650,8 +2650,10 @@ static void draw_dupli_objects(View3D *v3d, Base *base)
        ListBase *lb;
        DupliObject *dob;
        Base tbase;
+       BoundBox *bb= NULL;
+       GLuint displist=0;
        int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
-       short transflag;
+       short transflag, use_displist= G.rt;    /* -1 is initialize */
        char dt, dtx;
        
        if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
@@ -2660,6 +2662,10 @@ static void draw_dupli_objects(View3D *v3d, Base *base)
        if(base->object->dup_group && base->object->dup_group->id.us<1)
                color= TH_REDALERT;
        
+       /* test if we can do a displist */
+       if(base->object->transflag & OB_DUPLIGROUP)
+               use_displist= 0;
+       
        tbase.flag= OB_FROMDUPLI|base->flag;
        lb= object_duplilist(G.scene, base->object);
 
@@ -2668,8 +2674,6 @@ static void draw_dupli_objects(View3D *v3d, Base *base)
                else {
                        tbase.object= dob->ob;
                        
-                       Mat4CpyMat4(dob->ob->obmat, dob->mat);
-                       
                        /* extra service: draw the duplicator in drawtype of parent */
                        dt= tbase.object->dt; tbase.object->dt= base->object->dt;
                        dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
@@ -2680,7 +2684,39 @@ static void draw_dupli_objects(View3D *v3d, Base *base)
                                tbase.object->transflag ^= OB_NEG_SCALE;
                        
                        BIF_ThemeColorBlend(color, TH_BACK, 0.5);
-                       draw_object(&tbase, DRAW_CONSTCOLOR);
+                       
+                       /* generate displist, test for new object */
+                       if(use_displist==1 && dob->prev && dob->prev->ob!=dob->ob) {
+                               use_displist= -1;
+                               glDeleteLists(displist, 1);
+                       }
+                       /* generate displist */
+                       if(use_displist == -1) {
+                               /* disable boundbox check for list creation */
+                               object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
+                               /* need this for next part of code */
+                               bb= object_get_boundbox(dob->ob);
+                               
+                               Mat4One(dob->ob->obmat);        /* obmat gets restored */
+                               
+                               displist= glGenLists(1);
+                               glNewList(displist, GL_COMPILE);
+                               draw_object(&tbase, DRAW_CONSTCOLOR);
+                               glEndList();
+                               
+                               use_displist= 1;
+                               object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
+                       }
+                       if(use_displist) {
+                               mymultmatrix(dob->mat);
+                               if(boundbox_clip(dob->mat, bb))
+                                  glCallList(displist);
+                               myloadmatrix(G.vd->viewmat);
+                       }
+                       else {
+                               Mat4CpyMat4(dob->ob->obmat, dob->mat);
+                               draw_object(&tbase, DRAW_CONSTCOLOR);
+                       }
                        
                        tbase.object->dt= dt;
                        tbase.object->dtx= dtx;
@@ -2691,7 +2727,9 @@ static void draw_dupli_objects(View3D *v3d, Base *base)
        /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
        
        free_object_duplilist(lb);      /* does restore */
-                               
+       
+       if(use_displist)
+               glDeleteLists(displist, 1);
 }
 
 void view3d_update_depths(View3D *v3d)
index 51ef76e1f44fd3704143f159117afc7417198489..1cd409515099d89688a1c4112fa344259afb6368 100644 (file)
@@ -362,7 +362,8 @@ int boundbox_clip(float obmat[][4], BoundBox *bb)
        float vec[4], min, max;
        int a, flag= -1, fl;
        
-       if(bb==0) return 1;
+       if(bb==NULL) return 1;
+       if(bb->flag & OB_BB_DISABLED) return 1;
        
        Mat4MulMat4(mat, obmat, G.vd->persmat);