diff options
Diffstat (limited to 'source/blender/blenkernel/intern/displist.c')
-rw-r--r-- | source/blender/blenkernel/intern/displist.c | 2085 |
1 files changed, 2085 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c new file mode 100644 index 00000000000..b9f9d59c5e3 --- /dev/null +++ b/source/blender/blenkernel/intern/displist.c @@ -0,0 +1,2085 @@ + +/* displist.c GRAPHICS + * + * + * maart 95 + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/BL DUAL LICENSE BLOCK ***** + */ +#include <math.h> +#include <stdio.h> +#include <string.h> + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif +#include "MEM_guardedalloc.h" + +#include "nla.h" /* For __NLA: Please do not remove yet */ + +#include "IMB_imbuf_types.h" + +#include "DNA_texture_types.h" +#include "DNA_meta_types.h" +#include "DNA_curve_types.h" +#include "DNA_listBase.h" +#include "DNA_lamp_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_scene_types.h" +#include "DNA_image_types.h" +#include "DNA_material_types.h" +#include "DNA_view3d_types.h" +#include "DNA_lattice_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_displist.h" +#include "BKE_object.h" +#include "BKE_world.h" +#include "BKE_mesh.h" +#include "BKE_effect.h" +#include "BKE_mball.h" +#include "BKE_material.h" +#include "BKE_curve.h" +#include "BKE_anim.h" +#include "BKE_screen.h" +#include "BKE_texture.h" +#include "BKE_library.h" +#include "BKE_font.h" +#include "BKE_lattice.h" +#include "BKE_scene.h" +#include "BKE_subsurf.h" + +/***/ + +typedef struct _FastLamp FastLamp; +struct _FastLamp { + FastLamp *next; + + short type, mode, lay, rt; + float co[3]; + float vec[3]; + float dist, distkw, att1, att2, spotsi, spotbl, r, g, b; +}; + +/***/ + +static FastLamp *fastlamplist= NULL; +static float fviewmat[4][4]; + +static void displistmesh_free(DispListMesh *dlm) { + // also check on mvert and mface, can be NULL after decimator (ton) + if( dlm->mvert) MEM_freeN(dlm->mvert); + if (dlm->mface) MEM_freeN(dlm->mface); + if (dlm->mcol) MEM_freeN(dlm->mcol); + if (dlm->tface) MEM_freeN(dlm->tface); + MEM_freeN(dlm); +} + +static DispListMesh *displistmesh_copy(DispListMesh *odlm) { + DispListMesh *ndlm= MEM_dupallocN(odlm); + ndlm->mvert= MEM_dupallocN(odlm->mvert); + ndlm->mface= MEM_dupallocN(odlm->mface); + if (odlm->mcol) ndlm->mcol= MEM_dupallocN(odlm->mcol); + if (odlm->tface) ndlm->tface= MEM_dupallocN(odlm->tface); + + return ndlm; +} + +void free_disp_elem(DispList *dl) +{ + if(dl) { + if(dl->verts) MEM_freeN(dl->verts); + if(dl->nors) MEM_freeN(dl->nors); + if(dl->index) MEM_freeN(dl->index); + if(dl->col1) MEM_freeN(dl->col1); + if(dl->col2) MEM_freeN(dl->col2); + if(dl->mesh) displistmesh_free(dl->mesh); + MEM_freeN(dl); + } +} + +void freedisplist(ListBase *lb) +{ + DispList *dl; + + dl= lb->first; + while(dl) { + BLI_remlink(lb, dl); + free_disp_elem(dl); + dl= lb->first; + } +} + +void free_displist_by_type(ListBase *lb, int type) +{ + DispList *dl; + + for (dl= lb->first; dl; ) { + DispList *next= dl->next; + + if (dl->type==type) { + BLI_remlink(lb, dl); + free_disp_elem(dl); + } + + dl= next; + } +} + +DispList *find_displist_create(ListBase *lb, int type) +{ + DispList *dl; + + dl= lb->first; + while(dl) { + if(dl->type==type) return dl; + dl= dl->next; + } + + dl= MEM_callocN(sizeof(DispList), "find_disp"); + dl->type= type; + BLI_addtail(lb, dl); + + return dl; +} + +DispList *find_displist(ListBase *lb, int type) +{ + DispList *dl; + + dl= lb->first; + while(dl) { + if(dl->type==type) return dl; + dl= dl->next; + } + + return 0; +} + +void copy_displist(ListBase *lbn, ListBase *lb) +{ + DispList *dln, *dl; + + lbn->first= lbn->last= 0; + + dl= lb->first; + while(dl) { + + dln= MEM_dupallocN(dl); + BLI_addtail(lbn, dln); + dln->verts= MEM_dupallocN(dl->verts); + dln->nors= MEM_dupallocN(dl->nors); + dln->index= MEM_dupallocN(dl->index); + dln->col1= MEM_dupallocN(dl->col1); + dln->col2= MEM_dupallocN(dl->col2); + if (dl->mesh) + dln->mesh= displistmesh_copy(dl->mesh); + + dl= dl->next; + } +} + +static void initfastshade(void) +{ + Base *base; + Object *ob; + Lamp *la; + FastLamp *fl; + float mat[4][4]; + + R.vlr= 0; + + init_render_world(); + + if(fastlamplist) return; + if(G.scene->camera==0) G.scene->camera= scene_find_camera(G.scene); + if(G.scene->camera==0) return; + + /* uit roteerscene gejat */ + where_is_object(G.scene->camera); + Mat4CpyMat4(R.viewinv, G.scene->camera->obmat); + Mat4Ortho(R.viewinv); + Mat4Invert(fviewmat, R.viewinv); + + + /* initrendertexture(); */ + + base= G.scene->base.first; + while(base) { + ob= base->object; + if( ob->type==OB_LAMP && (base->lay & G.scene->lay)) { + + Mat4MulMat4(mat, ob->obmat, fviewmat); + + la= ob->data; + fl= MEM_mallocN(sizeof(FastLamp), "initfastshade2"); + + fl->next= fastlamplist; + fastlamplist= fl; + + fl->type= la->type; + fl->mode= la->mode; + fl->lay= base->lay; + + fl->vec[0]= mat[2][0]; + fl->vec[1]= mat[2][1]; + fl->vec[2]= mat[2][2]; + Normalise(fl->vec); + + fl->co[0]= mat[3][0]; + fl->co[1]= mat[3][1]; + fl->co[2]= mat[3][2]; + + fl->dist= la->dist; + fl->distkw= fl->dist*fl->dist; + fl->att1= la->att1; + fl->att2= la->att2; + + fl->spotsi= (float)cos( M_PI*la->spotsize/360.0 ); + fl->spotbl= (1.0f-fl->spotsi)*la->spotblend; + + fl->r= la->energy*la->r; + fl->g= la->energy*la->g; + fl->b= la->energy*la->b; + } + + if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; + else base= base->next; + } +} + + +void freefastshade() +{ + while (fastlamplist) { + FastLamp *fl= fastlamplist; + fastlamplist= fl->next; + + MEM_freeN(fl); + } +} + + +static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2, char *vertcol) +{ + FastLamp *fl; + float i, t, inp, soft, inpr, inpg, inpb, isr=0, isg=0, isb=0, lv[3], lampdist, ld; + float inpr1, inpg1, inpb1, isr1=0, isg1=0, isb1=0; + int a, back; + + if(ma==0) return; + R.mat= ma; + R.matren= ma->ren; + ma= R.matren; + + if(ma->mode & MA_VERTEXCOLP) { + if(vertcol) { + ma->r= vertcol[3]/255.0; + ma->g= vertcol[2]/255.0; + ma->b= vertcol[1]/255.0; + } + } + + if(ma->texco) { + VECCOPY(R.lo, orco); + VECCOPY(R.vn, nor); + + if(ma->texco & TEXCO_GLOB) { + VECCOPY(R.gl, R.lo); + } + if(ma->texco & TEXCO_WINDOW) { + VECCOPY(R.winco, R.lo); + } + if(ma->texco & TEXCO_STICKY) { + VECCOPY(R.sticky, R.lo); + } + if(ma->texco & TEXCO_UV) { + VECCOPY(R.uv, R.lo); + } + if(ma->texco & TEXCO_OBJECT) { + VECCOPY(R.co, R.lo); + } + if(ma->texco & TEXCO_NORM) { + VECCOPY(R.orn, R.vn); + } + if(ma->texco & TEXCO_REFL) { + + inp= 2.0*(R.vn[2]); + R.ref[0]= (inp*R.vn[0]); + R.ref[1]= (inp*R.vn[1]); + R.ref[2]= (-1.0+inp*R.vn[2]); + } + + if(ma->mode & MA_VERTEXCOLP) { + R.mat->r= ma->r; + R.mat->g= ma->g; + R.mat->b= ma->b; + } + do_material_tex(); + } + + if(ma->mode & MA_SHLESS) { + if(vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) { + col1[3]= vertcol[3]*ma->r; + col1[2]= vertcol[2]*ma->g; + col1[1]= vertcol[1]*ma->b; + } + else { + col1[3]= (255.0*ma->r); + col1[2]= (255.0*ma->g); + col1[1]= (255.0*ma->b); + } + if(col2) { + col2[3]= col1[3]; + col2[2]= col1[2]; + col2[1]= col1[1]; + } + return; + } + + if( vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) { + inpr= inpr1= ma->emit+vertcol[3]/255.0; + inpg= inpg1= ma->emit+vertcol[2]/255.0; + inpb= inpb1= ma->emit+vertcol[1]/255.0; + } + else { + inpr= inpg= inpb= inpr1= inpg1= inpb1= ma->emit; + } + + /* col[0]= (255.0*ma->r); */ + /* col[1]= (255.0*ma->g); */ + /* col[2]= (255.0*ma->b); */ + + for (fl= fastlamplist; fl; fl= fl->next) { + /* if(fl->mode & LA_LAYER) if((fl->lay & ma->lay)==0) continue; */ + + if(fl->type==LA_SUN || fl->type==LA_HEMI) { + VECCOPY(lv, fl->vec); + lampdist= 1.0; + } + else { + lv[0]= fl->co[0] - co[0]; + lv[1]= fl->co[1] - co[1]; + lv[2]= fl->co[2] - co[2]; + ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]); + lv[0]/=ld; + lv[1]/=ld; + lv[2]/=ld; + + if(fl->mode & LA_QUAD) { + t= 1.0; + if(fl->att1>0.0) + t= fl->dist/(fl->dist+fl->att1*ld); + if(fl->att2>0.0) + t*= fl->distkw/(fl->distkw+fl->att2*ld*ld); + + lampdist= t; + } + else { + lampdist= (fl->dist/(fl->dist+ld)); + } + + if(fl->mode & LA_SPHERE) { + t= fl->dist - ld; + if(t<0.0) continue; + + t/= fl->dist; + lampdist*= (t); + } + } + + if(fl->type==LA_SPOT) { + inp= lv[0]*fl->vec[0]+lv[1]*fl->vec[1]+lv[2]*fl->vec[2]; + if(inp<fl->spotsi) continue; + else { + t= inp-fl->spotsi; + i= 1.0; + soft= 1.0; + if(t<fl->spotbl && fl->spotbl!=0.0) { + /* zachte gebied */ + i= t/fl->spotbl; + t= i*i; + soft= (3.0*t-2.0*t*i); + inp*= soft; + } + + lampdist*=inp; + } + } + + inp= nor[0]*lv[0]+ nor[1]*lv[1]+ nor[2]*lv[2]; + + back= 0; + if(inp<0.0) { + back= 1; + inp= -inp; + } + inp*= lampdist*ma->ref; + + if(back==0) { + inpr+= inp*fl->r; + inpg+= inp*fl->g; + inpb+= inp*fl->b; + } else if(col2) { + inpr1+= inp*fl->r; + inpg1+= inp*fl->g; + inpb1+= inp*fl->b; + } + if(ma->spec) { + + lv[2]+= 1.0; + Normalise(lv); + t= nor[0]*lv[0]+nor[1]*lv[1]+nor[2]*lv[2]; + if(t>0) { + t= ma->spec*lampdist*RE_Spec(t, ma->har); + if(back==0) { + isr+= t*(fl->r * ma->specr); + isg+= t*(fl->g * ma->specg); + isb+= t*(fl->b * ma->specb); + } + else if(col2) { + isr1+= t*(fl->r * ma->specr); + isg1+= t*(fl->g * ma->specg); + isb1+= t*(fl->b * ma->specb); + } + } + } + + } + + a= 256*(inpr*ma->r + ma->ambr +isr); + if(a>255) col1[3]= 255; + else col1[3]= a; + a= 256*(inpg*ma->g + ma->ambg +isg); + if(a>255) col1[2]= 255; + else col1[2]= a; + a= 256*(inpb*ma->b + ma->ambb +isb); + if(a>255) col1[1]= 255; + else col1[1]= a; + + if(col2) { + a= 256*(inpr1*ma->r + ma->ambr +isr1); + if(a>255) col2[3]= 255; + else col2[3]= a; + a= 256*(inpr1*ma->g + ma->ambg +isg1); + if(a>255) col2[2]= 255; + else col2[2]= a; + a= 256*(inpr1*ma->b + ma->ambb +isb1); + if(a>255) col2[1]= 255; + else col2[1]= a; + } + +} + +void addnormalsDispList(Object *ob, ListBase *lb) +{ + DispList *dl = NULL; + Mesh *me; + MVert *ve1, *ve2, *ve3, *ve4; + MFace *mface; + float *vdata, *ndata, nor[3]; + float *v1, *v2, *v3, *v4; + float *n1, *n2, *n3, *n4; + int a, b, p1, p2, p3, p4; + + + if(ob->type==OB_MESH) { + + me= get_mesh(ob); + + if (mesh_uses_displist(me)) { + DispList *dl= find_displist(&me->disp, DL_MESH); + + if (dl && !dl->nors) { + DispListMesh *dlm= dl->mesh; + int i; + + dl->nors= MEM_mallocN(sizeof(*dl->nors)*3*dlm->totface, "meshnormals"); + + for (i=0; i<dlm->totface; i++) { + MFaceInt *mf= &dlm->mface[i]; + float *no= &dl->nors[i*3]; + + if (mf->v3) { + if (mf->v4) + CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no); + else + CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no); + } + } + } + } else { + if(me->totface==0) return; + + if(me->disp.first==0) { + dl= MEM_callocN(sizeof(DispList), "meshdisp"); + dl->type= DL_NORS; + dl->parts= 1; + dl->nr= me->totface; + BLI_addtail(&me->disp, dl); + } + + if(dl->nors==0) { + dl->nors= MEM_mallocN(sizeof(float)*3*me->totface, "meshnormals"); + n1= dl->nors; + mface= me->mface; + a= me->totface; + while(a--) { + if(mface->v3) { + ve1= me->mvert+mface->v1; + ve2= me->mvert+mface->v2; + ve3= me->mvert+mface->v3; + ve4= me->mvert+mface->v4; + + if(mface->v4) CalcNormFloat4(ve1->co, ve2->co, ve3->co, ve4->co, n1); + else CalcNormFloat(ve1->co, ve2->co, ve3->co, n1); + } + n1+= 3; + mface++; + } + } + } + + return; + } + + dl= lb->first; + + while(dl) { + if(dl->type==DL_INDEX3) { + if(dl->nors==0) { + dl->nors= MEM_callocN(sizeof(float)*3, "dlnors"); + if(dl->verts[2]<0.0) dl->nors[2]= -1.0; + else dl->nors[2]= 1.0; + } + } + else if(dl->type==DL_SURF) { + if(dl->nors==0) { + dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors"); + + vdata= dl->verts; + ndata= dl->nors; + + for(a=0; a<dl->parts; a++) { + + DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts); + + v1= vdata+ 3*p1; + n1= ndata+ 3*p1; + v2= vdata+ 3*p2; + n2= ndata+ 3*p2; + v3= vdata+ 3*p3; + n3= ndata+ 3*p3; + v4= vdata+ 3*p4; + n4= ndata+ 3*p4; + + for(; b<dl->nr; b++) { + + CalcNormFloat4(v1, v3, v4, v2, nor); + + VecAddf(n1, n1, nor); + VecAddf(n2, n2, nor); + VecAddf(n3, n3, nor); + VecAddf(n4, n4, nor); + + v2= v1; v1+= 3; + v4= v3; v3+= 3; + n2= n1; n1+= 3; + n4= n3; n3+= 3; + } + } + a= dl->parts*dl->nr; + v1= ndata; + while(a--) { + Normalise(v1); + v1+= 3; + } + } + } + dl= dl->next; + } +} + + +void shadeDispList(Object *ob) +{ + MFace *mface; + MVert *mvert; + DispList *dl, *dlob, *dldeform; + Material *ma = NULL; + Mesh *me; + Curve *cu; +/* extern Material defmaterial; *//* initrender.c, already in bad lev calls*/ + float *orco, imat[3][3], tmat[4][4], mat[4][4], vec[3], xn, yn, zn; + float *fp, *nor, n1[3]; + unsigned int *col1, *col2, *vertcol; + int a, lastmat= -1, need_orco = 0; + + if(ob->flag & OB_FROMDUPLI) return; + initfastshade(); + + Mat4MulMat4(mat, ob->obmat, fviewmat); + + Mat4Invert(tmat, mat); + Mat3CpyMat4(imat, tmat); + + /* we halen de dl_verts eruit, deform info */ + dldeform= find_displist(&ob->disp, DL_VERTS); + if(dldeform) BLI_remlink(&ob->disp, dldeform); + + /* Metaballs hebben de standaard displist aan het Object zitten */ + if(ob->type!=OB_MBALL) freedisplist(&ob->disp); + + if((R.flag & R_RENDERING)==0) { + need_orco= 0; + for(a=0; a<ob->totcol; a++) { + ma= give_current_material(ob, a+1); + if(ma) { + init_render_material(ma); + if(ma->ren->texco & TEXCO_ORCO) need_orco= 1; + } + } + } + if(ob->type==OB_MESH) { + + me= ob->data; + + if (mesh_uses_displist(me)) { + if (need_orco) { + make_orco_displist_mesh(ob, me->subdiv); + orco= me->orco; + } + + dl= me->disp.first; + while(dl) { + if(dl->type==DL_MESH) { + DispListMesh *dlm= dl->mesh; + int i; + + dlob= MEM_callocN(sizeof(DispList), "displistshade"); + BLI_addtail(&ob->disp, dlob); + dlob->type= DL_VERTCOL; + + dlob->col1= MEM_mallocN(sizeof(*dlob->col1)*dlm->totface*4, "col1"); + if (me->flag & ME_TWOSIDED) + dlob->col2= MEM_mallocN(sizeof(*dlob->col2)*dlm->totface*4, "col1"); + + for (i=0; i<dlm->totface; i++) { + MFaceInt *mf= &dlm->mface[i]; + + if (mf->v3) { + int j, vidx[4], nverts= mf->v4?4:3; + unsigned int *col1base= &dlob->col1[i*4]; + unsigned int *col2base= dlob->col2?&dlob->col2[i*4]:NULL; + MCol *mcolbase= dlm->mcol?&dlm->mcol[i*4]:NULL; + float nor[3]; + + ma= give_current_material(ob, mf->mat_nr+1); + if(ma==0) ma= &defmaterial; + + vidx[0]= mf->v1; + vidx[1]= mf->v2; + vidx[2]= mf->v3; + vidx[3]= mf->v4; + + if (mf->v4) + CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, nor); + else + CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, nor); + + n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2]; + n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2]; + n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; + Normalise(n1); + + for (j=0; j<nverts; j++) { + MVert *mv= &dlm->mvert[vidx[j]]; + unsigned int *col1= &col1base[j]; + unsigned int *col2= col2base?&col2base[j]:NULL; + MCol *mcol= mcolbase?&mcolbase[j]:NULL; + + VECCOPY(vec, mv->co); + Mat4MulVecfl(mat, vec); + + if (need_orco && orco) + fastshade(vec, n1, &orco[vidx[j]*3], ma, (char *)col1, (char*)col2, (char*) mcol); + else + fastshade(vec, n1, mv->co, ma, (char *)col1, (char*)col2, (char*) mcol); + } + } + } + } + dl= dl->next; + } + + if (need_orco && orco) { + MEM_freeN(me->orco); + me->orco= NULL; + } + } + else if(me->totvert>0) { + + if(me->orco==0 && need_orco) { + make_orco_mesh(me); + } + orco= me->orco; + /* ms= me->msticky; */ + + dl= me->disp.first; + if(dl==0 || dl->nors==0) addnormalsDispList(ob, &me->disp); + dl= me->disp.first; + if(dl==0 || dl->nors==0) return; + nor= dl->nors; + + dl= MEM_callocN(sizeof(DispList), "displistshade"); + BLI_addtail(&ob->disp, dl); + dl->type= DL_VERTCOL; + col1= dl->col1= MEM_mallocN(4*sizeof(int)*me->totface, "col1"); + col2= 0; + if(me->tface) tface_to_mcol(me); + vertcol= (unsigned int *)me->mcol; + + if( me->flag & ME_TWOSIDED) { + col2= dl->col2= MEM_mallocN(4*sizeof(int)*me->totface, "col2"); + } + + /* even geen puno's */ + mvert= me->mvert; + a= me->totvert; + while(FALSE || a--) { + + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + xn= mvert->no[0]; + yn= mvert->no[1]; + zn= mvert->no[2]; + + /* transpose ! */ + n1[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + n1[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + n1[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalise(n1); + + mvert++; + } + + mface= me->mface; + a= me->totface; + while(a--) { + + if(mface->v3) { + + /* transpose ! */ + n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2]; + n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2]; + n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; + Normalise(n1); + + if(lastmat!=mface->mat_nr) { + ma= give_current_material(ob, mface->mat_nr+1); + if(ma==0) ma= &defmaterial; + lastmat= mface->mat_nr; + } + + mvert= me->mvert+mface->v1; + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + if(orco) fastshade(vec, n1, orco+3*mface->v1, ma, (char *)col1, (char *)col2, (char *)vertcol); + else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol); + col1++; + if(vertcol) vertcol++; + if(col2) col2++; + + mvert= me->mvert+mface->v2; + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + if(orco) fastshade(vec, n1, orco+3*mface->v2, ma, (char *)col1, (char *)col2, (char *)vertcol); + else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol); + col1++; + if(vertcol) vertcol++; + if(col2) col2++; + + mvert= me->mvert+mface->v3; + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + if(orco) fastshade(vec, n1, orco+3*mface->v3, ma, (char *)col1, (char *)col2, (char *)vertcol); + else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol); + col1++; + if(vertcol) vertcol++; + if(col2) col2++; + + if(mface->v4) { + mvert= me->mvert+mface->v4; + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + if(orco) fastshade(vec, n1, orco+3*mface->v4, ma, (char *)col1, (char *)col2, (char *)vertcol); + else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol); + } + col1++; + if(vertcol) vertcol++; + if(col2) col2++; + + } + else { + col1+=4; + if(vertcol) vertcol+=4; + if(col2) col2+=4; + } + + nor+= 3; + mface++; + } + + if(me->orco) { + MEM_freeN(me->orco); + me->orco= 0; + } + if(me->tface) { + MEM_freeN(me->mcol); + me->mcol= 0; + } + } + } + else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { + + /* nu hebben we wel de normalen nodig */ + cu= ob->data; + dl= cu->disp.first; + + while(dl) { + dlob= MEM_callocN(sizeof(DispList), "displistshade"); + BLI_addtail(&ob->disp, dlob); + dlob->type= DL_VERTCOL; + dlob->parts= dl->parts; + dlob->nr= dl->nr; + + if(dl->type==DL_INDEX3) { + col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1"); + } + else { + col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1"); + } + + + ma= give_current_material(ob, dl->col+1); + if(ma==0) ma= &defmaterial; + + if(dl->type==DL_INDEX3) { + if(dl->nors) { + /* er is maar 1 normaal */ + n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2]; + n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2]; + n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2]; + Normalise(n1); + + fp= dl->verts; + + a= dl->nr; + while(a--) { + VECCOPY(vec, fp); + Mat4MulVecfl(mat, vec); + + fastshade(vec, n1, fp, ma, (char *)col1, 0, 0); + + fp+= 3; col1++; + } + } + } + else if(dl->type==DL_SURF) { + if(dl->nors) { + a= dl->nr*dl->parts; + fp= dl->verts; + nor= dl->nors; + + while(a--) { + VECCOPY(vec, fp); + Mat4MulVecfl(mat, vec); + + n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2]; + n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2]; + n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; + Normalise(n1); + + fastshade(vec, n1, fp, ma, (char *)col1, 0, 0); + + fp+= 3; nor+= 3; col1++; + } + } + } + dl= dl->next; + } + } + else if(ob->type==OB_MBALL) { + /* normalen zijn er al */ + dl= ob->disp.first; + + while(dl) { + + if(dl->type==DL_INDEX4) { + if(dl->nors) { + + if(dl->col1) MEM_freeN(dl->col1); + col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1"); + + ma= give_current_material(ob, dl->col+1); + if(ma==0) ma= &defmaterial; + + fp= dl->verts; + nor= dl->nors; + + a= dl->nr; + while(a--) { + VECCOPY(vec, fp); + Mat4MulVecfl(mat, vec); + + /* transpose ! */ + n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2]; + n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2]; + n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; + Normalise(n1); + + fastshade(vec, n1, fp, ma, (char *)col1, 0, 0); + + fp+= 3; col1++; nor+= 3; + } + } + } + dl= dl->next; + } + } + + if((R.flag & R_RENDERING)==0) { + for(a=0; a<ob->totcol; a++) { + ma= give_current_material(ob, a+1); + if(ma) end_render_material(ma); + } + } + + /* deze was er tijdelijk uitgehaald */ + if(dldeform) BLI_addtail(&ob->disp, dldeform); +} + +void reshadeall_displist(void) +{ + DispList *dldeform; + Base *base; + Object *ob; + + freefastshade(); + + base= G.scene->base.first; + while(base) { + if(base->lay & G.scene->lay) { + + ob= base->object; + + /* we halen de dl_verts eruit, deform info */ + dldeform= find_displist(&ob->disp, DL_VERTS); + if(dldeform) BLI_remlink(&ob->disp, dldeform); + + /* Metaballs hebben de standaard displist aan het Object zitten */ + if(ob->type==OB_MBALL) shadeDispList(ob); + else freedisplist(&ob->disp); + + if(dldeform) BLI_addtail(&ob->disp, dldeform); + } + base= base->next; + } +} + +void count_displist(ListBase *lb, int *totvert, int *totface) +{ + DispList *dl; + + dl= lb->first; + while(dl) { + + switch(dl->type) { + case DL_SURF: + *totvert+= dl->nr*dl->parts; + *totface+= (dl->nr-1)*(dl->parts-1); + break; + case DL_INDEX3: + case DL_INDEX4: + *totvert+= dl->nr; + *totface+= dl->parts; + break; + case DL_POLY: + case DL_SEGM: + *totvert+= dl->nr*dl->parts; + } + + dl= dl->next; + } +} + +static void curve_to_displist(ListBase *nubase, ListBase *dispbase) +{ + Nurb *nu; + DispList *dl; + BezTriple *bezt, *prevbezt; + BPoint *bp; + float *data, *v1, *v2; + int a, len; + + nu= nubase->first; + + while(nu) { + if(nu->hide==0) { + if((nu->type & 7)==CU_BEZIER) { + + /* tellen */ + len= 0; + a= nu->pntsu-1; + if(nu->flagu & 1) a++; + + prevbezt= nu->bezt; + bezt= prevbezt+1; + while(a--) { + if(a==0 && (nu->flagu & 1)) bezt= nu->bezt; + + if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++; + else len+= nu->resolu; + + if(a==0 && (nu->flagu & 1)==0) len++; + + prevbezt= bezt; + bezt++; + } + + dl= MEM_callocN(sizeof(DispList), "makeDispListbez"); + /* len+1 i.v.m. maakbez */ + dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts= 1; + dl->nr= len; + dl->col= nu->mat_nr; + + data= dl->verts; + + if(nu->flagu & 1) { + dl->type= DL_POLY; + a= nu->pntsu; + } + else { + dl->type= DL_SEGM; + a= nu->pntsu-1; + } + + prevbezt= nu->bezt; + bezt= prevbezt+1; + + while(a--) { + if(a==0 && dl->type== DL_POLY) bezt= nu->bezt; + + if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) { + VECCOPY(data, prevbezt->vec[1]); + data+= 3; + } + else { + v1= prevbezt->vec[1]; + v2= bezt->vec[0]; + maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu); + maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu); + if((nu->type & 8)==0) + maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu); + data+= 3*nu->resolu; + } + + if(a==0 && dl->type==DL_SEGM) { + VECCOPY(data, bezt->vec[1]); + } + + prevbezt= bezt; + bezt++; + } + } + else if((nu->type & 7)==CU_NURBS) { + len= nu->pntsu*nu->resolu; + dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts= 1; + dl->nr= len; + dl->col= nu->mat_nr; + + data= dl->verts; + if(nu->flagu & 1) dl->type= DL_POLY; + else dl->type= DL_SEGM; + makeNurbcurve(nu, data, 3); + } + else if((nu->type & 7)==CU_POLY) { + len= nu->pntsu; + dl= MEM_callocN(sizeof(DispList), "makeDispListpoly"); + dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts= 1; + dl->nr= len; + dl->col= nu->mat_nr; + + data= dl->verts; + if(nu->flagu & 1) dl->type= DL_POLY; + else dl->type= DL_SEGM; + + a= len; + bp= nu->bp; + while(a--) { + VECCOPY(data, bp->vec); + bp++; + data+= 3; + } + } + } + nu= nu->next; + } +} + + +static void filldisplist(ListBase *dispbase, ListBase *to) +{ + EditVert *eve, *v1, *vlast; + EditVlak *evl; + DispList *dlnew=0, *dl; + float *f1; + int colnr=0, cont=1, tot, a, *index; + long totvert; + + if(dispbase==0) return; + if(dispbase->first==0) return; + + /* tijd= clock(); */ + /* bit-wise and comes after == .... so this doesn't work... */ +/* if(G.f & G_PLAYANIM == 0) waitcursor(1); */ + if( !(G.f & G_PLAYANIM) ) waitcursor(1); + + while(cont) { + cont= 0; + totvert=0; + + dl= dispbase->first; + while(dl) { + + if(dl->type==DL_POLY) { + if(colnr<dl->col) cont= 1; + else if(colnr==dl->col) { + + colnr= dl->col; + + /* editverts en edges maken */ + f1= dl->verts; + a= dl->nr; + eve= v1= 0; + + while(a--) { + vlast= eve; + + eve= BLI_addfillvert(f1); + totvert++; + + if(vlast==0) v1= eve; + else { + BLI_addfilledge(vlast, eve); + } + f1+=3; + } + + if(eve!=0 && v1!=0) { + BLI_addfilledge(eve, v1); + } + } + } + dl= dl->next; + } + + /* to make edgefill work + G.obedit can be 0 on file load */ + if (G.obedit) { + BLI_setScanFillObjectRef(G.obedit); + BLI_setScanFillColourRef(&G.obedit->actcol); + } + + if(totvert && BLI_edgefill(0)!=0) { + + /* vlakken tellen */ + tot= 0; + evl= fillvlakbase.first; + while(evl) { + tot++; + evl= evl->next; + } + + if(tot) { + dlnew= MEM_callocN(sizeof(DispList), "filldisplist"); + dlnew->type= DL_INDEX3; + dlnew->col= colnr; + dlnew->nr= totvert; + dlnew->parts= tot; + + dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex"); + dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts"); + + /* vertdata */ + f1= dlnew->verts; + totvert= 0; + eve= fillvertbase.first; + while(eve) { + VECCOPY(f1, eve->co); + f1+= 3; + + /* indexnummer */ + eve->vn= (EditVert *)totvert; + totvert++; + + eve= eve->next; + } + + /* indexdata */ + evl= fillvlakbase.first; + index= dlnew->index; + while(evl) { + index[0]= (long)evl->v1->vn; + index[1]= (long)evl->v2->vn; + index[2]= (long)evl->v3->vn; + + index+= 3; + evl= evl->next; + } + } + + BLI_addhead(to, dlnew); + + } + BLI_end_edgefill(); + + colnr++; + } + + /* poly's niet vrijgeven. nodig voor wireframe display */ + + /* same as above ... */ +/* if(G.f & G_PLAYANIM == 0) waitcursor(0); */ + if( !(G.f & G_PLAYANIM) ) waitcursor(0); + /* printf("time: %d\n",(clock()-tijd)/1000); */ + +} + +static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) +{ + ListBase front, back; + DispList *dl, *dlnew; + float *fp, *fp1; + int a, dpoly; + + front.first= front.last= back.first= back.last= 0; + + if(cu->flag & CU_3D) return; + if( (cu->flag & (CU_FRONT+CU_BACK))==0 ) return; + + dl= dispbase->first; + while(dl) { + if(dl->type==DL_SURF) { + if(dl->flag==2) { + if(cu->flag & CU_BACK) { + dlnew= MEM_callocN(sizeof(DispList), "filldisp"); + BLI_addtail(&front, dlnew); + dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1"); + dlnew->nr= dl->parts; + dlnew->parts= 1; + dlnew->type= DL_POLY; + dlnew->col= dl->col; + + fp= dl->verts; + dpoly= 3*dl->nr; + + a= dl->parts; + while(a--) { + VECCOPY(fp1, fp); + fp1+= 3; + fp+= dpoly; + } + } + if(cu->flag & CU_FRONT) { + dlnew= MEM_callocN(sizeof(DispList), "filldisp"); + BLI_addtail(&back, dlnew); + dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1"); + dlnew->nr= dl->parts; + dlnew->parts= 1; + dlnew->type= DL_POLY; + dlnew->col= dl->col; + + fp= dl->verts+3*(dl->nr-1); + dpoly= 3*dl->nr; + + a= dl->parts; + while(a--) { + VECCOPY(fp1, fp); + fp1+= 3; + fp+= dpoly; + } + } + } + } + dl= dl->next; + } + + filldisplist(&front, dispbase); + filldisplist(&back, dispbase); + + freedisplist(&front); + freedisplist(&back); + + filldisplist(dispbase, dispbase); + +} + +void curve_to_filledpoly(Curve *cu, ListBase *dispbase) +{ + DispList *dl; + Nurb *nu; + + dl= dispbase->first; + + if(cu->flag & CU_3D) return; + + nu= cu->nurb.first; + while(nu) { + if(nu->flagu & CU_CYCLIC) break; + nu= nu->next; + } + if(nu==0) return; + + if(dl->type==DL_SURF) bevels_to_filledpoly(cu, dispbase); + else { + if(cu->flag & CU_FRONT) filldisplist(dispbase, dispbase); + } +} + + +static int dl_onlyzero= 0; + +void set_displist_onlyzero(int val) +{ + dl_onlyzero= val; +} + +void makeDispList(Object *ob) +{ + Mesh *me; + Nurb *nu; + Curve *cu; + BPoint *bp; + ListBase dlbev, *dispbase; + DispList *dl, *dlb; + BevList *bl; + BevPoint *bevp; + float *data, *fp1, widfac, vec[3]; + int len, a, b, draw=0; + + if(ob==0) return; + if(ob->flag & OB_FROMDUPLI) return; + freedisplist(&(ob->disp)); + + if(ob->type==OB_MESH) { + me= ob->data; + + freedisplist(&(me->disp)); + + tex_space_mesh(ob->data); + + object_deform(ob); + + if(ob->effect.first) object_wave(ob); + + if ((me->flag & ME_SUBSURF) && me->subdiv>0) { + if (ob==G.obedit) + subsurf_make_editmesh(ob); + else + subsurf_make_mesh(ob, me->subdiv); + } + } + else if(ob->type==OB_MBALL) { + ob= find_basis_mball(ob); + + metaball_polygonize(ob); + tex_space_mball(ob); + } + else if(ob->type==OB_SURF) { + + draw= ob->dt; + cu= ob->data; + dispbase= &(cu->disp); + if(dl_onlyzero && dispbase->first) return; + freedisplist(dispbase); + + if(ob==G.obedit) nu= editNurb.first; + else nu= cu->nurb.first; + + while(nu) { + if(nu->hide==0) { + if(nu->pntsv==1) { + if(draw==0) len= nu->pntsu; + else len= nu->pntsu*nu->resolu; + + dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); + + BLI_addtail(dispbase, dl); + dl->parts= 1; + dl->nr= len; + dl->col= nu->mat_nr; + + data= dl->verts; + if(nu->flagu & 1) dl->type= DL_POLY; + else dl->type= DL_SEGM; + + if(draw==0) { + bp= nu->bp; + while(len--) { + VECCOPY(data, bp->vec); + bp++; + data+= 3; + } + } + else makeNurbcurve(nu, data, 3); + } + else { + if(draw==0 && ob==G.obedit) ; + else { + if(draw==0) len= nu->pntsu*nu->pntsv; + else len= nu->resolu*nu->resolv; + + dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); + BLI_addtail(dispbase, dl); + + if(draw==0) { + dl->parts= nu->pntsv; + dl->nr= nu->pntsu; + if(nu->flagu & 1) dl->flag|= 1; + if(nu->flagv & 1) dl->flag|= 2; + } + else { + dl->parts= nu->resolu; /* andersom want makeNurbfaces gaat zo */ + dl->nr= nu->resolv; + if(nu->flagv & 1) dl->flag|= 1; /* ook andersom ! */ + if(nu->flagu & 1) dl->flag|= 2; + } + dl->col= nu->mat_nr; + + data= dl->verts; + dl->type= DL_SURF; + + if(draw==0) { + bp= nu->bp; + while(len--) { + VECCOPY(data, bp->vec); + bp++; + data+= 3; + } + } + else makeNurbfaces(nu, data); + } + } + } + nu= nu->next; + } + + tex_space_curve(cu); + + if(ob!=G.obedit) object_deform(ob); + } + else if ELEM(ob->type, OB_CURVE, OB_FONT) { + + draw= ob->dt; + cu= ob->data; + dispbase= &(cu->disp); + if(dl_onlyzero && dispbase->first) return; + freedisplist(dispbase); + + if(cu->path) free_path(cu->path); + cu->path= 0; + + BLI_freelistN(&(cu->bev)); + + if(ob==G.obedit) { + if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase); + else curve_to_displist(&cu->nurb, dispbase); + if(cu->flag & CU_PATH) makeBevelList(ob); + } + else if(cu->ext1==0.0 && cu->ext2==0.0 && cu->bevobj==0 && cu->width==1.0) { + curve_to_displist(&cu->nurb, dispbase); + if(cu->flag & CU_PATH) makeBevelList(ob); + } + else { + + makeBevelList(ob); + + dlbev.first= dlbev.last= 0; + if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) { + if(ob->dt!=0) makebevelcurve(ob, &dlbev); + } + + /* met bevellist werken */ + widfac= cu->width-1.0; + bl= cu->bev.first; + nu= cu->nurb.first; + while(bl) { + if(dlbev.first==0) { + dl= MEM_callocN(sizeof(DispList), "makeDispListbev"); + dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts"); + BLI_addtail(dispbase, dl); + if(bl->poly!= -1) dl->type= DL_POLY; + else dl->type= DL_SEGM; + dl->parts= 1; + dl->nr= bl->nr; + dl->col= nu->mat_nr; + + a= dl->nr; + bevp= (BevPoint *)(bl+1); + data= dl->verts; + while(a--) { + data[0]= bevp->x+widfac*bevp->sina; + data[1]= bevp->y+widfac*bevp->cosa; + data[2]= bevp->z; + bevp++; + data+=3; + } + } + else { + /* voor iedere stuk van de bevel een aparte dispblok maken */ + dlb= dlbev.first; + while(dlb) { + dl= MEM_callocN(sizeof(DispList), "makeDispListbev1"); + dl->verts= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts"); + BLI_addtail(dispbase, dl); + /* dl->type= dlb->type; */ + + dl->type= DL_SURF; + dl->flag= 0; + if(dlb->type==DL_POLY) dl->flag++; + if(bl->poly>=0) dl->flag+=2; + + dl->parts= bl->nr; + dl->nr= dlb->nr; + dl->col= nu->mat_nr; + + data= dl->verts; + bevp= (BevPoint *)(bl+1); + a= bl->nr; + while(a--) { /* voor ieder punt van poly een bevelstuk maken */ + + /* roteer bevelstuk en schrijf in data */ + fp1= dlb->verts; + b= dlb->nr; + + while(b--) { + if(cu->flag & CU_3D) { + + vec[0]= fp1[1]+widfac; + vec[1]= fp1[2]; + vec[2]= 0.0; + + Mat3MulVecfl(bevp->mat, vec); + + data[0]= bevp->x+ vec[0]; + data[1]= bevp->y+ vec[1]; + data[2]= bevp->z+ vec[2]; + } + else { + data[0]= bevp->x+ (fp1[1]+widfac)*bevp->sina; + data[1]= bevp->y+ (fp1[1]+widfac)*bevp->cosa; + data[2]= bevp->z+ fp1[2]; + } + + data+=3; + fp1+=3; + } + + bevp++; + } + + dlb= dlb->next; + } + } + + bl= bl->next; + nu= nu->next; + } + + if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) { + freedisplist(&dlbev); + } + } + + if(ob!=G.obedit) object_deform(ob); + + tex_space_curve(cu); + + } +} + + +/*******************************/ +/***** OUTLINE *****/ +/*******************************/ + +typedef struct Sample{ + short x, y; +} Sample; + +typedef struct Segment{ + /* coordinaten */ + struct Segment * next, * prev; + float co[2]; +} Segment; + + + +static int dflt_in_out(struct ImBuf * ibuf, int x, int y) +{ + unsigned char * rect; + + if (ibuf == 0) return (0); + if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y || ibuf->rect == 0) return (-1); + + rect = (unsigned char *) (ibuf->rect + (y * ibuf->x) + x); + if (rect[0] > 0x81) return (1); + return(0); +} + + +static Sample * outline(struct ImBuf * ibuf, + int (*in_or_out)(struct ImBuf *, int, int)) +{ + static int dirs[8][2] = { + {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, + {1, 0}, {1, -1}, {0, -1}, {-1, -1} + }; + + int dir, x, y, in, i; + int count, sampcount; + int startx = 0, starty = 0; + Sample * samp, * oldsamp; + + /* wat erin gaat: + * 1 - plaatje waarvan outline berekent moet worden, + * 2 - pointer naar functie die bepaalt welke pixel in of uit is + */ + + if (ibuf == 0) return (0); + if (ibuf->rect == 0) return (0); + + if (in_or_out == 0) in_or_out = dflt_in_out; + in = in_or_out(ibuf, 0, 0); + + /* zoek naar eerste overgang en ga van daar uit 'zoeken' */ + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + if (in_or_out(ibuf, x, y) != in) { + /* eerste 'andere' punt gevonden !! */ + + if (x != startx) dir = 0; + else dir = 6; + + startx = x; starty = y; + count = 1; + sampcount = 2000; + samp = MEM_mallocN(sampcount * sizeof(Sample), "wire_samples"); + + do{ + samp[count].x = x; samp[count].y = y; + count++; + + if (count >= sampcount) { + oldsamp = samp; + samp = MEM_mallocN(2 * sampcount * sizeof(Sample), "wire_samples"); + memcpy(samp, oldsamp, sampcount * sizeof(Sample)); + sampcount *= 2; + MEM_freeN(oldsamp); + } + + i = 0; + while(in_or_out(ibuf, x + dirs[dir][0], y + dirs[dir][1]) == in) { + dir = (dir + 1) & 0x7; + if (i++ == 9) break; + } + + if (i >= 8) { + /* dit moet een losse punt geweest zijn */ + break; + } + + x += dirs[dir][0]; + y += dirs[dir][1]; + dir = (dir - 3) & 0x7; + } while(x != startx || y != starty); + + if (i >= 8) { + /* losse punten patch */ + MEM_freeN(samp); + } else { + count = count - 1; + samp[0].x = count >> 16; + samp[0].y = count; + return(samp); + } + } + } + } + /* printf("geen overgang \n"); */ + return(0); +} + + + +/*******************************/ +/***** WIREFRAME *****/ +/*******************************/ + + +static float DistToLine2D(short *v1, short *v2, short *v3) /* met formule van Hesse :GEEN LIJNSTUK! */ +{ + float a[2],deler; + + a[0] = v2[1]-v3[1]; + a[1] = v3[0]-v2[0]; + deler = sqrt(a[0]*a[0]+a[1]*a[1]); + if(deler == 0.0) return 0; + + return fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler; + +} + +static float ComputeMaxShpError(Sample *samp, int first, int last, int *splitPoint) + /* samp: Array of digitized points */ + /* first, last: Indices defining region */ + /* splitpoint: Point of maximum error */ +{ + int i; + float maxDist; /* Maximum error */ + float dist; /* Current error */ + + *splitPoint = (last - first + 1) / 2; + maxDist = 0.0; + + for (i = first + 1; i < last; i++) { + dist = DistToLine2D((short *)(samp+i), (short *)(samp+first), (short *)(samp+last)); + + if (dist >= maxDist) { + maxDist = dist; + *splitPoint = i; + } + } + + return (maxDist); +} + + +static void FitPoly(Sample *samp, int first, int last, float shperr, ListBase *seglist) + /* Samp: Array of digitized points */ + /* first,last: Indices of first and last pts in region */ + /* spherr: User-defined error squared */ +{ + Segment * seg; /* Control points segment*/ + float maxError; /* Maximum fitting error */ + int splitPoint; /* Point to split point set at */ + int nPts; /* Number of points in subset */ + + nPts = last - first + 1; + + /* Use heuristic if region only has two points in it */ + + seg = MEM_mallocN(sizeof(Segment), "wure_segment"); + + seg->co[0] = samp[first].x; + seg->co[1] = samp[first].y; + + if (nPts == 2) { + BLI_addtail(seglist, seg); + return; + } + + maxError = ComputeMaxShpError(samp, first, last, &splitPoint); + if (maxError < shperr) { + BLI_addtail(seglist, seg); + return; + } + + /* Fitting failed -- split at max error point and fit recursively */ + + FitPoly(samp, first, splitPoint, shperr, seglist); + FitPoly(samp, splitPoint, last, shperr, seglist); + + MEM_freeN(seg); +} + + +static void ibuf2wire(ListBase * wireframe, struct ImBuf * ibuf) +{ + int count; + Sample * samp; + + /* eerst een lijst met samples maken */ + + samp = outline(ibuf, 0); + if (samp == 0) return; + + count = (samp[0].x << 16) + samp[0].y; + if (count) FitPoly(samp, 1, count, 1.0, wireframe); /* was 3.0. Frank */ + + MEM_freeN(samp); +} + + + +void imagestodisplist(void) +{ + Base *base; + Object *ob; + Material *ma; + Tex *tex; + Mesh *me; + ListBase _wireframe, *wireframe; + DispList *dl; + Segment *seg; + float *data, xfac, yfac, xsi, ysi, vec[3]; + int tot; + + _wireframe.first= 0; + _wireframe.last= 0; + wireframe = &_wireframe; + + init_render_textures(); + + base= G.scene->base.first; + while(base) { + if(( (base->flag & SELECT) && (base->lay & G.scene->lay) ) ) { + if( base->object->type==OB_MESH) { + ob= base->object; + me= ob->data; + + ma= give_current_material(ob, 1); + + if(ma && ma->mtex[0] && ma->mtex[0]->tex) { + tex= ma->mtex[0]->tex; + + /* dit zorgt voor correct laden van nieuwe imbufs */ + externtex(ma->mtex[0], vec); + + if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) { + + ob->dtx |= OB_DRAWIMAGE; + + ibuf2wire(wireframe, tex->ima->ibuf); + + tot= 0; + seg = wireframe->first; + while (seg) { + tot++; + seg = seg->next; + } + + if(tot) { + freedisplist(&(ob->disp)); + + dl= MEM_callocN(sizeof(DispList), "makeDispListimage"); + dl->verts= MEM_callocN(3*sizeof(float)*tot, "dlverts"); + + BLI_addtail(&(ob->disp), dl); + dl->type= DL_POLY; + dl->parts= 1; + dl->nr= tot; + + xsi= 0.5*(tex->ima->ibuf->x); + ysi= 0.5*(tex->ima->ibuf->y); + xfac= me->size[0]/xsi; + yfac= me->size[1]/ysi; + + data= dl->verts; + seg = wireframe->first; + while (seg) { + data[0]= xfac*(seg->co[0]-xsi); + data[1]= yfac*(seg->co[1]-ysi); + data+= 3; + seg = seg->next; + } + BLI_freelistN(wireframe); + } + } + } + } + } + base= base->next; + } + + end_render_textures(); + + allqueue(REDRAWVIEW3D, 0); +} + +/* on frame change */ + +void test_all_displists(void) +{ + Base *base; + Object *ob; + unsigned int lay; + + /* background */ + lay= G.scene->lay; + + base= G.scene->base.first; + while(base) { + if(base->lay & lay) { + ob= base->object; + + + if(ob->type==OB_MBALL && ob->ipo) { + // find metaball object holding the displist + // WARNING: if more metaballs have IPO's the displist + // is recalculated to often... + + if(ob->disp.first == NULL) { + ob= find_basis_mball(ob); + } + + makeDispList(ob); + } + else if(ob->parent) { + + if (ob->parent->type == OB_LATTICE) + makeDispList(ob); + else if ((ob->parent->type == OB_IKA) && (ob->partype == PARSKEL)) + makeDispList(ob); +#ifdef __NLA + else if ((ob->parent->type==OB_ARMATURE) && (ob->partype == PARSKEL)) + makeDispList(ob); + +#endif + } + + if ELEM(ob->type, OB_CURVE, OB_SURF) { + if(ob!=G.obedit) { + if( ((Curve *)(ob->data))->key ) makeDispList(ob); + } + } + else if(ob->type==OB_FONT) { + Curve *cu= ob->data; + if(cu->textoncurve) { + if( ((Curve *)cu->textoncurve->data)->key ) { + text_to_curve(ob, 0); + makeDispList(ob); + } + } + } + else if(ob->type==OB_MESH) { + if(ob->effect.first) object_wave(ob); + if(ob!=G.obedit) { + if( ((Mesh *)(ob->data))->key ) makeDispList(ob); + } + } + + } + if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; + else base= base->next; + } +} + + +void boundbox_displist(Object *ob) +{ + BoundBox *bb=0; + float min[3], max[3]; + DispList *dl; + float *vert; + int a, tot=0; + + INIT_MINMAX(min, max); + + if(ob->type==OB_MESH) { + Mesh *me= ob->data; + + dl= find_displist(&ob->disp, DL_VERTS); + if(!dl) return; + + if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + bb= me->bb; + + vert= dl->verts; + for(a=0; a<dl->nr; a++, vert+=3) { + DO_MINMAX(vert, min, max); + } + } + else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + Curve *cu= ob->data; + + if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + bb= cu->bb; + + dl= cu->disp.first; + + while (dl) { + if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr; + else tot= dl->nr*dl->parts; + + vert= dl->verts; + for(a=0; a<tot; a++, vert+=3) { + DO_MINMAX(vert, min, max); + } + + dl= dl->next; + } + } + + if(bb) { + bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= min[0]; + bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= max[0]; + + bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= min[1]; + bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= max[1]; + + bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= min[2]; + bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= max[2]; + } +} + |