Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/radiosity/intern/source/radnode.c')
-rw-r--r--source/blender/radiosity/intern/source/radnode.c1095
1 files changed, 1095 insertions, 0 deletions
diff --git a/source/blender/radiosity/intern/source/radnode.c b/source/blender/radiosity/intern/source/radnode.c
new file mode 100644
index 00000000000..b75edc0c2cf
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radnode.c
@@ -0,0 +1,1095 @@
+/* ***************************************
+ *
+ * ***** 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 *****
+
+
+
+ node.c nov/dec 1992
+ may 1999
+
+ $Id$
+
+ *************************************** */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_toolbox.h"
+
+#include "radio.h"
+
+/* locals */
+void *malloc_fast(int size);
+void *calloc_fast(int size);
+void free_fast(void *poin, int siz);
+void deleteTriNodes(RNode *node);
+/* lower because of local type define */
+/* void check_mallocgroup(MallocGroup *mg); */
+
+
+/* ********** fastmalloc ************** */
+
+#define MAL_GROUPSIZE 256
+#define MAL_AVAILABLE 1
+#define MAL_FULL 2
+
+
+
+
+ListBase MallocBase= {0, 0};
+int totfastmem= 0;
+
+typedef struct MallocGroup {
+ struct MallocGroup *next, *prev;
+ short size, flag;
+ short curfree, tot;
+ char flags[MAL_GROUPSIZE];
+ char *data;
+} MallocGroup;
+
+/* one more local */
+void check_mallocgroup(MallocGroup *mg);
+
+void check_mallocgroup(MallocGroup *mg)
+{
+ int a;
+ char *cp;
+
+ if(mg->tot==MAL_GROUPSIZE) {
+ mg->flag= MAL_FULL;
+ return;
+ }
+
+ cp= mg->flags;
+
+ if(mg->curfree<MAL_GROUPSIZE-1) {
+ if(cp[mg->curfree+1]==0) {
+ mg->curfree++;
+ return;
+ }
+ }
+ if(mg->curfree>0) {
+ if(cp[mg->curfree-1]==0) {
+ mg->curfree--;
+ return;
+ }
+ }
+
+ for(a=0; a<MAL_GROUPSIZE; a++) {
+ if(cp[a]==0) {
+ mg->curfree= a;
+ return;
+ }
+ }
+ printf("fastmalloc: shouldnt be here\n");
+}
+
+void *malloc_fast(int size)
+{
+ MallocGroup *mg;
+ void *retval;
+
+ mg= MallocBase.last;
+ while(mg) {
+ if(mg->size==size) {
+ if(mg->flag & MAL_AVAILABLE) {
+ mg->flags[mg->curfree]= 1;
+ mg->tot++;
+ retval= mg->data+mg->curfree*mg->size;
+ check_mallocgroup(mg);
+ return retval;
+ }
+ }
+ mg= mg->prev;
+ }
+
+ /* no free block found */
+ mg= MEM_callocN(sizeof(MallocGroup), "mallocgroup");
+ BLI_addtail(&MallocBase, mg);
+ mg->data= MEM_mallocN(MAL_GROUPSIZE*size, "mallocgroupdata");
+ mg->flag= MAL_AVAILABLE;
+ mg->flags[0]= 1;
+ mg->curfree= 1;
+ mg->size= size;
+ mg->tot= 1;
+
+ totfastmem+= sizeof(MallocGroup)+MAL_GROUPSIZE*size;
+
+ return mg->data;
+}
+
+void *calloc_fast(int size)
+{
+ void *poin;
+
+ poin= malloc_fast(size);
+ memset(poin, 0, size);
+
+ return poin;
+}
+
+void free_fast(void *poin, int size)
+{
+ MallocGroup *mg;
+ long val;
+
+ mg= MallocBase.last;
+ while(mg) {
+ if(mg->size==size) {
+ if( ((long)poin) >= ((long)mg->data) ) {
+ if( ((long)poin) < ((long)(mg->data+MAL_GROUPSIZE*size)) ) {
+ val= ((long)poin) - ((long)mg->data);
+ val/= size;
+ mg->curfree= val;
+ mg->flags[val]= 0;
+ mg->flag= MAL_AVAILABLE;
+
+ mg->tot--;
+ if(mg->tot==0) {
+ BLI_remlink(&MallocBase, mg);
+ MEM_freeN(mg->data);
+ MEM_freeN(mg);
+ totfastmem-= sizeof(MallocGroup)+MAL_GROUPSIZE*size;
+ }
+ return;
+ }
+ }
+ }
+ mg= mg->prev;
+ }
+ printf("fast free: pointer not in memlist %p size %d\n",
+ poin, size);
+}
+
+/* security: only one function in a time can use it */
+static char *fastmallocstr= 0;
+
+void free_fastAll()
+{
+ MallocGroup *mg;
+
+ mg= MallocBase.first;
+ while(mg) {
+ BLI_remlink(&MallocBase, mg);
+ MEM_freeN(mg->data);
+ MEM_freeN(mg);
+ mg= MallocBase.first;
+ }
+ totfastmem= 0;
+ fastmallocstr= 0;
+}
+
+void start_fastmalloc(char *str)
+{
+ if(fastmallocstr) {
+ error("Fastmalloc in use: %s", fastmallocstr);
+ return;
+ }
+ fastmallocstr= str;
+}
+
+/* **************************************** */
+
+float nodelimit;
+
+void setnodelimit(float limit)
+{
+ nodelimit= limit;
+
+}
+
+/* ************ GEHEUGENBEHEER *********** */
+
+int Ntotvert=0, Ntotnode=0, Ntotpatch=0;
+
+float *mallocVert()
+{
+ Ntotvert++;
+ return (float *)malloc_fast(16);
+}
+
+float *callocVert()
+{
+ Ntotvert++;
+ return (float *)calloc_fast(16);
+}
+
+void freeVert(float *vert)
+{
+ free_fast(vert, 16);
+ Ntotvert--;
+}
+
+RNode *mallocNode()
+{
+ Ntotnode++;
+ return (RNode *)malloc_fast(sizeof(RNode));
+}
+
+RNode *callocNode()
+{
+ Ntotnode++;
+ return (RNode *)calloc_fast(sizeof(RNode));
+}
+
+void freeNode(RNode *node)
+{
+ free_fast(node, sizeof(RNode));
+ Ntotnode--;
+}
+
+void freeNode_recurs(RNode *node)
+{
+
+ if(node->down1) {
+ freeNode_recurs(node->down1);
+ freeNode_recurs(node->down2);
+ }
+
+ node->down1= node->down2= 0;
+ freeNode(node);
+
+}
+
+RPatch *mallocPatch()
+{
+ Ntotpatch++;
+ return (RPatch *)malloc_fast(sizeof(RPatch));
+}
+
+RPatch *callocPatch()
+{
+ Ntotpatch++;
+ return (RPatch *)calloc_fast(sizeof(RPatch));
+}
+
+void freePatch(RPatch *patch)
+{
+ free_fast(patch, sizeof(RPatch));
+ Ntotpatch--;
+}
+
+/* ************ SUBDIVIDE *********** */
+
+
+void replaceAllNode(RNode *neighb, RNode *newn)
+{
+ /* verandert van alle buren de edgepointers die naar newn->up wijzen in new */
+ int ok= 0;
+
+
+ if(neighb==0) return;
+ if(newn->up==0) return;
+
+ if(neighb->ed1==newn->up) {
+ neighb->ed1= newn;
+ ok= 1;
+ }
+ else if(neighb->ed2==newn->up) {
+ neighb->ed2= newn;
+ ok= 1;
+ }
+ else if(neighb->ed3==newn->up) {
+ neighb->ed3= newn;
+ ok= 1;
+ }
+ else if(neighb->ed4==newn->up) {
+ neighb->ed4= newn;
+ ok= 1;
+ }
+
+ if(ok && neighb->down1) {
+ replaceAllNode(neighb->down1, newn);
+ replaceAllNode(neighb->down2, newn);
+ }
+}
+
+void replaceAllNodeInv(RNode *neighb, RNode *old)
+{
+ /* verandert van alle buren de edgepointers die naar old wijzen in old->up */
+ if(neighb==0) return;
+ if(old->up==0) return;
+
+ if(neighb->ed1==old) {
+ neighb->ed1= old->up;
+ }
+ else if(neighb->ed2==old) {
+ neighb->ed2= old->up;
+ }
+ else if(neighb->ed3==old) {
+ neighb->ed3= old->up;
+ }
+ else if(neighb->ed4==old) {
+ neighb->ed4= old->up;
+ }
+
+ if(neighb->down1) {
+ replaceAllNodeInv(neighb->down1, old);
+ replaceAllNodeInv(neighb->down2, old);
+ }
+}
+
+void replaceAllNodeUp(RNode *neighb, RNode *old)
+{
+ /* verandert van alle buren de edgepointers die naar old wijzen in old->up */
+ if(neighb==0) return;
+ if(old->up==0) return;
+ neighb= neighb->up;
+ if(neighb==0) return;
+
+ if(neighb->ed1==old) {
+ neighb->ed1= old->up;
+ }
+ else if(neighb->ed2==old) {
+ neighb->ed2= old->up;
+ }
+ else if(neighb->ed3==old) {
+ neighb->ed3= old->up;
+ }
+ else if(neighb->ed4==old) {
+ neighb->ed4= old->up;
+ }
+
+ if(neighb->up) {
+ replaceAllNodeUp(neighb, old);
+ }
+}
+
+
+void replaceTestNode(RNode *neighb, RNode **edpp, RNode *newn, int level, float *vert)
+{
+ /* IF neighb->ed wijst naar newn->up
+ * IF edgelevels gelijk
+ IF testvert zit in neighb->ed
+ pointers beide kanten op veranderen
+ ELSE
+ RETURN
+ ELSE
+ IF neighb edgelevel is dieper
+ verander neighb pointer
+
+ */
+ int ok= 0;
+
+ if(neighb==0) return;
+ if(newn->up==0) return;
+
+ if(neighb->ed1==newn->up) {
+ if(neighb->lev1==level) {
+ if(vert==neighb->v1 || vert==neighb->v2) {
+ *edpp= neighb;
+ neighb->ed1= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev1>level) {
+ neighb->ed1= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed2==newn->up) {
+ if(neighb->lev2==level) {
+ if(vert==neighb->v2 || vert==neighb->v3) {
+ *edpp= neighb;
+ neighb->ed2= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev2>level) {
+ neighb->ed2= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed3==newn->up) {
+ if(neighb->lev3==level) {
+ if(neighb->type==3) {
+ if(vert==neighb->v3 || vert==neighb->v1) {
+ *edpp= neighb;
+ neighb->ed3= newn;
+ }
+ else return;
+ }
+ else {
+ if(vert==neighb->v3 || vert==neighb->v4) {
+ *edpp= neighb;
+ neighb->ed3= newn;
+ }
+ else return;
+ }
+ }
+ else if(neighb->lev3>level) {
+ neighb->ed3= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed4==newn->up) {
+ if(neighb->lev4==level) {
+ if(vert==neighb->v4 || vert==neighb->v1) {
+ *edpp= neighb;
+ neighb->ed4= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev4>level) {
+ neighb->ed4= newn;
+ }
+ ok= 1;
+ }
+
+ if(ok && neighb->down1) {
+ replaceTestNode(neighb->down1, edpp, newn, level, vert);
+ replaceTestNode(neighb->down2, edpp, newn, level, vert);
+ }
+
+}
+
+int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2)
+{
+ /* vergelijkt edgelevels , als gelijk zet het de vertexpointers */
+
+ if(neighb==0) return 0;
+
+ if(neighb->ed1==node) {
+ if(neighb->lev1==level) {
+ *v1= neighb->v1;
+ *v2= neighb->v2;
+ return 1;
+ }
+ }
+ else if(neighb->ed2==node) {
+ if(neighb->lev2==level) {
+ *v1= neighb->v2;
+ *v2= neighb->v3;
+ return 1;
+ }
+ }
+ else if(neighb->ed3==node) {
+ if(neighb->lev3==level) {
+ if(neighb->type==3) {
+ *v1= neighb->v3;
+ *v2= neighb->v1;
+ }
+ else {
+ *v1= neighb->v3;
+ *v2= neighb->v4;
+ }
+ return 1;
+ }
+ }
+ else if(neighb->ed4==node) {
+ if(neighb->lev4==level) {
+ *v1= neighb->v4;
+ *v2= neighb->v1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+float edlen(float *v1, float *v2)
+{
+ return (v1[0]-v2[0])*(v1[0]-v2[0])+ (v1[1]-v2[1])*(v1[1]-v2[1])+ (v1[2]-v2[2])*(v1[2]-v2[2]);
+}
+
+
+void subdivideTriNode(RNode *node, RNode *edge)
+{
+ RNode *n1, *n2, *up;
+ float fu, fv, fl, *v1, *v2; /* , AreaT3Dfl(); ... from arithb... */
+ int uvl;
+
+ if(node->down1 || node->down2) {
+ /* printf("trinode: subd already done\n"); */
+ return;
+ }
+
+ /* bepaal subdivide richting */
+
+ if(edge==0) {
+ /* areathreshold */
+ if(node->area<nodelimit) return;
+
+ fu= edlen(node->v1, node->v2);
+ fv= edlen(node->v2, node->v3);
+ fl= edlen(node->v3, node->v1);
+
+ if(fu>fv && fu>fl) uvl= 1;
+ else if(fv>fu && fv>fl) uvl= 2;
+ else uvl= 3;
+ }
+ else {
+
+ if(edge==node->ed1) uvl= 1;
+ else if(edge==node->ed2) uvl= 2;
+ else uvl= 3;
+ }
+
+ /* moeten naastliggende nodes dieper? Recursief! */
+ n1= 0;
+ if(uvl==1) {
+ if(node->ed1 && node->ed1->down1==0) n1= node->ed1;
+ }
+ else if(uvl==2) {
+ if(node->ed2 && node->ed2->down1==0) n1= node->ed2;
+ }
+ else {
+ if(node->ed3 && node->ed3->down1==0) n1= node->ed3;
+ }
+ if(n1) {
+ up= node->up;
+ while(up) { /* ook testen op ed4 !!! */
+ if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) {
+ subdivideNode(n1, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+
+ /* Het subdividen */
+ n1= mallocNode();
+ memcpy(n1, node, sizeof(RNode));
+ n2= mallocNode();
+ memcpy(n2, node, sizeof(RNode));
+
+ n1->up= node;
+ n2->up= node;
+
+ node->down1= n1;
+ node->down2= n2;
+
+ /* subdivide edge 1 */
+ if(uvl==1) {
+
+ /* EERSTE NODE krijgt edge 2 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed2, n1);
+ n1->lev1++;
+ replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed2= n1;
+ n2->lev2= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev1++;
+ replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1);
+
+ /* NIEUWE VERTEX uit edge 1 */
+ if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v1= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v1= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v1= n2->v2= mallocVert();
+ n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]);
+ n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]);
+ n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]);
+ n1->v1[3]= node->v1[3]; /* color */
+ }
+ }
+ else if(uvl==2) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev2++;
+ replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev2++;
+ replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3);
+
+ /* NIEUWE VERTEX uit edge 2 */
+ if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v3= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v2= mallocVert();
+ n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]);
+ n1->v3[3]= node->v1[3]; /* color */
+ }
+ }
+ else if(uvl==3) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed2= n2;
+ n1->lev2= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev3++;
+ replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v1);
+
+ /* TWEEDE NODE krijgt edge 2 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed2, n2);
+ n2->lev3++;
+ replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v3);
+
+ /* NIEUWE VERTEX uit edge 3 */
+ if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v1) {
+ n1->v3= v2;
+ n2->v1= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v1= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v1= mallocVert();
+ n1->v3[0]= 0.5*(node->v1[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v1[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v1[2]+ node->v3[2]);
+ n1->v3[3]= node->v3[3]; /* color */
+ }
+ }
+ n1->area= AreaT3Dfl(n1->v1, n1->v2, n1->v3);
+ n2->area= AreaT3Dfl(n2->v1, n2->v2, n2->v3);
+
+}
+
+
+void subdivideNode(RNode *node, RNode *edge)
+{
+ RNode *n1, *n2, *up;
+ float fu, fv, *v1, *v2;/*, AreaQ3Dfl(); ... from arithb... */
+ int uvl;
+
+ if(Ntotnode>RG.maxnode) return;
+
+ if(node->type==3) {
+ subdivideTriNode(node, edge);
+ return;
+ }
+
+ if(node->down1 || node->down2) {
+ /* printf("subdivide Node: already done \n"); */
+ return;
+ }
+
+ /* bepaal subdivide richting */
+
+ if(edge==0) {
+ /* areathreshold */
+ if(node->area<nodelimit) {
+ return;
+ }
+ fu= fabs(node->v1[0]- node->v2[0])+ fabs(node->v1[1]- node->v2[1]) +fabs(node->v1[2]- node->v2[2]);
+ fv= fabs(node->v1[0]- node->v4[0])+ fabs(node->v1[1]- node->v4[1]) +fabs(node->v1[2]- node->v4[2]);
+ if(fu>fv) uvl= 1;
+ else uvl= 2;
+ }
+ else {
+ if(edge==node->ed1 || edge==node->ed3) uvl= 1;
+ else uvl= 2;
+ }
+
+ /* moeten naastliggende nodes dieper? Recursief! */
+ n1= n2= 0;
+ if(uvl==1) {
+ if(node->ed1 && node->ed1->down1==0) n1= node->ed1;
+ if(node->ed3 && node->ed3->down1==0) n2= node->ed3;
+ }
+ else {
+ if(node->ed2 && node->ed2->down1==0) n1= node->ed2;
+ if(node->ed4 && node->ed4->down1==0) n2= node->ed4;
+ }
+ if(n1) {
+ up= node->up;
+ while(up) {
+ if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) {
+ /* printf("recurs subd\n"); */
+ subdivideNode(n1, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+ if(n2) {
+ up= node->up;
+ while(up) {
+ if(n2->ed1==up || n2->ed2==up || n2->ed3==up || n2->ed4==up) {
+ /* printf("recurs subd\n"); */
+ subdivideNode(n2, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+
+ /* Het subdividen */
+ n1= mallocNode();
+ memcpy(n1, node, sizeof(RNode));
+ n2= mallocNode();
+ memcpy(n2, node, sizeof(RNode));
+
+ n1->up= node;
+ n2->up= node;
+
+ node->down1= n1;
+ node->down2= n2;
+
+ /* subdivide edge 1 en 3 */
+ if(uvl==1) {
+
+ /* EERSTE NODE krijgt edge 2 */
+ n1->ed4= n2;
+ n1->lev4= 0;
+ replaceAllNode(n1->ed2, n1);
+ n1->lev1++;
+ n1->lev3++;
+ replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2);
+ replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v3);
+
+ /* TWEEDE NODE krijgt edge 4 */
+ n2->ed2= n1;
+ n2->lev2= 0;
+ replaceAllNode(n2->ed4, n2);
+ n2->lev1++;
+ n2->lev3++;
+ replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1);
+ replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v4);
+
+ /* NIEUWE VERTEX uit edge 1 */
+ if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v1= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v1= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v1= n2->v2= mallocVert();
+ n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]);
+ n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]);
+ n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]);
+ n1->v1[3]= node->v1[3]; /* color */
+ }
+
+ /* NIEUWE VERTEX uit edge 3 */
+ if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v3) {
+ n1->v4= v2;
+ n2->v3= v2;
+ }
+ else {
+ n1->v4= v1;
+ n2->v3= v1;
+ }
+ }
+ else {
+ n1->v4= n2->v3= mallocVert();
+ n1->v4[0]= 0.5*(node->v3[0]+ node->v4[0]);
+ n1->v4[1]= 0.5*(node->v3[1]+ node->v4[1]);
+ n1->v4[2]= 0.5*(node->v3[2]+ node->v4[2]);
+ n1->v4[3]= node->v4[3]; /* color */
+ }
+ }
+ /* subdivide edge 2 en 4 */
+ else if(uvl==2) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev2++;
+ n1->lev4++;
+ replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2);
+ replaceTestNode(n1->ed4, &(n1->ed4), n1, n1->lev4, n1->v1);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev2++;
+ n2->lev4++;
+ replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3);
+ replaceTestNode(n2->ed4, &(n2->ed4), n2, n2->lev4, n2->v4);
+
+ /* NIEUWE VERTEX uit edge 2 */
+ if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v3= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v2= mallocVert();
+ n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]);
+ n1->v3[3]= node->v3[3]; /* color */
+ }
+
+ /* NIEUWE VERTEX uit edge 4 */
+ if( setvertexpointersNode(n1->ed4, n1, n1->lev4, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v1) {
+ n1->v4= v2;
+ n2->v1= v2;
+ }
+ else {
+ n1->v4= v1;
+ n2->v1= v1;
+ }
+ }
+ else {
+ n1->v4= n2->v1= mallocVert();
+ n1->v4[0]= 0.5*(node->v1[0]+ node->v4[0]);
+ n1->v4[1]= 0.5*(node->v1[1]+ node->v4[1]);
+ n1->v4[2]= 0.5*(node->v1[2]+ node->v4[2]);
+ n1->v4[3]= node->v4[3]; /* color */
+ }
+
+ }
+
+ n1->area= AreaQ3Dfl(n1->v1, n1->v2, n1->v3, n1->v4);
+ n2->area= AreaQ3Dfl(n2->v1, n2->v2, n2->v3, n2->v4);
+
+}
+
+int comparelevel(RNode *node, RNode *nb, int level)
+{
+ /* recursief afdalen: bij diepste node testen */
+ /* return 1 is gelijk of hoger */
+
+ if(nb==0) return 1;
+
+ if(nb->down1) {
+ return 0;
+
+ /* HIER ZIT EEN FOUT, MAAR WELKE? (zonder dit werkt 't ook, maar langzamer)
+ n1= nb->down1;
+ if(n1->ed1==node) return comparelevel(node, n1, level);
+ if(n1->ed2==node) return comparelevel(node, n1, level);
+ if(n1->ed3==node) return comparelevel(node, n1, level);
+ if(n1->ed4==node) return comparelevel(node, n1, level);
+ n1= nb->down2;
+ if(n1->ed1==node) return comparelevel(node, n1, level);
+ if(n1->ed2==node) return comparelevel(node, n1, level);
+ if(n1->ed3==node) return comparelevel(node, n1, level);
+ if(n1->ed4==node) return comparelevel(node, n1, level);
+ printf(" dit kan niet ");
+ return 0;
+ */
+
+ }
+
+ if(nb->down1==0) {
+ /* if(nb->ed1==node) return (nb->lev1<=level); */
+ /* if(nb->ed2==node) return (nb->lev2<=level); */
+ /* if(nb->ed3==node) return (nb->lev3<=level); */
+ /* if(nb->ed4==node) return (nb->lev4<=level); */
+
+ return 1; /* is hogere node */
+ }
+ return 1;
+}
+
+void deleteTriNodes(RNode *node) /* beide kinderen van node */
+{
+ RNode *n1, *n2;
+
+ /* als naastliggende nodes dieper zijn: geen delete */
+ /* enkel twee nodes testen, van andere verandert level niet */
+
+ n1= node->down1;
+ n2= node->down2;
+
+ if(n1==0 || n2==0) return;
+
+ if(n1->down1 || n2->down1) return;
+
+ /* aan edges mag geen gesubdivide node zitten */
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed3 && n1->ed3->down1) return;
+
+ if(n2->ed1 && n2->ed1->down1) return;
+ if(n2->ed2 && n2->ed2->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed3, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed3, n1);
+
+ replaceAllNodeInv(n2->ed1, n2);
+ replaceAllNodeInv(n2->ed2, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+
+ replaceAllNodeUp(n2->ed1, n2);
+ replaceAllNodeUp(n2->ed2, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+}
+
+ /* beide kinderen van node */
+void deleteNodes(RNode *node)
+{
+ RNode *n1, *n2;
+
+ /* als naastliggende nodes dieper zijn: geen delete */
+ /* enkel twee nodes testen, van andere verandert level niet */
+
+ if(node->type==3) {
+ deleteTriNodes(node);
+ return;
+ }
+
+ n1= node->down1;
+ n2= node->down2;
+
+ if(n1==0 || n2==0) return;
+
+ if(n1->down1 || n2->down1) return;
+
+ if(n1->ed3==n2) {
+
+ /* aan edges mag geen gesubdivide node zitten */
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed4 && n1->ed4->down1) return;
+
+ if(n2->ed2 && n2->ed2->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+ if(n2->ed4 && n2->ed4->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed4, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed4, n1);
+
+ replaceAllNodeInv(n2->ed2, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+ replaceAllNodeInv(n2->ed4, n2);
+
+ replaceAllNodeUp(n2->ed2, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+ replaceAllNodeUp(n2->ed4, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+ return;
+ }
+ else if(n1->ed4==n2) {
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed3 && n1->ed3->down1) return;
+
+ if(n2->ed1 && n2->ed1->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+ if(n2->ed4 && n2->ed4->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed3, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed3, n1);
+
+ replaceAllNodeInv(n2->ed1, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+ replaceAllNodeInv(n2->ed4, n2);
+
+ replaceAllNodeUp(n2->ed1, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+ replaceAllNodeUp(n2->ed4, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+ return;
+ }
+
+}
+
+