diff options
author | Ton Roosendaal <ton@blender.org> | 2004-04-24 01:02:58 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2004-04-24 01:02:58 +0400 |
commit | dffa667674a1fda23328a93b2b49d549906bb49b (patch) | |
tree | 009b6254f9f6bde632a17416d3d25fb61308042a /source/blender | |
parent | d8580d181b975cc73d59dfe3719d7284582c1c51 (diff) |
Raytrace now has option to change the resolution of the Octree used. It
appeared that the standard size (64x64x64) just works fine for small
scenes, like a single character in a small environment. Larger scenes and
larger environments became exponentional slower.
Disadvantage of larger octrees is longer build time, and overhead traver-
sing it though, so something to tweak based on some experimenting.
A table with test results + blender file will be in CMS soon.
New button is in F10 Render panel, in bottom. Last free spot there! O_o
Sizes supported now 64, 128, 256 or 512.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 54 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 4 | ||||
-rw-r--r-- | source/blender/render/intern/source/ray.c | 146 | ||||
-rw-r--r-- | source/blender/src/buttons_scene.c | 12 |
4 files changed, 155 insertions, 61 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 42d4e3c52a4..3ce03aca4a3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -977,7 +977,7 @@ static void switch_endian_structs(struct SDNA *filesdna, BHead *bhead) } } -static void *read_struct(FileData *fd, BHead *bh) +static void *read_struct(FileData *fd, BHead *bh, char *blockname) { void *temp= NULL; @@ -989,7 +989,7 @@ static void *read_struct(FileData *fd, BHead *bh) if(fd->compflags[bh->SDNAnr]==2) { temp= dna_reconstruct(fd->memsdna, fd->filesdna, fd->compflags, bh->SDNAnr, bh->nr, (bh+1)); } else { - temp= MEM_mallocN(bh->len, "read_struct"); + temp= MEM_mallocN(bh->len, blockname); memcpy(temp, (bh+1), bh->len); /* BHEAD+DATA dependancy */ } } @@ -2698,6 +2698,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID ID *id; ListBase *lb; + char *str; if(bhead->code==ID_ID) { ID *linkedid= (ID *)(bhead + 1); /* BHEAD+DATA dependancy */ @@ -2709,7 +2710,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID } /* read libblock */ - id = read_struct(fd, bhead); + id = read_struct(fd, bhead, "lib block"); if (id_r) *id_r= id; if (!id) @@ -2731,9 +2732,41 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID bhead = blo_nextbhead(fd, bhead); + switch( GS(id->name) ) { + case ID_OB: str= "ID_OB"; break; + case ID_SCE: str= "ID_SCE"; break; + case ID_LI: str= "ID_LI"; break; + case ID_ME: str= "ID_ME"; break; + case ID_CU: str= "ID_CU"; break; + case ID_MB: str= "ID_MB"; break; + case ID_MA: str= "ID_MA"; break; + case ID_TE: str= "ID_TE"; break; + case ID_IM: str= "ID_IM"; break; + case ID_IK: str= "ID_IK"; break; + case ID_WV: str= "ID_WV"; break; + case ID_LT: str= "ID_LT"; break; + case ID_SE: str= "ID_SE"; break; + case ID_LF: str= "ID_LF"; break; + case ID_LA: str= "ID_LA"; break; + case ID_CA: str= "ID_CA"; break; + case ID_IP: str= "ID_IP"; break; + case ID_KE: str= "ID_KE"; break; + case ID_WO: str= "ID_WO"; break; + case ID_SCR: str= "ID_SCR"; break; + case ID_VF: str= "ID_VF"; break; + case ID_TXT : str= "ID_TXT"; break; + case ID_SO: str= "ID_SO"; break; + case ID_SAMPLE: str= "ID_SAMPLE"; break; + case ID_GR: str= "ID_GR"; break; + case ID_ID: str= "ID_ID"; break; + case ID_SEQ: str= "ID_SEQ"; break; + case ID_AR: str= "ID_AR"; break; + case ID_AC: str= "ID_AC"; break; + case ID_SCRIPT: str= "ID_SCRIPT"; break; + } /* read all data */ while(bhead && bhead->code==DATA) { - void *data= read_struct(fd, bhead); + void *data= read_struct(fd, bhead, str); if (data) { oldnewmap_insert(fd->datamap, bhead->old, data, 0); @@ -4118,6 +4151,7 @@ static void do_versions(Main *main) Tex *tex= main->tex.first; World *wrld= main->world.first; bScreen *sc; + Scene *sce; while(tex) { /* copied from kernel texture.c */ @@ -4163,6 +4197,12 @@ static void do_versions(Main *main) } } } + sce= main->scene.first; + while(sce) { + if(sce->r.ocres==0) sce->r.ocres= 64; + sce= sce->id.next; + } + } @@ -4202,14 +4242,14 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) { Link *link; - bfd->user= read_struct(fd, bhead); + bfd->user= read_struct(fd, bhead, "user def"); bfd->user->themes.first= bfd->user->themes.last= NULL; bhead = blo_nextbhead(fd, bhead); /* read all attached data */ while(bhead && bhead->code==DATA) { - link= read_struct(fd, bhead); + link= read_struct(fd, bhead, "user def data"); BLI_addtail(&bfd->user->themes, link); bhead = blo_nextbhead(fd, bhead); } @@ -4237,7 +4277,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r) case TEST: case REND: if (bhead->code==GLOB) { - fg= read_struct(fd, bhead); + fg= read_struct(fd, bhead, "REND"); } bhead = blo_nextbhead(fd, bhead); break; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 5550dcd4708..f1f374fe182 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -182,8 +182,8 @@ typedef struct RenderData { */ int mode; - /* yafray: render engine (not exclusive to yafray) */ - short renderer, rpad[3]; + /* render engine, octree resolution */ + short renderer, ocres, rpad[2]; /** * What to do with the sky/background. Picks sky/premul/key diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index 71298b17aff..21e053532e2 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.c @@ -51,8 +51,6 @@ #include "jitter.h" #include "texture.h" -#define OCRES 64 - #define DDA_SHADOW 0 #define DDA_MIRROR 1 #define DDA_SHADOW_TRA 2 @@ -64,10 +62,11 @@ typedef struct Octree { struct Branch *adrbranch[256]; - struct Node *adrnode[256]; + struct Node *adrnode[4096]; float ocsize; /* ocsize: mult factor, max size octree */ float ocfacx,ocfacy,ocfacz; float min[3], max[3]; + int ocres; /* for optimize, last intersected face */ VlakRen *vlr_last; @@ -194,25 +193,25 @@ static Branch *addbranch(Branch *br, short oc) if(br->b[oc]) return br->b[oc]; branchcount++; - if(g_oc.adrbranch[branchcount>>8]==0) - g_oc.adrbranch[branchcount>>8]= MEM_callocN(256*sizeof(Branch),"addbranch"); + if(g_oc.adrbranch[branchcount>>12]==NULL) + g_oc.adrbranch[branchcount>>12]= MEM_callocN(4096*sizeof(Branch),"addbranch"); - if(branchcount>= 256*256) { + if(branchcount>= 256*4096) { printf("error; octree branches full\n"); branchcount=0; } - return br->b[oc]=g_oc.adrbranch[branchcount>>8]+(branchcount & 255); + return br->b[oc]=g_oc.adrbranch[branchcount>>12]+(branchcount & 4095); } static Node *addnode(void) { nodecount++; - if(g_oc.adrnode[nodecount>>12]==0) + if(g_oc.adrnode[nodecount>>12]==NULL) g_oc.adrnode[nodecount>>12]= MEM_callocN(4096*sizeof(Node),"addnode"); - if(nodecount> 256*4096) { + if(nodecount> 4096*4096) { printf("error; octree nodes full\n"); nodecount=0; } @@ -270,6 +269,22 @@ static void ocwrite(VlakRen *vlr, short x, short y, short z, float rtf[][3]) x<<=2; y<<=1; + + br= g_oc.adrbranch[0]; + + if(g_oc.ocres==512) { + oc0= ((x & 1024)+(y & 512)+(z & 256))>>8; + br= addbranch(br, oc0); + } + if(g_oc.ocres>=256) { + oc0= ((x & 512)+(y & 256)+(z & 128))>>7; + br= addbranch(br, oc0); + } + if(g_oc.ocres>=128) { + oc0= ((x & 256)+(y & 128)+(z & 64))>>6; + br= addbranch(br, oc0); + } + oc0= ((x & 128)+(y & 64)+(z & 32))>>5; oc1= ((x & 64)+(y & 32)+(z & 16))>>4; oc2= ((x & 32)+(y & 16)+(z & 8))>>3; @@ -277,7 +292,7 @@ static void ocwrite(VlakRen *vlr, short x, short y, short z, float rtf[][3]) oc4= ((x & 8)+(y & 4)+(z & 2))>>1; oc5= ((x & 4)+(y & 2)+(z & 1)); - br= addbranch(g_oc.adrbranch[0],oc0); + br= addbranch(br,oc0); br= addbranch(br,oc1); br= addbranch(br,oc2); br= addbranch(br,oc3); @@ -304,8 +319,8 @@ static void ocwrite(VlakRen *vlr, short x, short y, short z, float rtf[][3]) static void d2dda(short b1, short b2, short c1, short c2, char *ocvlak, short rts[][3], float rtf[][3]) { - short ocx1,ocx2,ocy1,ocy2; - short x,y,dx=0,dy=0; + int ocx1,ocx2,ocy1,ocy2; + int x,y,dx=0,dy=0; float ox1,ox2,oy1,oy2; float labda,labdao,labdax,labday,ldx,ldy; @@ -315,7 +330,7 @@ static void d2dda(short b1, short b2, short c1, short c2, char *ocvlak, short rt ocy2= rts[b2][c2]; if(ocx1==ocx2 && ocy1==ocy2) { - ocvlak[OCRES*ocx1+ocy1]= 1; + ocvlak[g_oc.ocres*ocx1+ocy1]= 1; return; } @@ -359,8 +374,8 @@ static void d2dda(short b1, short b2, short c1, short c2, char *ocvlak, short rt while(TRUE) { - if(x<0 || y<0 || x>=OCRES || y>=OCRES); - else ocvlak[OCRES*x+y]= 1; + if(x<0 || y<0 || x>=g_oc.ocres || y>=g_oc.ocres); + else ocvlak[g_oc.ocres*x+y]= 1; labdao=labda; if(labdax==labday) { @@ -381,17 +396,18 @@ static void d2dda(short b1, short b2, short c1, short c2, char *ocvlak, short rt if(labda==labdao) break; if(labda>=1.0) break; } - ocvlak[OCRES*ocx2+ocy2]=1; + ocvlak[g_oc.ocres*ocx2+ocy2]=1; } static void filltriangle(short c1, short c2, char *ocvlak, short *ocmin) { - short a,x,y,y1,y2,*ocmax; + short *ocmax; + int a, x, y, y1, y2; ocmax=ocmin+3; for(x=ocmin[c1];x<=ocmax[c1];x++) { - a= OCRES*x; + a= g_oc.ocres*x; for(y=ocmin[c2];y<=ocmax[c2];y++) { if(ocvlak[a+y]) { y++; @@ -442,8 +458,9 @@ void makeoctree() float ocfac[3], t00, t01, t02; float rtf[4][3]; int v; - short a,b,c, rts[4][3], oc1, oc2, oc3, oc4, ocmin[6], *ocmax, x, y, z; - char ocvlak[3*OCRES*OCRES + 8]; // front, top, size view of face, to fill in + int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2; + short rts[4][3], ocmin[6], *ocmax; + char *ocvlak; // front, top, size view of face, to fill in ocmax= ocmin+3; @@ -457,6 +474,9 @@ void makeoctree() rejected= 0; coherent_ray= 0; + /* fill main octree struct */ + g_oc.ocres= R.r.ocres; + ocres2= g_oc.ocres*g_oc.ocres; g_oc.vlr_last= NULL; INIT_MINMAX(g_oc.min, g_oc.max); @@ -477,21 +497,22 @@ void makeoctree() if(g_oc.min[0] > g_oc.max[0]) return; /* empty octree */ - g_oc.adrbranch[0]=(Branch *)MEM_callocN(256*sizeof(Branch),"makeoctree"); - + g_oc.adrbranch[0]=(Branch *)MEM_callocN(4096*sizeof(Branch), "makeoctree"); + ocvlak= MEM_callocN( 3*ocres2 + 8, "ocvlak"); + for(c=0;c<3;c++) { /* octree enlarge, still needed? */ g_oc.min[c]-= 0.01; g_oc.max[c]+= 0.01; } - + t00= g_oc.max[0]-g_oc.min[0]; t01= g_oc.max[1]-g_oc.min[1]; t02= g_oc.max[2]-g_oc.min[2]; /* this minus 0.1 is old safety... seems to be needed? */ - g_oc.ocfacx=ocfac[0]= (OCRES-0.1)/t00; - g_oc.ocfacy=ocfac[1]= (OCRES-0.1)/t01; - g_oc.ocfacz=ocfac[2]= (OCRES-0.1)/t02; + g_oc.ocfacx=ocfac[0]= (g_oc.ocres-0.1)/t00; + g_oc.ocfacy=ocfac[1]= (g_oc.ocres-0.1)/t01; + g_oc.ocfacz=ocfac[2]= (g_oc.ocres-0.1)/t02; g_oc.ocsize= sqrt(t00*t00+t01*t01+t02*t02); /* global, max size octree */ @@ -534,50 +555,52 @@ void makeoctree() ocmin[c]= MIN4(oc1,oc2,oc3,oc4); ocmax[c]= MAX4(oc1,oc2,oc3,oc4); } - if(ocmax[c]>OCRES-1) ocmax[c]=OCRES-1; + if(ocmax[c]>g_oc.ocres-1) ocmax[c]=g_oc.ocres-1; if(ocmin[c]<0) ocmin[c]=0; } - d2dda(0,1,0,1,ocvlak+OCRES*OCRES,rts,rtf); + d2dda(0,1,0,1,ocvlak+ocres2,rts,rtf); d2dda(0,1,0,2,ocvlak,rts,rtf); - d2dda(0,1,1,2,ocvlak+2*OCRES*OCRES,rts,rtf); - d2dda(1,2,0,1,ocvlak+OCRES*OCRES,rts,rtf); + d2dda(0,1,1,2,ocvlak+2*ocres2,rts,rtf); + d2dda(1,2,0,1,ocvlak+ocres2,rts,rtf); d2dda(1,2,0,2,ocvlak,rts,rtf); - d2dda(1,2,1,2,ocvlak+2*OCRES*OCRES,rts,rtf); + d2dda(1,2,1,2,ocvlak+2*ocres2,rts,rtf); if(v4==NULL) { - d2dda(2,0,0,1,ocvlak+OCRES*OCRES,rts,rtf); + d2dda(2,0,0,1,ocvlak+ocres2,rts,rtf); d2dda(2,0,0,2,ocvlak,rts,rtf); - d2dda(2,0,1,2,ocvlak+2*OCRES*OCRES,rts,rtf); + d2dda(2,0,1,2,ocvlak+2*ocres2,rts,rtf); } else { - d2dda(2,3,0,1,ocvlak+OCRES*OCRES,rts,rtf); + d2dda(2,3,0,1,ocvlak+ocres2,rts,rtf); d2dda(2,3,0,2,ocvlak,rts,rtf); - d2dda(2,3,1,2,ocvlak+2*OCRES*OCRES,rts,rtf); - d2dda(3,0,0,1,ocvlak+OCRES*OCRES,rts,rtf); + d2dda(2,3,1,2,ocvlak+2*ocres2,rts,rtf); + d2dda(3,0,0,1,ocvlak+ocres2,rts,rtf); d2dda(3,0,0,2,ocvlak,rts,rtf); - d2dda(3,0,1,2,ocvlak+2*OCRES*OCRES,rts,rtf); + d2dda(3,0,1,2,ocvlak+2*ocres2,rts,rtf); } /* nothing todo with triangle..., just fills :) */ - filltriangle(0,1,ocvlak+OCRES*OCRES,ocmin); + filltriangle(0,1,ocvlak+ocres2,ocmin); filltriangle(0,2,ocvlak,ocmin); - filltriangle(1,2,ocvlak+2*OCRES*OCRES,ocmin); + filltriangle(1,2,ocvlak+2*ocres2,ocmin); /* init static vars here */ face_in_node(vlr, 0,0,0, rtf); for(x=ocmin[0];x<=ocmax[0];x++) { - a= OCRES*x; + a= g_oc.ocres*x; for(y=ocmin[1];y<=ocmax[1];y++) { - b= OCRES*y; - if(ocvlak[a+y+OCRES*OCRES]) { + b= g_oc.ocres*y; + if(ocvlak[a+y+ocres2]) { for(z=ocmin[2];z<=ocmax[2];z++) { - if(ocvlak[b+z+2*OCRES*OCRES] && ocvlak[a+z]) ocwrite(vlr, x,y,z, rtf); + if(ocvlak[b+z+2*ocres2] && ocvlak[a+z]) ocwrite(vlr, x,y,z, rtf); } } } } } } + + MEM_freeN(ocvlak); } /* ************ raytracer **************** */ @@ -892,13 +915,13 @@ static int testnode(Isect *is, Node *no, int x, int y, int z) /* find the Node for the octree coord x y z */ static Node *ocread(int x, int y, int z) { - static int mdiff=0, xo=OCRES, yo=OCRES, zo=OCRES; + static int mdiff=0, xo, yo, zo; Branch *br; int oc1, diff; /* outside of octree check, reset */ - if( (x & ~(OCRES-1)) || (y & ~(OCRES-1)) || (z & ~(OCRES-1)) ) { - xo=OCRES; yo=OCRES; zo=OCRES; + if( x >= g_oc.ocres) { + xo= g_oc.ocres; yo= g_oc.ocres; zo= g_oc.ocres; return NULL; } @@ -910,8 +933,35 @@ static Node *ocread(int x, int y, int z) x<<=2; y<<=1; + br= g_oc.adrbranch[0]; + + if(g_oc.ocres==512) { + oc1= ((x & 1024)+(y & 512)+(z & 256))>>8; + br= br->b[oc1]; + if(br==NULL) { + mdiff= 255; + return NULL; + } + } + if(g_oc.ocres>=256) { + oc1= ((x & 512)+(y & 256)+(z & 128))>>7; + br= br->b[oc1]; + if(br==NULL) { + mdiff= 127; + return NULL; + } + } + if(g_oc.ocres>=128) { + oc1= ((x & 256)+(y & 128)+(z & 64))>>6; + br= br->b[oc1]; + if(br==NULL) { + mdiff= 63; + return NULL; + } + } + oc1= ((x & 128)+(y & 64)+(z & 32))>>5; - br= g_oc.adrbranch[0]->b[oc1]; + br= br->b[oc1]; if(br) { oc1= ((x & 64)+(y & 32)+(z & 16))>>4; @@ -1036,7 +1086,7 @@ static int d3dda(Isect *is) if(c1==0) return 0; /* reset static variables in ocread */ - ocread(OCRES, OCRES, OCRES); + ocread(g_oc.ocres, 0, 0); /* setup 3dda to traverse octree */ ox1= (is->start[0]-g_oc.min[0])*g_oc.ocfacx; diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index a4ca0bb17db..d1ab737b64e 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -1043,15 +1043,19 @@ static void render_panel_render(void) uiDefButS(block, NUM,B_DIFF,"Yparts:", 472,42,86,31,&G.scene->r.yparts,1.0, 64.0, 0, 0, "Sets the number of vertical parts to render image in"); uiBlockBeginAlign(block); - uiDefButS(block, ROW,800,"Sky", 369,11,38,24,&G.scene->r.alphamode,3.0,0.0, 0, 0, "Fill background with sky"); - uiDefButS(block, ROW,800,"Premul", 410,11,54,24,&G.scene->r.alphamode,3.0,1.0, 0, 0, "Multiply alpha in advance"); - uiDefButS(block, ROW,800,"Key", 467,11,44,24,&G.scene->r.alphamode,3.0,2.0, 0, 0, "Alpha and colour values remain unchanged"); + uiDefButS(block, ROW,800,"Sky", 369,11,30,24,&G.scene->r.alphamode,3.0,0.0, 0, 0, "Fill background with sky"); + uiDefButS(block, ROW,800,"Premul", 400,11,50,24,&G.scene->r.alphamode,3.0,1.0, 0, 0, "Multiply alpha in advance"); + uiDefButS(block, ROW,800,"Key", 450,11,40,24,&G.scene->r.alphamode,3.0,2.0, 0, 0, "Alpha and colour values remain unchanged"); + uiBlockEndAlign(block); + + if(G.scene->r.mode & R_RAYTRACE) + uiDefButS(block, MENU, B_DIFF,"Octree resolution %t|64 %x64|128 %x128|256 %x256|512 %x512", 495,11,66,24,&G.scene->r.ocres,0.0,0.0, 0, 0, "Octree resolution for ray tracing"); uiBlockBeginAlign(block); uiDefButI(block, TOG|BIT|1,0,"Shadow", 565,171,61,30, &G.scene->r.mode, 0, 0, 0, 0, "Enable shadow calculation"); uiDefButI(block, TOG|BIT|4,0,"EnvMap", 626,171,61,30, &G.scene->r.mode, 0, 0, 0, 0, "Enable environment map rendering"); uiDefButI(block, TOG|BIT|10,0,"Pano", 565,142,41,28, &G.scene->r.mode, 0, 0, 0, 0, "Enable panorama rendering (output width is multiplied by Xparts)"); - uiDefButI(block, TOG|BIT|16,0,"Ray", 606,142,35,28, &G.scene->r.mode, 0, 0, 0, 0, "Enable ray tracing"); + uiDefButI(block, TOG|BIT|16,B_REDR,"Ray",606,142,35,28, &G.scene->r.mode, 0, 0, 0, 0, "Enable ray tracing"); uiDefButI(block, TOG|BIT|8,0,"Radio", 641,142,46,28, &G.scene->r.mode, 0, 0, 0, 0, "Enable radiosity rendering"); uiBlockBeginAlign(block); |