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.
This commit is contained in:
2004-04-23 21:02:58 +00:00
parent d8580d181b
commit dffa667674
4 changed files with 155 additions and 61 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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,7 +497,8 @@ 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;
@@ -489,9 +510,9 @@ void makeoctree()
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;

View File

@@ -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);