diff options
author | Daniel Dunbar <daniel@zuster.org> | 2005-04-04 08:20:32 +0400 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2005-04-04 08:20:32 +0400 |
commit | b88711b5310993873932916f92af294d3b813680 (patch) | |
tree | 689812d67eaf76824be0d10cc8cd1ec513d610ba /source/blender | |
parent | 0b02d592b8d3c665aceba5c4665326c3fc80aa1c (diff) |
- moved subsurf_calculate_limit_positions to using ccgsubsurf
- removed ME_CCG_SUBSURF define
- dropped CCGSubSurf from editing menu... subsurf is always
CCG now.
NOTE: If you saved a file with CCGSubSurf set on the button
will show up blank (will still work as a subsurf). Just change
type back to Catmull-Clark.
Wave bye-bye to HyperMesh...
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/subsurf.c | 1126 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 44 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_mesh_types.h | 1 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 2 |
4 files changed, 45 insertions, 1128 deletions
diff --git a/source/blender/blenkernel/intern/subsurf.c b/source/blender/blenkernel/intern/subsurf.c deleted file mode 100644 index 7359555da45..00000000000 --- a/source/blender/blenkernel/intern/subsurf.c +++ /dev/null @@ -1,1126 +0,0 @@ - -/* subsurf.c - * - * jun 2001 - * - * - * $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 ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <math.h> -#include "MEM_guardedalloc.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" - -#include "BKE_bad_level_calls.h" -#include "BKE_global.h" -#include "BKE_mesh.h" -#include "BKE_subsurf.h" -#include "BKE_displist.h" -#include "BKE_DerivedMesh.h" - -#include "BLI_blenlib.h" -#include "BLI_editVert.h" -#include "BLI_arithb.h" -#include "BLI_linklist.h" -#include "BLI_memarena.h" - -/* - * TODO - * - * make uvco's && vcol's properly subdivided - * - requires moving uvco and vcol data to vertices - * (where it belongs?), or making sharedness explicit - * remove/integrate zsl functions - * clean up uvco && vcol stuff - * add option to update subsurf only after done transverting - * decouple display subdivlevel and render subdivlevel - * look into waves/particles with subsurfs - * groan... make it work with sticky? - * U check if storing tfaces (clut, tpage) in a displist is - * going to be a mem problem (for example, on duplicate) - * U write game blender convert routine - * U thorough rendering check + background - * - */ - -/****/ - -static float *Vec2Cpy(float *t, float *a) { - t[0]= a[0]; - t[1]= a[1]; - return t; -} -static float *Vec3Cpy(float *t, float *a) { - t[0]= a[0]; - t[1]= a[1]; - t[2]= a[2]; - return t; -} - -static float *Vec2CpyI(float *t, float x, float y) { - t[0]= x; - t[1]= y; - return t; -} -static float *Vec3CpyI(float *t, float x, float y, float z) { - t[0]= x; - t[1]= y; - t[2]= z; - return t; -} - -static float *Vec2AvgT(float *t, float *a, float *b) { - t[0]= (a[0]+b[0])*0.5f; - t[1]= (a[1]+b[1])*0.5f; - return t; -} -static float *Vec3AvgT(float *t, float *a, float *b) { - t[0]= (a[0]+b[0])*0.5f; - t[1]= (a[1]+b[1])*0.5f; - t[2]= (a[2]+b[2])*0.5f; - return t; -} - -static float *Vec3AddT(float *t, float *a, float *b) { - t[0]= a[0]+b[0]; - t[1]= a[1]+b[1]; - t[2]= a[2]+b[2]; - return t; -} -static float *Vec2Add(float *ta, float *b) { - ta[0]+= b[0]; - ta[1]+= b[1]; - return ta; -} - - -static float *Vec3MulNT(float *t, float *a, float n) { - t[0]= a[0]*n; - t[1]= a[1]*n; - t[2]= a[2]*n; - return t; -} - -static float *Vec3Add(float *ta, float *b) { - ta[0]+= b[0]; - ta[1]+= b[1]; - ta[2]+= b[2]; - return ta; -} - -static float *Vec2MulN(float *ta, float n) { - ta[0]*= n; - ta[1]*= n; - return ta; -} -static float *Vec3MulN(float *ta, float n) { - ta[0]*= n; - ta[1]*= n; - ta[2]*= n; - return ta; -} - -/****/ - -typedef struct _HyperVert HyperVert; -typedef struct _HyperEdge HyperEdge; -typedef struct _HyperFace HyperFace; -typedef struct _HyperMesh HyperMesh; - -struct _HyperVert { - HyperVert *next; - - float co[3]; - EditVert *orig; // if set, pointer to original vertex - HyperVert *nmv; - LinkNode *edges, *faces; -}; - -/* hyper edge flags */ -#define DR_OPTIM 1 -#define HE_SEAM 2 - -struct _HyperEdge { - HyperEdge *next; - - HyperVert *v[2]; - HyperVert *ep; - int flag; // added for drawing optimal - float sharp; // sharpness weight - EditEdge *ee; // for selection state - LinkNode *faces; -}; - -struct _HyperFace { - HyperFace *next; - - int nverts; - HyperVert **verts; - HyperEdge **edges; - - HyperVert *mid; - - unsigned char (*vcol)[4]; - float (*uvco)[2]; - short unwrap; - - /* for getting back tface, matnr, etc */ - union { - int ind; - EditFace *ef; - } orig; -}; - -struct _HyperMesh { - HyperVert *verts; - HyperEdge *edges; - HyperFace *faces; - HyperFace *lastface; // we add faces in same order they get delivered now (ton) - Mesh *orig_me; - short hasuvco, hasvcol; - - MemArena *arena; -}; - -/***/ - -static HyperEdge *hypervert_find_edge(HyperVert *v, HyperVert *to) { - LinkNode *l; - - for (l= v->edges; l; l= l->next) { - HyperEdge *e= l->link; - - if ((e->v[0]==v&&e->v[1]==to) || (e->v[1]==v&&e->v[0]==to)) - return e; - } - - return NULL; -} - -static int hyperedge_is_boundary(HyperEdge *e) { - /* len(e->faces) <= 1 */ - return (!e->faces || !e->faces->next); -} - -static int hypervert_is_boundary(HyperVert *v) { - LinkNode *l; - - for (l= v->edges; l; l= l->next) - if (hyperedge_is_boundary(l->link)) - return 1; - - return 0; -} - -static HyperVert *hyperedge_other_vert(HyperEdge *e, HyperVert *a) { - return (a==e->v[0])?e->v[1]:e->v[0]; -} - -static HyperVert *hypermesh_add_vert(HyperMesh *hme, float *co, EditVert *orig) { - HyperVert *hv= BLI_memarena_alloc(hme->arena, sizeof(*hv)); - - hv->nmv= NULL; - hv->edges= NULL; - hv->faces= NULL; - - Vec3Cpy(hv->co, co); - hv->orig= orig; - - hv->next= hme->verts; - hme->verts= hv; - - return hv; -} - -static HyperEdge *hypermesh_add_edge(HyperMesh *hme, - HyperVert *v1, HyperVert *v2, int flag, float sharp, EditEdge *ee) { - HyperEdge *he= BLI_memarena_alloc(hme->arena, sizeof(*he)); - - BLI_linklist_prepend_arena(&v1->edges, he, hme->arena); - BLI_linklist_prepend_arena(&v2->edges, he, hme->arena); - - he->v[0]= v1; - he->v[1]= v2; - he->ep= NULL; - he->faces= NULL; - he->sharp = sharp; - he->flag= flag; - he->ee= ee; - - he->next= hme->edges; - hme->edges= he; - - return he; -} - -static HyperFace *hypermesh_add_face(HyperMesh *hme, HyperVert **verts, int nverts, int flag) { - HyperFace *f= BLI_memarena_alloc(hme->arena, sizeof(*f)); - HyperVert *last; - int j; - - f->mid= NULL; - f->vcol= NULL; - f->uvco= NULL; - - f->nverts= nverts; - f->verts= BLI_memarena_alloc(hme->arena, sizeof(*f->verts)*f->nverts); - f->edges= BLI_memarena_alloc(hme->arena, sizeof(*f->edges)*f->nverts); - - last= verts[nverts-1]; - for (j=0; j<nverts; j++) { - HyperVert *v= verts[j]; - HyperEdge *e= hypervert_find_edge(v, last); - - if (!e) - e= hypermesh_add_edge(hme, v, last, flag, 0, NULL); - - f->verts[j]= v; - f->edges[j]= e; - - BLI_linklist_prepend_arena(&v->faces, f, hme->arena); - BLI_linklist_prepend_arena(&e->faces, f, hme->arena); - - last= v; - } - - // less elegant, but for many reasons i prefer the order of faces to remain same (vpaint etc) (ton) - f->next= NULL; - if(hme->lastface) hme->lastface->next= f; - else hme->faces= f; - hme->lastface= f; - - return f; -} - -static HyperMesh *hypermesh_new(void) { - HyperMesh *hme= MEM_mallocN(sizeof(*hme), "hme"); - - hme->verts= NULL; - hme->edges= NULL; - hme->faces= hme->lastface= NULL; - hme->orig_me= NULL; - hme->hasuvco= hme->hasvcol= 0; - hme->arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); - - return hme; -} - -static HyperMesh *hypermesh_from_mesh(Mesh *me, int subdivLevels) { - HyperMesh *hme= hypermesh_new(); - HyperVert **vert_tbl; - MFace *mface= me->mface; - MEdge *medge= me->medge; - float creasefac= ((float)subdivLevels)/255.0; // in Mesh sharpness is byte - int i, j, flag; - - hme->orig_me= me; - if (me->tface) - hme->hasvcol= hme->hasuvco= 1; - else if (me->mcol) - hme->hasvcol= 1; - - vert_tbl= MEM_mallocN(sizeof(*vert_tbl)*me->totvert, "vert_tbl"); - - for (i= 0; i<me->totvert; i++) { - vert_tbl[i]= hypermesh_add_vert(hme, me->mvert[i].co, NULL); - } - - if(medge) { - for (i=0; i<me->totedge; i++) { - MEdge *med= &medge[i]; - - flag= DR_OPTIM; - if(med->flag & ME_SEAM) flag |= HE_SEAM; - - hypermesh_add_edge(hme, vert_tbl[med->v1], vert_tbl[med->v2], flag, - creasefac*((float)med->crease), NULL); - } - } - - for (i=0; i<me->totface; i++) { - MFace *mf= &mface[i]; - - if (mf->v3) { - int nverts= mf->v4?4:3; - HyperVert *verts[4]; - HyperFace *f; - - verts[0]= vert_tbl[mf->v1]; - verts[1]= vert_tbl[mf->v2]; - verts[2]= vert_tbl[mf->v3]; - if (nverts>3) - verts[3]= vert_tbl[mf->v4]; - - f= hypermesh_add_face(hme, verts, nverts, DR_OPTIM); - f->orig.ind= i; - - if (hme->hasuvco) { - TFace *tf= &((TFace*) me->tface)[i]; - - f->uvco= BLI_memarena_alloc(hme->arena, sizeof(*f->uvco)*nverts); - for (j=0; j<nverts; j++) - Vec2Cpy(f->uvco[j], tf->uv[j]); - - f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts); - for (j=0; j<nverts; j++) - *((unsigned int*) f->vcol[j])= tf->col[j]; - - f->unwrap= tf->unwrap; - } else if (hme->hasvcol) { - MCol *mcol= &me->mcol[i*4]; - - f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts); - for (j=0; j<nverts; j++) - *((unsigned int*) f->vcol[j])= *((unsigned int*) &mcol[j]); - } - } else if(medge==NULL) { - hypermesh_add_edge(hme, vert_tbl[mf->v1], vert_tbl[mf->v2], DR_OPTIM, 0.0, NULL); - } - } - - MEM_freeN(vert_tbl); - - return hme; -} - -static HyperMesh *hypermesh_from_editmesh(EditMesh *em, int subdivLevels) { - HyperMesh *hme= hypermesh_new(); - EditVert *ev, *prevev; - EditEdge *ee; - EditFace *ef; - float creasefac= (float)subdivLevels; - int flag; - - /* hide flags rule: - - face hidden, not do. is easy - - edge hidden, always means face is hidden too - - vertex hidden, always means edge is hidden too - */ - - /* we only add vertices with edges, 'f1' is a free flag */ - /* added: check for hide flag in vertices */ - for (ev= em->verts.first; ev; ev= ev->next) { - ev->f1= 1; - ev->prev= NULL; - } - - /* hack, tuck the new hypervert pointer into - * the ev->prev link so we can find it easy, - * then restore real prev links later. - */ - for (ee= em->edges.first; ee; ee= ee->next) { - - if(ee->v1->f1) { - ee->v1->prev= (EditVert*) hypermesh_add_vert(hme, ee->v1->co, ee->v1); - ee->v1->f1= 0; - } - if(ee->v2->f1) { - ee->v2->prev= (EditVert*) hypermesh_add_vert(hme, ee->v2->co, ee->v2); - ee->v2->f1= 0; - } - if((ee->h & 1)==0) { - - flag= DR_OPTIM; - if(ee->seam) flag |= HE_SEAM; - - hypermesh_add_edge(hme, (HyperVert*) ee->v1->prev, (HyperVert*) ee->v2->prev, flag, - creasefac*ee->crease, ee); - } - } - for (ef= em->faces.first; ef; ef= ef->next) { - if(ef->h==0) { - int nverts= ef->v4?4:3; - HyperVert *verts[4]; - HyperFace *f; - - verts[0]= (HyperVert*) ef->v1->prev; - verts[1]= (HyperVert*) ef->v2->prev; - verts[2]= (HyperVert*) ef->v3->prev; - if (nverts>3) - verts[3]= (HyperVert*) ef->v4->prev; - - f= hypermesh_add_face(hme, verts, nverts, DR_OPTIM); - f->orig.ef= ef; - } - } - - /* see hack above, restore the prev links */ - for (prevev= NULL, ev= em->verts.first; ev; prevev= ev, ev= ev->next) - ev->prev= prevev; - - return hme; -} - -static void VColAvgT(unsigned char *t, unsigned char *a, unsigned char *b) { - t[0]= (a[0]+b[0])>>1; - t[1]= (a[1]+b[1])>>1; - t[2]= (a[2]+b[2])>>1; - t[3]= (a[3]+b[3])>>1; -} - -static void hypermesh_calc_sharp_edge(HyperEdge *e, float co[3]) -{ - Vec3AvgT(co, e->v[0]->co, e->v[1]->co); -} - -static void hypermesh_calc_smooth_edge(HyperEdge *e, float co[3]) -{ - int count; - LinkNode *link; - HyperFace *f; - - Vec3AddT(co, e->v[0]->co, e->v[1]->co); - for (count=2, link= e->faces; link; count++, link= link->next) { - f= (HyperFace *) link->link; - Vec3Add(co, f->mid->co); - } - Vec3MulN(co, (float)(1.0/count)); -} - -static void hypermesh_lininterp_vert(float co[3], float co1[3], float co2[3], float w) -{ - float codiff[3]; - - codiff[0] = co2[0] - co1[0]; - codiff[1] = co2[1] - co1[1]; - codiff[2] = co2[2] - co1[2]; - - Vec3MulN(codiff, w); - - Vec3AddT(co, co1, codiff); -} - -static void hypermesh_calc_interp_edge(HyperEdge *e, float co[3]) -{ - float co1[3]; - float co2[3]; - - hypermesh_calc_smooth_edge(e, co1); - hypermesh_calc_sharp_edge(e, co2); - - hypermesh_lininterp_vert(co, co1, co2, e->sharp); -} - - -static void hypermesh_calc_smooth_vert(HyperVert *v, float co[3]) -{ - float q[3], r[3], s[3]; - LinkNode *link; - HyperFace *f; - HyperEdge *e; - int count = 0; - - if (hypervert_is_boundary(v)) { - Vec3CpyI(r, 0.0, 0.0, 0.0); - - for (count= 0, link= v->edges; link; link= link->next) { - if (hyperedge_is_boundary(link->link)) { - HyperVert *ov= hyperedge_other_vert(link->link, v); - - Vec3Add(r, ov->co); - count++; - } - } - - /* I believe CC give the factors as - 3/2k and 1/4k, but that doesn't make - sense (to me) as they don't sum to unity... - It's rarely important. - */ - Vec3MulNT(s, v->co, 0.75f); - Vec3Add(s, Vec3MulN(r, (float)(1.0/(4.0*count)))); - } else { - Vec3Cpy(q, Vec3Cpy(r, Vec3CpyI(s, 0.0f, 0.0f, 0.0f))); - - for (count=0, link= v->faces; link; count++, link= link->next) { - f= (HyperFace *) link->link; - Vec3Add(q, f->mid->co); - } - Vec3MulN(q, (float)(1.0/count)); - - for (count=0, link= v->edges; link; count++, link= link->next) { - e= (HyperEdge *) link->link; - Vec3Add(r, hyperedge_other_vert(e, v)->co); - } - Vec3MulN(r, (float)(1.0/count)); - - Vec3MulNT(s, v->co, (float)(count-2)); - - Vec3Add(s, q); - Vec3Add(s, r); - Vec3MulN(s, (float)(1.0/count)); - } - - Vec3Cpy(co, s); - -} - -static void hypermesh_calc_creased_vert(HyperVert *v, float co[3], float w) -{ - LinkNode *l; - float epSum[3] = {0,0,0}; - int count = 0; - - /* use the crease rule */ - for (l= v->edges; l; l= l->next) { - HyperEdge *he = l->link; - if (he->sharp != 0.0) { - HyperVert *oV = hyperedge_other_vert(he, v); - epSum[0] += oV->co[0]; - epSum[1] += oV->co[1]; - epSum[2] += oV->co[2]; - count++; - } - } - - epSum[0] /= count; - epSum[1] /= count; - epSum[2] /= count; - - if (count!=2) { - epSum[0] = epSum[0] + (v->co[0] - epSum[0])*w; - epSum[1] = epSum[1] + (v->co[1] - epSum[1])*w; - epSum[2] = epSum[2] + (v->co[2] - epSum[2])*w; - } - - co[0] = (3.0 * v->co[0] + epSum[0]) / 4.0; - co[1] = (3.0 * v->co[1] + epSum[1]) / 4.0; - co[2] = (3.0 * v->co[2] + epSum[2]) / 4.0; -} - -static void hypermesh_calc_interp_vert(HyperVert *v, float co[3], float w) -{ - float co1[3]; - float co2[3]; - - hypermesh_calc_smooth_vert(v, co1); - hypermesh_calc_creased_vert(v, co2, w); - - hypermesh_lininterp_vert(co, co1, co2, w); -} - -static void hypermesh_subdivide(HyperMesh *me, HyperMesh *nme) { - HyperVert *v; - HyperEdge *e; - HyperFace *f; - LinkNode *link; - float co[3]; - int j, k; - - for (f= me->faces; f; f= f->next) { - Vec3CpyI(co, 0.0, 0.0, 0.0); - for (j=0; j<f->nverts; j++) - Vec3Add(co, f->verts[j]->co); - Vec3MulN(co, (float)(1.0/f->nverts)); - - f->mid= hypermesh_add_vert(nme, co, NULL); - } - - for (e= me->edges; e; e= e->next) { - if (hyperedge_is_boundary(e) || (e->sharp > 1.0)) { - hypermesh_calc_sharp_edge(e, co); - } - else { - hypermesh_calc_interp_edge(e, co); - } - - e->ep= hypermesh_add_vert(nme, co, NULL); - } - - for (v= me->verts; v; v= v->next) { - float s[3]; - int sharpcnt = 0; - float avgw = 0.0; - - /* count the sharp edges */ - for (link= v->edges; link; link= link->next) { - if (((HyperEdge *)link->link)->sharp != 0.0) { - sharpcnt++; - avgw += ((HyperEdge *)link->link)->sharp; - } - } - - avgw /= (float)sharpcnt; - if (avgw > 1.0) - avgw = 1.0; - - switch (sharpcnt) { - case 0: - case 1: - hypermesh_calc_smooth_vert(v, s); - break; - case 2: - default: - hypermesh_calc_interp_vert(v, s, avgw); - break; - } - - v->nmv= hypermesh_add_vert(nme, s, v->orig); - } - - for (e= me->edges; e; e= e->next) { - hypermesh_add_edge(nme, e->v[0]->nmv, e->ep, e->flag, e->sharp>1.0?e->sharp-1.0:0.0, e->ee); - hypermesh_add_edge(nme, e->v[1]->nmv, e->ep, e->flag, e->sharp>1.0?e->sharp-1.0:0.0, e->ee); - } - - for (f= me->faces; f; f= f->next) { - int last= f->nverts-1; - unsigned char vcol_mid[4]; - unsigned char vcol_edge[4][4]; - float uvco_mid[2]; - float uvco_edge[4][4]; - - if (me->hasvcol) { - int t[4]= {0, 0, 0, 0}; - for (j=0; j<f->nverts; j++) { - t[0]+= f->vcol[j][0]; - t[1]+= f->vcol[j][1]; - t[2]+= f->vcol[j][2]; - t[3]+= f->vcol[j][3]; - } - vcol_mid[0]= t[0]/f->nverts; - vcol_mid[1]= t[1]/f->nverts; - vcol_mid[2]= t[2]/f->nverts; - vcol_mid[3]= t[3]/f->nverts; - - for (j=0; j<f->nverts; last= j, j++) - VColAvgT(vcol_edge[j], f->vcol[last], f->vcol[j]); - last= f->nverts-1; - } - if (me->hasuvco) { - Vec2CpyI(uvco_mid, 0.0, 0.0); - for (j=0; j<f->nverts; j++) - Vec2Add(uvco_mid, f->uvco[j]); - Vec2MulN(uvco_mid, (float)(1.0/f->nverts)); - - for (j=0; j<f->nverts; last= j, j++) - Vec2AvgT(uvco_edge[j], f->uvco[last], f->uvco[j]); - last= f->nverts-1; - } - - for (j=0; j<f->nverts; last=j, j++) { - HyperVert *nv[4]; - HyperFace *nf; - - nv[0]= f->verts[last]->nmv; - nv[1]= f->edges[j]->ep; - nv[2]= f->mid; - nv[3]= f->edges[last]->ep; - - nf= hypermesh_add_face(nme, nv, 4, 0); - nf->orig= f->orig; - - if (me->hasvcol) { - nf->vcol= BLI_memarena_alloc(nme->arena, sizeof(*nf->vcol)*4); - - for (k=0; k<4; k++) { - nf->vcol[0][k]= f->vcol[last][k]; - nf->vcol[1][k]= vcol_edge[j][k]; - nf->vcol[2][k]= vcol_mid[k]; - nf->vcol[3][k]= vcol_edge[last][k]; - } - } - if (me->hasuvco) { - nf->uvco= BLI_memarena_alloc(nme->arena, sizeof(*nf->uvco)*4); - - Vec2Cpy(nf->uvco[0], f->uvco[last]); - Vec2Cpy(nf->uvco[1], uvco_edge[j]); - Vec2Cpy(nf->uvco[2], uvco_mid); - Vec2Cpy(nf->uvco[3], uvco_edge[last]); - - if(j==0 && (f->unwrap & ((f->nverts==4)?TF_PIN4:TF_PIN3))) - nf->unwrap= TF_PIN1; - else if(j==1 && f->unwrap & TF_PIN1) nf->unwrap= TF_PIN1; - else if(j==2 && f->unwrap & TF_PIN2) nf->unwrap= TF_PIN1; - else if(j==3 && f->unwrap & TF_PIN3) nf->unwrap= TF_PIN1; - else nf->unwrap= 0; - } - } - } -} - -/* Simple subdivision surface for radio and displacement */ -static void hypermesh_simple_subdivide(HyperMesh *me, HyperMesh *nme) { - HyperVert *v; - HyperEdge *e; - HyperFace *f; - float co[3]; - int j, k; - - for (f= me->faces; f; f= f->next) { /* Adds vert at center of each existing face */ - Vec3CpyI(co, 0.0, 0.0, 0.0); - for (j=0; j<f->nverts; j++) Vec3Add(co, f->verts[j]->co); - Vec3MulN(co, (float)(1.0/f->nverts)); - - f->mid= hypermesh_add_vert(nme, co, NULL); - } - - for (e= me->edges; e; e= e->next) { /* Add vert in middle of each edge */ - Vec3AvgT(co, e->v[0]->co, e->v[1]->co); - e->ep= hypermesh_add_vert(nme, co, NULL); - } - - for (v= me->verts; v; v= v->next) { - v->nmv= hypermesh_add_vert(nme, v->co, v->orig); - } - - for (e= me->edges; e; e= e->next) { /* Add original edges */ - hypermesh_add_edge(nme, e->v[0]->nmv, e->ep, e->flag, 0.0, e->ee); - hypermesh_add_edge(nme, e->v[1]->nmv, e->ep, e->flag, 0.0, e->ee); - } - - for (f= me->faces; f; f= f->next) { - int last= f->nverts-1; - unsigned char vcol_mid[4]; - unsigned char vcol_edge[4][4]; - float uvco_mid[2]; - float uvco_edge[4][4]; - - if (me->hasvcol) { - int t[4]= {0, 0, 0, 0}; - for (j=0; j<f->nverts; j++) { - t[0]+= f->vcol[j][0]; - t[1]+= f->vcol[j][1]; - t[2]+= f->vcol[j][2]; - t[3]+= f->vcol[j][3]; - } - vcol_mid[0]= t[0]/f->nverts; - vcol_mid[1]= t[1]/f->nverts; - vcol_mid[2]= t[2]/f->nverts; - vcol_mid[3]= t[3]/f->nverts; - - for (j=0; j<f->nverts; last= j, j++) - VColAvgT(vcol_edge[j], f->vcol[last], f->vcol[j]); - last= f->nverts-1; - } - if (me->hasuvco) { - Vec2CpyI(uvco_mid, 0.0, 0.0); - for (j=0; j<f->nverts; j++) - Vec2Add(uvco_mid, f->uvco[j]); - Vec2MulN(uvco_mid, (float)(1.0/f->nverts)); - - for (j=0; j<f->nverts; last= j, j++) - Vec2AvgT(uvco_edge[j], f->uvco[last], f->uvco[j]); - last= f->nverts-1; - } - - for (j=0; j<f->nverts; last=j, j++) { - HyperVert *nv[4]; - HyperFace *nf; - - nv[0]= f->verts[last]->nmv; - nv[1]= f->edges[j]->ep; - nv[2]= f->mid; - nv[3]= f->edges[last]->ep; - - nf= hypermesh_add_face(nme, nv, 4, 0); - nf->orig= f->orig; - - if (me->hasvcol) { - nf->vcol= BLI_memarena_alloc(nme->arena, sizeof(*nf->vcol)*4); - - for (k=0; k<4; k++) { - nf->vcol[0][k]= f->vcol[last][k]; - nf->vcol[1][k]= vcol_edge[j][k]; - nf->vcol[2][k]= vcol_mid[k]; - nf->vcol[3][k]= vcol_edge[last][k]; - } - } - if (me->hasuvco) { - nf->uvco= BLI_memarena_alloc(nme->arena, sizeof(*nf->uvco)*4); - - Vec2Cpy(nf->uvco[0], f->uvco[last]); - Vec2Cpy(nf->uvco[1], uvco_edge[j]); - Vec2Cpy(nf->uvco[2], uvco_mid); - Vec2Cpy(nf->uvco[3], uvco_edge[last]); - } - } - } -} - - -static void hypermesh_free(HyperMesh *me) { - BLI_memarena_free(me->arena); - - MEM_freeN(me); -} - -/*****/ - -static int hypermesh_get_nverts(HyperMesh *hme) { - HyperVert *v; - int count= 0; - - for (v= hme->verts; v; v= v->next) - count++; - - return count; -} - -static int hypermesh_get_nfaces(HyperMesh *hme) { - HyperFace *f; - int count= 0; - - for (f= hme->faces; f; f= f->next) - count++; - - return count; -} - -static int hypermesh_get_nedges(HyperMesh *hme) { - HyperEdge *e; - int count= 0; - - for (e= hme->edges; e; e= e->next) - count++; - - return count; -} - -/* flag is me->flag, for 'optim' */ -static DispListMesh *hypermesh_to_displistmesh(HyperMesh *hme) { - int nverts= hypermesh_get_nverts(hme); - int nedges= hypermesh_get_nedges(hme); - int nfaces= hypermesh_get_nfaces(hme); - DispListMesh *dlm= MEM_callocN(sizeof(*dlm), "dlmesh"); - HyperFace *f; - HyperVert *v; - HyperEdge *e; - TFace *tfaces; - MEdge *med; - MFace *mfaces, *mf; - int i, j; - - /* hme->orig_me==NULL if we are working on an editmesh */ - if (hme->orig_me) { - tfaces= hme->orig_me->tface; - mfaces= hme->orig_me->mface; - } else { - tfaces= NULL; - mfaces= NULL; - } - - /* removed: handles for editmode. it now stores pointer to subsurfed vertex in editvert */ - dlm->totvert= nverts; - dlm->totface= nfaces; - dlm->totedge= nedges; - - /* calloc for clear flag and nor in mvert */ - dlm->mvert= MEM_callocN(dlm->totvert*sizeof(*dlm->mvert), "dlm->mvert"); - dlm->medge= MEM_callocN(dlm->totedge*sizeof(*dlm->medge), "dlm->medge"); - dlm->mface= MEM_mallocN(dlm->totface*sizeof(*dlm->mface), "dlm->mface"); - /* these two blocks for live update of selection in editmode */ - if (hme->orig_me==NULL) { - dlm->editedge= MEM_callocN(dlm->totedge*sizeof(EditEdge *), "dlm->editface"); - dlm->editface= MEM_mallocN(dlm->totface*sizeof(EditFace *), "dlm->editedge"); - } - - if (hme->hasuvco) - dlm->tface= MEM_callocN(dlm->totface*sizeof(*dlm->tface), "dlm->tface"); - else if (hme->hasvcol) - dlm->mcol= MEM_mallocN(dlm->totface*4*sizeof(*dlm->mcol), "dlm->mcol"); - - for (i=0, v= hme->verts; i<nverts; i++, v= v->next) { - MVert *mv= &dlm->mvert[i]; - Vec3Cpy(mv->co, v->co); - v->nmv= (void*) i; - } - - /* we use by default edges for displistmesh now */ - med= dlm->medge; - for (i=0, e= hme->edges; e; e= e->next, med++, i++) { - med->v1= (int) e->v[0]->nmv; - med->v2= (int) e->v[1]->nmv; - - if (hme->orig_me==NULL) dlm->editedge[i]= e->ee; - - if(e->flag & DR_OPTIM) med->flag |= ME_EDGEDRAW; - if(e->flag & HE_SEAM) med->flag |= ME_SEAM; - } - - /* and we add pointer to subsurfed vertex in editvert */ - if(hme->orig_me==NULL) { - MVert *mv= dlm->mvert; - for (v= hme->verts; v; v= v->next, mv++) { - if(v->orig) v->orig->ssco= mv->co; - } - } - - /* faces */ - mf= dlm->mface; - for (i=0, f= hme->faces; f; i++, f= f->next) { - /* There is a complicated dependancy here: - * After a subdivision the points that were shifted will always be - * first in the hme->verts list (because they are added last, but to - * the head). This means that the HVert with index 0 will always be - * a shifted vertice, and the shifted vertices (corners) are always - * HFace->verts[0]. Therefore it is guaranteed that if any vertice - * index is 0, it will always be in mf->v1, so we do not have to worry - * about tweaking the indices. - */ - mf->v1= (int) f->verts[0]->nmv; - mf->v2= (int) f->verts[1]->nmv; - mf->v3= (int) f->verts[2]->nmv; - mf->v4= (int) f->verts[3]->nmv; - - if (hme->orig_me) { - MFace *origmf= &mfaces[f->orig.ind]; - - mf->mat_nr= origmf->mat_nr; - mf->flag= origmf->flag; - mf->puno= 0; - } else { - EditFace *origef= f->orig.ef; - - mf->mat_nr= origef->mat_nr; - mf->flag= origef->flag; - mf->puno= 0; - - // for subsurf draw in editmode - dlm->editface[i]= origef; - } - - /* although not used by 3d display, still needed for wire-render */ - mf->edcode= 0; - if (f->edges[0]->flag) mf->edcode|= ME_V4V1; - if (f->edges[1]->flag) mf->edcode|= ME_V1V2; - if (f->edges[2]->flag) mf->edcode|= ME_V2V3; - if (f->edges[3]->flag) mf->edcode|= ME_V3V4; - - if (hme->hasuvco) { - TFace *origtf, *tf= &dlm->tface[i]; - - //if (hme->orig_me) - origtf= &tfaces[f->orig.ind]; - //else ton: removed, hme->hasuvco doesn't happen in editmode (yet?) - // origtf= f->orig.ef->tface; - - for (j=0; j<4; j++) { - Vec2Cpy(tf->uv[j], f->uvco[j]); - tf->col[j]= *((unsigned int*) f->vcol[j]); - } - - tf->tpage= origtf->tpage; - tf->flag= origtf->flag; - tf->transp= origtf->transp; - tf->mode= origtf->mode; - tf->tile= origtf->tile; - tf->unwrap= f->unwrap; - } else if (hme->hasvcol) { - MCol *mcolbase= &dlm->mcol[i*4]; - - for (j=0; j<4; j++) - *((unsigned int*) &mcolbase[j])= *((unsigned int*) f->vcol[j]); - } - - mf++; - } - - displistmesh_calc_normals(dlm); - - return dlm; -} - -/* flag is me->flag, and 'optim' */ -static DispListMesh *subsurf_subdivide_to_displistmesh(HyperMesh *hme, short subdiv, short type) { - DispListMesh *dlm; - int i; - - for (i= 0; i<subdiv; i++) { - HyperMesh *tmp= hypermesh_new(); - tmp->hasvcol= hme->hasvcol; - tmp->hasuvco= hme->hasuvco; - tmp->orig_me= hme->orig_me; - - if (type == ME_SIMPLE_SUBSURF) hypermesh_simple_subdivide(hme, tmp); - else hypermesh_subdivide(hme, tmp); /* default to CC subdiv. */ - - hypermesh_free(hme); - hme= tmp; - } - - dlm= hypermesh_to_displistmesh(hme); - hypermesh_free(hme); - - return dlm; -} - - // editarmature.c -void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) -{ - /* Finds the subsurf limit positions for the verts in a mesh - * and puts them in an array of floats. Please note that the - * calculated vert positions is incorrect for the verts - * on the boundary of the mesh. - */ - HyperMesh *hme= hypermesh_from_mesh(me, 1); // 1=subdivlevel - HyperMesh *nme= hypermesh_new(); - float edge_sum[3], face_sum[3]; - HyperVert *hv; - LinkNode *l; - int i; - - hypermesh_subdivide(hme, nme); - - for (i= me->totvert-1,hv=hme->verts; i>=0; i--,hv=hv->next) { - int N= 0; - - edge_sum[0]= edge_sum[1]= edge_sum[2]= 0.0; - face_sum[0]= face_sum[1]= face_sum[2]= 0.0; - - for (N=0,l=hv->edges; l; N++,l= l->next) { - Vec3Add(edge_sum, ((HyperEdge*) l->link)->ep->co); - } - for (l=hv->faces; l; l= l->next) { - Vec3Add(face_sum, ((HyperFace*) l->link)->mid->co); - } - - positions_r[i][0] = - (hv->nmv->co[0]*N*N + edge_sum[0]*4 + face_sum[0])/(N*(N+5)); - positions_r[i][1] = - (hv->nmv->co[1]*N*N + edge_sum[1]*4 + face_sum[1])/(N*(N+5)); - positions_r[i][2] = - (hv->nmv->co[2]*N*N + edge_sum[2]*4 + face_sum[2])/(N*(N+5)); - } - - hypermesh_free(nme); - hypermesh_free(hme); -} - diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 61ee4737576..7c5ca9583b3 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1017,3 +1017,47 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, int subdivLevels) { return derivedmesh_from_displistmesh(NULL, dlm); } +void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) +{ + /* Finds the subsurf limit positions for the verts in a mesh + * and puts them in an array of floats. Please note that the + * calculated vert positions is incorrect for the verts + * on the boundary of the mesh. + */ + SubSurf *ss = subSurf_fromMesh(me, 0, 1); + float edge_sum[3], face_sum[3]; + CCGVertIterator *vi; + + subSurf_sync(ss, 0); + + vi = ccgSubSurf_getVertIterator(ss->subSurf); + for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { + CCGVert *v = ccgVertIterator_getCurrent(vi); + int idx = (int) ccgSubSurf_getVertVertHandle(ss->subSurf, v); + int N = ccgSubSurf_getVertNumEdges(ss->subSurf, v); + int numFaces = ccgSubSurf_getVertNumFaces(ss->subSurf, v); + float *co; + int i; + + edge_sum[0]= edge_sum[1]= edge_sum[2]= 0.0; + face_sum[0]= face_sum[1]= face_sum[2]= 0.0; + + for (i=0; i<N; i++) { + CCGEdge *e = ccgSubSurf_getVertEdge(ss->subSurf, v, i); + VecAddf(edge_sum, edge_sum, ccgSubSurf_getEdgeData(ss->subSurf, e, 1)); + } + for (i=0; i<numFaces; i++) { + CCGFace *f = ccgSubSurf_getVertFace(ss->subSurf, v, i); + VecAddf(face_sum, face_sum, ccgSubSurf_getFaceCenterData(ss->subSurf, f)); + } + + co = ccgSubSurf_getVertData(ss->subSurf, v); + positions_r[idx][0] = (co[0]*N*N + edge_sum[0]*4 + face_sum[0])/(N*(N+5)); + positions_r[idx][1] = (co[1]*N*N + edge_sum[1]*4 + face_sum[1])/(N*(N+5)); + positions_r[idx][2] = (co[2]*N*N + edge_sum[2]*4 + face_sum[2])/(N*(N+5)); + } + ccgVertIterator_free(vi); + + subSurf_free(ss); +} + diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 965bd0de5a2..b7ef4b0f3bd 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -125,7 +125,6 @@ typedef struct Mesh { /* Subsurf Type */ #define ME_CC_SUBSURF 0 #define ME_SIMPLE_SUBSURF 1 -#define ME_CCG_SUBSURF 2 #define TF_DYNAMIC 1 /* #define TF_INVISIBLE 2 */ diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 4da27218455..a76077ce40b 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -656,7 +656,7 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me) uiBlock *block; float val; /* Hope to support more than two subsurf algorithms */ - char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|CCGSubSurf%x2|Simple Subdiv.%x1"; + char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1"; block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win); if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return; |