This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenkernel/intern/displist.c
Hans Lambermont 12315f4d0e Initial revision
2002-10-12 11:37:38 +00:00

2086 lines
45 KiB
C

/* 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];
}
}