diff options
author | Ton Roosendaal <ton@blender.org> | 2006-01-24 01:05:47 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2006-01-24 01:05:47 +0300 |
commit | 042d612df219c8f6a29afa235537380f227b5684 (patch) | |
tree | 310a2c859b99c559115bbcda0aa70f2543bf962c /source/blender/blenkernel/intern | |
parent | 5668480c99001a617fd59a2383deb858195ffb26 (diff) |
Giant commit!
A full detailed description of this will be done later... is several days
of work. Here's a summary:
Render:
- Full cleanup of render code, removing *all* globals and bad level calls
all over blender. Render module is now not called abusive anymore
- API-fied calls to rendering
- Full recode of internal render pipeline. Is now rendering tiles by
default, prepared for much smarter 'bucket' render later.
- Each thread now can render a full part
- Renders were tested with 4 threads, goes fine, apart from some lookup
tables in softshadow and AO still
- Rendering is prepared to do multiple layers and passes
- No single 32 bits trick in render code anymore, all 100% floats now.
Writing images/movies
- moved writing images to blender kernel (bye bye 'schrijfplaatje'!)
- made a new Movie handle system, also in kernel. This will enable much
easier use of movies in Blender
PreviewRender:
- Using new render API, previewrender (in buttons) now uses regular render
code to generate images.
- new datafile 'preview.blend.c' has the preview scenes in it
- previews get rendered in exact displayed size (1 pixel = 1 pixel)
3D Preview render
- new; press Pkey in 3d window, for a panel that continuously renders
(pkey is for games, i know... but we dont do that in orange now!)
- this render works nearly identical to buttons-preview render, so it stops
rendering on any event (mouse, keyboard, etc)
- on moving/scaling the panel, the render code doesn't recreate all geometry
- same for shifting/panning view
- all other operations (now) regenerate the full render database still.
- this is WIP... but big fun, especially for simple scenes!
Compositor
- Using same node system as now in use for shaders, you can composit images
- works pretty straightforward... needs much more options/tools and integration
with rendering still
- is not threaded yet, nor is so smart to only recalculate changes... will be
done soon!
- the "Render Result" node will get all layers/passes as output sockets
- The "Output" node renders to a builtin image, which you can view in the Image
window. (yes, output nodes to render-result, and to files, is on the list!)
The Bad News
- "Unified Render" is removed. It might come back in some stage, but this
system should be built from scratch. I can't really understand this code...
I expect it is not much needed, especially with advanced layer/passes
control
- Panorama render, Field render, Motion blur, is not coded yet... (I had to
recode every single feature in render, so...!)
- Lens Flare is also not back... needs total revision, might become composit
effect though (using zbuffer for visibility)
- Part render is gone! (well, thats obvious, its default now).
- The render window is only restored with limited functionality... I am going
to check first the option to render to a Image window, so Blender can become
a true single-window application. :)
For example, the 'Spare render buffer' (jkey) doesnt work.
- Render with border, now default creates a smaller image
- No zbuffers are written yet... on the todo!
- Scons files and MSVC will need work to get compiling again
OK... thats what I can quickly recall. Now go compiling!
Diffstat (limited to 'source/blender/blenkernel/intern')
22 files changed, 1878 insertions, 943 deletions
diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 1bdeda1841f..c173051e862 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -87,3 +87,7 @@ ifeq ($(WITH_OPENEXR), true) CPPFLAGS += -DWITH_OPENEXR endif +ifeq ($(WITH_QUICKTIME), true) + CPPFLAGS += -I../../quicktime + CPPFLAGS += -DWITH_QUICKTIME +endif diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index b160dd41522..642ce855383 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -66,7 +66,6 @@ #include "BLI_blenlib.h" #include "nla.h" -#include "render.h" /* *********************** NOTE ON POSE AND ACTION ********************** @@ -755,9 +754,9 @@ static float nla_time(float cfra, float unit) extern float bluroffs; // bad construct, borrowed from object.c for now /* 2nd field */ - if(R.flag & R_SEC_FIELD) { - if(R.r.mode & R_FIELDSTILL); else cfra+= 0.5f*unit; - } +// if(R.flag & R_SEC_FIELD) { +// if(R.r.mode & R_FIELDSTILL); else cfra+= 0.5f*unit; +// } /* motion blur */ cfra+= unit*bluroffs; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 43b37740455..992139a5120 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -1,4 +1,3 @@ - /* blender.c jan 94 MIXED MODEL * * common help functions and data @@ -34,10 +33,6 @@ * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #ifndef WIN32 #include <unistd.h> // for read close #include <sys/param.h> // for MAXPATHLEN @@ -51,11 +46,13 @@ #include <fcntl.h> // for open #include "MEM_guardedalloc.h" + #include "DNA_listBase.h" #include "DNA_sdna_types.h" #include "DNA_userdef_types.h" #include "DNA_object_types.h" #include "DNA_curve_types.h" +#include "DNA_scene_types.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" @@ -233,10 +230,6 @@ static void clear_global(void) free_main(G.main); /* free all lib data */ freefastshade(); /* othwerwise old lamp settings stay active */ - - /* prevent hanging vars */ - R.backbuf= 0; - /* force all queues to be left */ winqueue_break= 1; @@ -275,7 +268,6 @@ static void clean_paths(Main *main) Sequence *seq; Strip *strip; - while(image) { BLI_clean(image->name); image= image->id.next; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 30c74fd65cb..5b4c4ca107f 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -402,7 +402,7 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) } /* call when you do images etc, needs restore too. also verifies tables */ -static void curvemapping_premultiply(CurveMapping *cumap, int restore) +void curvemapping_premultiply(CurveMapping *cumap, int restore) { static CurveMapPoint *table[3]= {NULL, NULL, NULL}; int a; @@ -545,7 +545,7 @@ void curvemapping_evaluateRGBF(CurveMapping *cumap, float *vecout, const float * /* RGB with black/white points and premult. tables are checked */ -static void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float *vecout, const float *vecin) +void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float *vecout, const float *vecin) { float fac; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index ae187c0e0f7..9a4a8f62600 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1385,6 +1385,8 @@ void DAG_scene_sort(struct Scene *sce) printf(" %s\n", base->object->id.name); } } + /* temporal...? */ + G.scene->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */ } /* node was checked to have lasttime != curtime and is if type ID_OB */ diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 668e8d6e71c..2e7f821abd7 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1,4 +1,3 @@ - /* displist.c * * @@ -33,10 +32,6 @@ * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include <math.h> #include <stdio.h> #include <string.h> @@ -93,28 +88,10 @@ #include "BKE_modifier.h" #include "nla.h" /* For __NLA: Please do not remove yet */ -#include "render.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 void boundbox_displist(Object *ob); -static FastLamp *fastlamplist= NULL; -static float fviewmat[4][4]; - void displistmesh_free(DispListMesh *dlm) { // also check on mvert and mface, can be NULL after decimator (ton) @@ -288,358 +265,18 @@ void copy_displist(ListBase *lbn, ListBase *lb) } } -static void initfastshade(void) +void initfastshade(void) { - Base *base; - Scene *setscene; - Object *ob; - Lamp *la; - FastLamp *fl; - float mat[4][4]; - - 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; - - /* copied from 'roteerscene' (does that function still exist? (ton) */ - where_is_object(G.scene->camera); - Mat4CpyMat4(R.viewinv, G.scene->camera->obmat); - Mat4Ortho(R.viewinv); - Mat4Invert(fviewmat, R.viewinv); - - /* initrendertexture(); */ - setscene = G.scene->set; - 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 && setscene && setscene->set) {/*if(base->next==0 && G.scene->set && base==G.scene->base.last) {*/ - setscene = setscene->set; - base= setscene->base.first; /* 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) { - ShadeInput shi; - FastLamp *fl; - float i, t, inp, is, soft, lv[3], lampdist, ld; - float diff1[3], diff2[3]; - float isr1=0, isg1=0, isb1=0, isr=0, isg=0, isb=0; - int a, back; - - if(ma==0) return; - - shi.mat= ma; - shi.vlr= NULL; // have to do this! - - // copy all relevant material vars, note, keep this synced with render_types.h - memcpy(&shi.r, &shi.mat->r, 23*sizeof(float)); - // set special cases: - shi.har= shi.mat->har; - - shi.osatex= 0; // also prevents reading vlr - - VECCOPY(shi.vn, nor); - - if(ma->mode & MA_VERTEXCOLP) { - if(vertcol) { - shi.r= vertcol[3]/255.0; - shi.g= vertcol[2]/255.0; - shi.b= vertcol[1]/255.0; - } - } - - if(ma->texco) { - VECCOPY(shi.lo, orco); - - if(ma->texco & TEXCO_GLOB) { - VECCOPY(shi.gl, shi.lo); - } - if(ma->texco & TEXCO_WINDOW) { - VECCOPY(shi.winco, shi.lo); - } - if(ma->texco & TEXCO_STICKY) { - VECCOPY(shi.sticky, shi.lo); - } - if(ma->texco & TEXCO_UV) { - VECCOPY(shi.uv, shi.lo); - } - if(ma->texco & TEXCO_OBJECT) { - VECCOPY(shi.co, shi.lo); - } - if(ma->texco & TEXCO_NORM) { - VECCOPY(shi.orn, shi.vn); - } - if(ma->texco & TEXCO_REFL) { - - inp= 2.0*(shi.vn[2]); - shi.ref[0]= (inp*shi.vn[0]); - shi.ref[1]= (inp*shi.vn[1]); - shi.ref[2]= (-1.0+inp*shi.vn[2]); - } - - do_material_tex(&shi); - } - - if(ma->mode & MA_SHLESS) { - if(vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) { - float fac; - fac= vertcol[3]*shi.r; - col1[3]= fac>=1.0?255:(char)fac; - fac= vertcol[2]*shi.g; - col1[2]= fac>=1.0?255:(char)fac; - fac= vertcol[1]*shi.b; - col1[1]= fac>=1.0?255:(char)fac; - } - else { - int fac; - fac= (int) (255.0*shi.r); - col1[3]= fac>255?255:(char)fac; - fac= (int) (255.0*shi.g); - col1[2]= fac>255?255:(char)fac; - fac= (int) (255.0*shi.b); - col1[1]= fac>255?255:(char)fac; - } - 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 ) { - diff1[0]= diff2[0]= shi.r*(shi.emit+vertcol[3]/255.0); - diff1[1]= diff2[1]= shi.g*(shi.emit+vertcol[2]/255.0); - diff1[2]= diff2[2]= shi.b*(shi.emit+vertcol[1]/255.0); - } - else { - diff1[0]= diff2[0]= shi.r*shi.emit; - diff1[1]= diff2[1]= shi.g*shi.emit; - diff1[2]= diff2[2]= shi.b*shi.emit; - } - - shi.view[0]= 0.0; - shi.view[1]= 0.0; - shi.view[2]= 1.0; - - Normalise(shi.view); - - 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) { - /* soft area */ - i= t/fl->spotbl; - t= i*i; - soft= (3.0*t-2.0*t*i); - inp*= soft; - } - - lampdist*=inp; - } - } - - if(fl->mode & LA_NO_DIFF) is= 0.0; - else { - is= nor[0]*lv[0]+ nor[1]*lv[1]+ nor[2]*lv[2]; - - if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(nor, lv, shi.view, ma->roughness); - else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(nor, lv, shi.view, ma->param[0], ma->param[1]); - else if(ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(is, nor, shi.view, ma->darkness); - else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(nor, lv, shi.view, ma->param[0], ma->param[1]); - } - - back= 0; - if(is<0.0) { - back= 1; - is= -is; - } - inp= is*lampdist*shi.refl; - - if(back==0) { - add_to_diffuse(diff1, &shi, is, inp*fl->r, inp*fl->g, inp*fl->b); - //diff1[0]+= inp*fl->r; - //diff1[1]+= inp*fl->g; - //diff1[2]+= inp*fl->b; - } else if(col2) { - add_to_diffuse(diff2, &shi, is, inp*fl->r, inp*fl->g, inp*fl->b); - //diff2[0]+= inp*fl->r; - //diff2[1]+= inp*fl->g; - //diff2[2]+= inp*fl->b; - } - if(shi.spec!=0.0 && (fl->mode & LA_NO_SPEC)==0) { - float specfac; - - if(ma->spec_shader==MA_SPEC_PHONG) - specfac= Phong_Spec(nor, lv, shi.view, shi.har, 0); - else if(ma->spec_shader==MA_SPEC_COOKTORR) - specfac= CookTorr_Spec(nor, lv, shi.view, shi.har, 0); - else if(ma->spec_shader==MA_SPEC_BLINN) - specfac= Blinn_Spec(nor, lv, shi.view, ma->refrac, (float)shi.har, 0); - else if(ma->spec_shader==MA_SPEC_WARDISO) - specfac= WardIso_Spec(nor, lv, shi.view, ma->rms, 0); - else - specfac= Toon_Spec(nor, lv, shi.view, ma->param[2], ma->param[3], 0); - - if(specfac>0) { - t= specfac*shi.spec*lampdist; - if(back==0) { - if(ma->mode & MA_RAMP_SPEC) { - float spec[3]; - do_specular_ramp(&shi, specfac, t, spec); - isr+= t*(fl->r * spec[0]); - isg+= t*(fl->g * spec[1]); - isb+= t*(fl->b * spec[2]); - } - else { - isr+= t*(fl->r * shi.specr); - isg+= t*(fl->g * shi.specg); - isb+= t*(fl->b * shi.specb); - } - } - else if(col2) { - if(ma->mode & MA_RAMP_SPEC) { - float spec[3]; - do_specular_ramp(&shi, specfac, t, spec); - isr1+= t*(fl->r * spec[0]); - isg1+= t*(fl->g * spec[1]); - isb1+= t*(fl->b * spec[2]); - } - else { - isr1+= t*(fl->r * shi.specr); - isg1+= t*(fl->g * shi.specg); - isb1+= t*(fl->b * shi.specb); - } - } - } - } - - } - - if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(diff1, &shi); - if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(&isr, &isg, &isb, &shi); - - a= 256*(diff1[0] + shi.ambr +isr); - if(a>255) col1[3]= 255; - else col1[3]= a; - a= 256*(diff1[1] + shi.ambg +isg); - if(a>255) col1[2]= 255; - else col1[2]= a; - a= 256*(diff1[2] + shi.ambb +isb); - if(a>255) col1[1]= 255; - else col1[1]= a; - - if(col2) { - if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(diff2, &shi); - if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(&isr1, &isg1, &isb1, &shi); - - a= 256*(diff2[0] + shi.ambr +isr1); - if(a>255) col2[3]= 255; - else col2[3]= a; - a= 256*(diff2[1] + shi.ambg +isg1); - if(a>255) col2[2]= 255; - else col2[2]= a; - a= 256*(diff2[2] + shi.ambb +isb1); - if(a>255) col2[1]= 255; - else col2[1]= a; - } - } void addnormalsDispList(Object *ob, ListBase *lb) @@ -710,27 +347,6 @@ void addnormalsDispList(Object *ob, ListBase *lb) static void init_fastshade_for_ob(Object *ob, int *need_orco_r, float mat[4][4], float imat[3][3]) { - float tmat[4][4]; - int a; - - initfastshade(); - - Mat4MulMat4(mat, ob->obmat, fviewmat); - - Mat4Invert(tmat, mat); - Mat3CpyMat4(imat, tmat); - if(ob->transflag & OB_NEG_SCALE) Mat3MulFloat((float *)imat, -1.0); - - if (need_orco_r) *need_orco_r= 0; - for(a=0; a<ob->totcol; a++) { - Material *ma= give_current_material(ob, a+1); - if(ma) { - init_render_material(ma); - if(ma->texco & TEXCO_ORCO) { - if (need_orco_r) *need_orco_r= 1; - } - } - } } void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r, unsigned int **col2_r) @@ -833,7 +449,7 @@ void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r Mat4MulVecfl(mat, vec); fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, ma, col1, col2, mcol); } - } + } MEM_freeN(vnors); displistmesh_free(dlm); @@ -1693,304 +1309,9 @@ void makeDispListCurveTypes(Object *ob, int forOrco) boundbox_displist(ob); } -/*******************************/ -/***** OUTLINE *****/ -/*******************************/ - -typedef struct Sample{ - short x, y; -} Sample; - -typedef struct Segment{ - /* coordinates */ - 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; - - /* input: - * 1 - image - * 2 - pointer to function that defines which pixel 'in' or 'out' 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); - - /* search for first transition, and continue from there */ - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { - if (in_or_out(ibuf, x, y) != in) { - /* found first 'other' point !! */ - - 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) { - /* this has to be a loose point */ - break; - } - - x += dirs[dir][0]; - y += dirs[dir][1]; - dir = (dir - 3) & 0x7; - } while(x != startx || y != starty); - - if (i >= 8) { - /* patch for loose points */ - MEM_freeN(samp); - } else { - count = count - 1; - samp[0].x = count >> 16; - samp[0].y = count; - return(samp); - } - } - } - } - /* printf("no transition \n"); */ - return(0); -} - - - -/*******************************/ -/***** WIREFRAME *****/ -/*******************************/ - - -static float DistToLine2D(short *v1, short *v2, short *v3) /* using Hesse formula :NO LINE PIECE! */ -{ - 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; - - /* first make a list of samples */ - - 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], dum; - 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; - - /* this takes care of correct loading of new imbufs */ - externtex(ma->mtex[0], vec, &dum, &dum, &dum, &dum, &dum); - - 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) { - float size[3]; - - 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); - - mesh_get_texspace(me, NULL, NULL, size); - xfac= size[0]/xsi; - yfac= 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; - } - - allqueue(REDRAWVIEW3D, 0); + /* removed */ } static void boundbox_displist(Object *ob) diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index fc27de989dc..663fe02aaf0 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -52,8 +52,9 @@ #include "DNA_texture_types.h" #include "DNA_scene_types.h" -#include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_jitter.h" #include "BLI_rand.h" #include "BKE_action.h" @@ -77,9 +78,10 @@ #include "BKE_screen.h" #include "BKE_utildefines.h" -#include "render.h" // externtex, bad level call (ton) #include "PIL_time.h" +#include "RE_render_ext.h" + /* temporal struct, used for reading return of mesh_get_mapped_verts_nors() */ typedef struct VeNoCo { float co[3], no[3]; @@ -1217,9 +1219,9 @@ static void init_mv_jit(float *jit, int num, int seed2) jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit"); for (i=0 ; i<4 ; i++) { - RE_jitterate1(jit, jit2, num, rad1); - RE_jitterate1(jit, jit2, num, rad1); - RE_jitterate2(jit, jit2, num, rad2); + BLI_jitterate1(jit, jit2, num, rad1); + BLI_jitterate1(jit, jit2, num, rad1); + BLI_jitterate2(jit, jit2, num, rad2); } MEM_freeN(jit2); rng_free(rng); @@ -1609,8 +1611,7 @@ void build_particle_system(Object *ob) if(me->totvert==0) return; if(ob==G.obedit) return; - - totpart= (R.flag & R_RENDERING)?paf->totpart:(paf->disp*paf->totpart)/100; + totpart= (G.rendering)?paf->totpart:(paf->disp*paf->totpart)/100; if(totpart==0) return; /* No returns after this line! */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 26711495252..b37e787729e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -51,6 +51,7 @@ #include "DNA_image_types.h" #include "DNA_texture_types.h" #include "DNA_packedFile_types.h" +#include "DNA_scene_types.h" #include "DNA_userdef_types.h" #include "BLI_blenlib.h" @@ -275,86 +276,155 @@ void free_unused_animimages() /* *********** READ AND WRITE ************** */ -void makepicstring(char *string, int frame) +int BKE_imtype_is_movie(int imtype) { - short i,len; - char num[10], *extension; - - if (string==0) return; - - extension= ""; - - strcpy(string, G.scene->r.pic); - BLI_convertstringcode(string, G.sce, G.scene->r.cfra); - - len= strlen(string); - - /* can also: sprintf(num, "%04d", frame); */ - - i=4-sprintf(num,"%d",frame); - for(;i>0;i--){ - string[len]='0'; - len++; + switch(imtype) { + case R_MOVIE: + case R_AVIRAW: + case R_AVIJPEG: + case R_AVICODEC: + case R_QUICKTIME: + return 1; } - string[len]=0; - strcat(string,num); - - if(G.scene->r.scemode & R_EXTENSION) - addImageExtension(string); - + return 0; } -void addImageExtension(char *string) +void BKE_add_image_extension(char *string, int imtype) { char *extension=""; - + if(G.scene->r.imtype== R_IRIS) { if(!BLI_testextensie(string, ".rgb")) extension= ".rgb"; } - else if(G.scene->r.imtype==R_IRIZ) { + else if(imtype==R_IRIZ) { if(!BLI_testextensie(string, ".rgb")) extension= ".rgb"; } - else if(G.scene->r.imtype==R_RADHDR) { + else if(imtype==R_RADHDR) { if(!BLI_testextensie(string, ".hdr")) extension= ".hdr"; } - else if(G.scene->r.imtype==R_PNG) { + else if(imtype==R_PNG) { if(!BLI_testextensie(string, ".png")) extension= ".png"; } - else if(G.scene->r.imtype==R_TARGA) { - if(!BLI_testextensie(string, ".tga")) - extension= ".tga"; - } - else if(G.scene->r.imtype==R_RAWTGA) { + else if(imtype==R_RAWTGA) { if(!BLI_testextensie(string, ".tga")) extension= ".tga"; } - else if(G.scene->r.imtype==R_JPEG90) { + else if(ELEM5(imtype, R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90)) { if(!BLI_testextensie(string, ".jpg")) extension= ".jpg"; } - else if(G.scene->r.imtype==R_BMP) { + else if(imtype==R_BMP) { if(!BLI_testextensie(string, ".bmp")) extension= ".bmp"; } - else if(G.have_libtiff && (G.scene->r.imtype==R_TIFF)) { + else if(G.have_libtiff && (imtype==R_TIFF)) { if(!BLI_testextensie(string, ".tif")) extension= ".tif"; } #ifdef WITH_OPENEXR - else if(G.scene->r.imtype==R_OPENEXR) { + else if(imtype==R_OPENEXR) { if(!BLI_testextensie(string, ".exr")) extension= ".exr"; } #endif - + else { /* targa default */ + if(!BLI_testextensie(string, ".tga")) + extension= ".tga"; + } + strcat(string, extension); } +int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quality) +{ + int ok; + + if(imtype==0); + else if(imtype== R_IRIS) ibuf->ftype= IMAGIC; + else if ((imtype==R_RADHDR)) { + ibuf->ftype= RADHDR; + } + else if ((imtype==R_PNG)) { + ibuf->ftype= PNG; + } + else if ((imtype==R_BMP)) { + ibuf->ftype= BMP; + } + else if ((G.have_libtiff) && (imtype==R_TIFF)) { + ibuf->ftype= TIF; + } +#ifdef WITH_OPENEXR + else if (imtype==R_OPENEXR) { + ibuf->ftype= OPENEXR; + if(subimtype & R_OPENEXR_HALF) + ibuf->ftype |= OPENEXR_HALF; + ibuf->ftype |= (quality & OPENEXR_COMPRESS); + + if(!(subimtype & R_OPENEXR_ZBUF)) + ibuf->zbuf_float = NULL; /* signal for exr saving */ + + } +#endif + else if (imtype==R_TARGA) { + ibuf->ftype= TGA; + } + else if(imtype==R_RAWTGA) { + ibuf->ftype= RAWTGA; + } + else if(imtype==R_HAMX) { + ibuf->ftype= AN_hamx; + } + else if ELEM(imtype, R_JPEG90, R_MOVIE) { + if(quality < 10) quality= 90; + ibuf->ftype= JPG|quality; + } + else ibuf->ftype= TGA; + + BLI_make_existing_file(name); + + ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); + if (ok == 0) { + perror(name); + } + + return(ok); +} + + +void BKE_makepicstring(char *string, int frame) +{ + short i,len; + char num[10], *extension; + + if (string==0) return; + + extension= ""; + + strcpy(string, G.scene->r.pic); + BLI_convertstringcode(string, G.sce, G.scene->r.cfra); + + len= strlen(string); + + /* can also: sprintf(num, "%04d", frame); */ + + i=4-sprintf(num,"%d",frame); + for(;i>0;i--){ + string[len]='0'; + len++; + } + string[len]=0; + strcat(string,num); + + if(G.scene->r.scemode & R_EXTENSION) + BKE_add_image_extension(string, G.scene->r.imtype); + +} + /* ******** IMAGE WRAPPING INIT ************* */ /* used by sequencer, texture */ @@ -519,7 +589,6 @@ void ima_ibuf_is_nul(Tex *tex, Image *ima) if (ima->anim) { dur = IMB_anim_get_duration(ima->anim); - ima->lastquality= R.osa; fra= ima->lastframe-1; if(fra<0) fra = 0; @@ -544,8 +613,6 @@ void ima_ibuf_is_nul(Tex *tex, Image *ima) load_image(ima, IB_rect, G.sce, G.scene->r.cfra); if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf); - - ima->lastquality= R.osa; } if(ima->ibuf) { @@ -573,14 +640,11 @@ void ima_ibuf_is_nul(Tex *tex, Image *ima) converttopremul(ima->ibuf); } - if(R.osa) { - - if(tex->imaflag & TEX_ANTISCALE) { - IMB_clever_double(ima->ibuf); - IMB_antialias(ima->ibuf); - } - else if(tex->imaflag & TEX_ANTIALI) IMB_antialias(ima->ibuf); + if(tex->imaflag & TEX_ANTISCALE) { + IMB_clever_double(ima->ibuf); + IMB_antialias(ima->ibuf); } + else if(tex->imaflag & TEX_ANTIALI) IMB_antialias(ima->ibuf); } if(ima->ibuf) diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 60ba7f3cfeb..b6b4f9a3bcb 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -57,6 +57,7 @@ #include "DNA_sound_types.h" #include "DNA_texture_types.h" #include "DNA_view3d_types.h" +#include "DNA_world_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -178,9 +179,9 @@ float frame_to_float(int cfra) /* see also bsystem_time in object.c */ float ctime; ctime= (float)cfra; - if(R.flag & R_SEC_FIELD) { - if((R.r.mode & R_FIELDSTILL)==0) ctime+= 0.5; - } +// if(R.flag & R_SEC_FIELD) { +// if((R.r.mode & R_FIELDSTILL)==0) ctime+= 0.5; +// } ctime+= bluroffs; ctime*= G.scene->r.framelen; diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index a2e372f33d5..e0006c854cf 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -45,6 +45,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "BKE_action.h" #include "BKE_bad_level_calls.h" diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index c617541e225..b95c401808d 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -34,6 +34,8 @@ */ #include <string.h> +#include <math.h> + #include "MEM_guardedalloc.h" #include "DNA_curve_types.h" @@ -61,10 +63,18 @@ #include "BPY_extern.h" +/* used in UI and render */ +Material defmaterial; + +/* called on startup, creator.c */ +void init_def_material(void) +{ + init_material(&defmaterial); +} + /* not material itself */ void free_material(Material *ma) { - MaterialLayer *ml; MTex *mtex; int a; @@ -81,11 +91,6 @@ void free_material(Material *ma) BKE_icon_delete((struct ID*)ma); ma->id.icon_id = 0; - - for(ml= ma->layers.first; ml; ml= ml->next) - if(ml->mat) ml->mat->id.us--; - - BLI_freelistN(&ma->layers); /* is no lib link block, but material extension */ if(ma->nodetree) { @@ -134,7 +139,6 @@ void init_material(Material *ma) ma->rampfac_col= 1.0; ma->rampfac_spec= 1.0; ma->pr_lamp= 3; /* two lamps, is bits */ - ma->ml_flag= ML_RENDER; /* default render base material for layers */ ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR; } @@ -153,7 +157,6 @@ Material *add_material(char *name) Material *copy_material(Material *ma) { Material *man; - MaterialLayer *ml; int a; man= copy_libblock(ma); @@ -173,10 +176,6 @@ Material *copy_material(Material *ma) if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col); if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec); - duplicatelist(&man->layers, &ma->layers); - for(ml= man->layers.first; ml; ml= ml->next) - id_us_plus((ID *)ml->mat); - if(ma->nodetree) { man->nodetree= ntreeCopyTree(ma->nodetree, 0); /* 0 == full new tree */ } @@ -274,25 +273,10 @@ void make_local_material(Material *ma) new_id(0, (ID *)ma, 0); } else if(local && lib) { - Material *mat; - MaterialLayer *ml; man= copy_material(ma); man->id.us= 0; - /* do material layers */ - for(mat= G.main->mat.first; mat; mat= mat->id.next) { - if(mat->id.lib==NULL) { - for(ml= mat->layers.first; ml; ml= ml->next) { - if(ml->mat==ma) { - ml->mat= man; - man->id.us++; - ma->id.us--; - } - } - } - } - /* do objects */ ob= G.main->object.first; while(ob) { @@ -579,7 +563,7 @@ void new_material_to_objectdata(Object *ob) ob->actcol= ob->totcol; } -static void do_init_render_material(Material *ma) +static void do_init_render_material(Material *ma, int osa, float *amb) { MTex *mtex; int a, needuv=0; @@ -595,48 +579,41 @@ static void do_init_render_material(Material *ma) ma->texco |= mtex->texco; ma->mapto |= mtex->mapto; - if(R.osa) { + if(osa) { if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA; } if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1; else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT)) needuv= 1; else if(ma->texco & (TEXCO_LAVECTOR|TEXCO_VIEW|TEXCO_STICKY)) needuv= 1; - - if(mtex->object) mtex->object->flag |= OB_DO_IMAT; - } } - if(ma->mode & MA_ZTRA) { - /* if(ma->alpha==0.0 || ma->alpha==1.0) */ - if(R.flag & R_RENDERING) R.flag |= R_ZTRA; - } if(ma->mode & MA_RADIO) needuv= 1; if(ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) { needuv= 1; - if(R.osa) ma->texco |= TEXCO_OSA; /* for texfaces */ + if(osa) ma->texco |= TEXCO_OSA; /* for texfaces */ } if(needuv) ma->texco |= NEED_UV; // since the raytracer doesnt recalc O structs for each ray, we have to preset them all if(ma->mode & (MA_RAYMIRROR|MA_RAYTRANSP|MA_SHADOW_TRA)) { ma->texco |= NEED_UV|TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM; - if(R.osa) ma->texco |= TEXCO_OSA; + if(osa) ma->texco |= TEXCO_OSA; } - ma->ambr= ma->amb*R.wrld.ambr; - ma->ambg= ma->amb*R.wrld.ambg; - ma->ambb= ma->amb*R.wrld.ambb; + ma->ambr= ma->amb*amb[0]; + ma->ambg= ma->amb*amb[1]; + ma->ambb= ma->amb*amb[2]; - /* will become or-ed result of all layer modes */ + /* will become or-ed result of all node modes */ ma->mode_l= ma->mode; } -void init_render_material(Material *mat) +void init_render_material(Material *mat, int osa, float *amb) { - do_init_render_material(mat); + do_init_render_material(mat, osa, amb); if(mat->nodetree && mat->use_nodes) { bNode *node; @@ -645,26 +622,26 @@ void init_render_material(Material *mat) if(node->id && GS(node->id->name)==ID_MA) { Material *ma= (Material *)node->id; if(ma!=mat) { - do_init_render_material(ma); + do_init_render_material(ma, osa, amb); mat->texco |= ma->texco; mat->mode_l |= ma->mode_l; } } } /* parses the geom nodes */ - mat->texco |= ntreeShaderGetTexco(mat->nodetree); + mat->texco |= ntreeShaderGetTexco(mat->nodetree, osa); ntreeBeginExecTree(mat->nodetree); /* has internal flag to detect it only does it once */ } } -void init_render_materials() +void init_render_materials(int osa, float *amb) { Material *ma; /* two steps, first initialize, then or the flags for layers */ for(ma= G.main->mat.first; ma; ma= ma->id.next) if(ma->id.us) - init_render_material(ma); + init_render_material(ma, osa, amb); } /* only needed for nodes now */ @@ -815,3 +792,89 @@ void delete_material_index() freedisplist(&ob->disp); } } + + +/* r g b = current value, col = new value, fac==0 is no change */ +/* if g==NULL, it only does r channel */ +void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col) +{ + float tmp, facm= 1.0-fac; + + switch (type) { + case MA_RAMP_BLEND: + *r = facm*(*r) + fac*col[0]; + if(g) { + *g = facm*(*g) + fac*col[1]; + *b = facm*(*b) + fac*col[2]; + } + break; + case MA_RAMP_ADD: + *r += fac*col[0]; + if(g) { + *g += fac*col[1]; + *b += fac*col[2]; + } + break; + case MA_RAMP_MULT: + *r *= (facm + fac*col[0]); + if(g) { + *g *= (facm + fac*col[1]); + *b *= (facm + fac*col[2]); + } + break; + case MA_RAMP_SCREEN: + *r = 1.0 - (facm + fac*(1.0 - col[0])) * (1.0 - *r); + if(g) { + *g = 1.0 - (facm + fac*(1.0 - col[1])) * (1.0 - *g); + *b = 1.0 - (facm + fac*(1.0 - col[2])) * (1.0 - *b); + } + break; + case MA_RAMP_SUB: + *r -= fac*col[0]; + if(g) { + *g -= fac*col[1]; + *b -= fac*col[2]; + } + break; + case MA_RAMP_DIV: + if(col[0]!=0.0) + *r = facm*(*r) + fac*(*r)/col[0]; + if(g) { + if(col[1]!=0.0) + *g = facm*(*g) + fac*(*g)/col[1]; + if(col[2]!=0.0) + *b = facm*(*b) + fac*(*b)/col[2]; + } + break; + case MA_RAMP_DIFF: + *r = facm*(*r) + fac*fabs(*r-col[0]); + if(g) { + *g = facm*(*g) + fac*fabs(*g-col[1]); + *b = facm*(*b) + fac*fabs(*b-col[2]); + } + break; + case MA_RAMP_DARK: + tmp= fac*col[0]; + if(tmp < *r) *r= tmp; + if(g) { + tmp= fac*col[1]; + if(tmp < *g) *g= tmp; + tmp= fac*col[2]; + if(tmp < *b) *b= tmp; + } + break; + case MA_RAMP_LIGHT: + tmp= fac*col[0]; + if(tmp > *r) *r= tmp; + if(g) { + tmp= fac*col[1]; + if(tmp > *g) *g= tmp; + tmp= fac*col[2]; + if(tmp > *b) *b= tmp; + } + break; + } + +} + + diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 09408e4a220..9429183105b 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -30,8 +30,6 @@ * 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): Jiri Hnidek <jiri.hnidek@vslib.cz>. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** @@ -1106,7 +1104,6 @@ void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v) } if(FALSE) { - /* if(R.flag & R_RENDERING) { */ MB_POINT temp; delta*= 2.0; @@ -2002,7 +1999,7 @@ void metaball_polygonize(Object *ob) mb= ob->data; if(totelem==0) return; - if(!(R.flag & R_RENDERING) && (mb->flag==MB_UPDATE_NEVER)) return; + if(!(G.rendering) && (mb->flag==MB_UPDATE_NEVER)) return; if(G.moving && mb->flag==MB_UPDATE_FAST) return; freedisplist(&ob->disp); @@ -2029,7 +2026,7 @@ void metaball_polygonize(Object *ob) if(totelem > 1024) init_metaball_octal_tree(5); /* width is size per polygonize cube */ - if(R.flag & R_RENDERING) width= mb->rendersize; + if(G.rendering) width= mb->rendersize; else { width= mb->wiresize; if(G.moving && mb->flag==MB_UPDATE_HALFRES) width*= 2; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index da18725c2dd..f7d0be1ac33 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -47,6 +47,7 @@ #include "BLI_blenlib.h" #include "MEM_guardedalloc.h" +#include "IMB_imbuf.h" /* not very important, but the stack solver likes to know a maximum */ #define MAX_SOCKET 64 @@ -77,6 +78,8 @@ void ntreeInitTypes(bNodeTree *ntree) if(ntree->type==NTREE_SHADER) ntree->alltypes= node_all_shaders; + else if(ntree->type==NTREE_COMPOSIT) + ntree->alltypes= node_all_composit; else { ntree->alltypes= NULL; printf("Error: no type definitions for nodes\n"); @@ -702,6 +705,14 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup) else if(type==SH_NODE_CURVE_RGB) node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } + else if(ntree->type==NTREE_COMPOSIT) { + if(type==CMP_NODE_VALTORGB) + node->storage= add_colorband(1); + else if(type==CMP_NODE_CURVE_VEC) + node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); + else if(type==CMP_NODE_CURVE_RGB) + node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); + } return node; } @@ -735,6 +746,12 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) else nnode->storage= MEM_dupallocN(nnode->storage); } + else if(ntree->type==NTREE_COMPOSIT) { + if(node->type==CMP_NODE_CURVE_VEC || node->type==CMP_NODE_CURVE_RGB) + nnode->storage= curvemapping_copy(node->storage); + else + nnode->storage= MEM_dupallocN(nnode->storage); + } else nnode->storage= MEM_dupallocN(nnode->storage); } @@ -832,6 +849,12 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) else MEM_freeN(node->storage); } + else if(ntree->type==NTREE_COMPOSIT) { + if(node->type==CMP_NODE_CURVE_VEC || node->type==CMP_NODE_CURVE_RGB) + curvemapping_free(node->storage); + else + MEM_freeN(node->storage); + } else MEM_freeN(node->storage); } @@ -843,6 +866,8 @@ void ntreeFreeTree(bNodeTree *ntree) { bNode *node, *next; + if(ntree==NULL) return; + BLI_freelistN(&ntree->links); /* do first, then unlink_node goes fast */ for(node= ntree->nodes.first; node; node= next) { @@ -1070,6 +1095,9 @@ void ntreeSolveOrder(bNodeTree *ntree) bNodeLink *link; int a, totnode=0; + /* the solve-order is called on each tree change, so we should be sure no exec can be running */ + ntreeEndExecTree(ntree); + /* set links pointers the input sockets, to find dependencies */ /* first clear data */ for(node= ntree->nodes.first; node; node= node->next) { @@ -1110,8 +1138,8 @@ void ntreeSolveOrder(bNodeTree *ntree) MEM_freeN(nodesort); /* find the active outputs, tree type dependant, might become handler */ - if(ntree->type==NTREE_SHADER) { - /* shader nodes only accepts one output */ + if(ntree->type==NTREE_SHADER || ntree->type==NTREE_COMPOSIT) { + /* shader/composit nodes only accepts one output */ int output= 0; for(node= ntree->nodes.first; node; node= node->next) { @@ -1127,9 +1155,6 @@ void ntreeSolveOrder(bNodeTree *ntree) /* here we could recursively set which nodes have to be done, might be different for editor or for "real" use... */ - - - } #pragma mark /* *************** preview *********** */ @@ -1138,12 +1163,9 @@ void ntreeSolveOrder(bNodeTree *ntree) static void nodeInitPreview(bNode *node, int xsize, int ysize) { - /* signal we don't do anything, preview writing is protected */ - if(xsize==0 || ysize==0) - return; /* sanity checks & initialize */ - if(node->preview) { + if(node->preview && node->preview->rect) { if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) { MEM_freeN(node->preview->rect); node->preview->rect= NULL; @@ -1154,6 +1176,11 @@ static void nodeInitPreview(bNode *node, int xsize, int ysize) node->preview= MEM_callocN(sizeof(bNodePreview), "node preview"); printf("added preview %s\n", node->name); } + + /* node previews can get added with variable size this way */ + if(xsize==0 || ysize==0) + return; + if(node->preview->rect==NULL) { node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect"); node->preview->xsize= xsize; @@ -1293,17 +1320,31 @@ static int ntree_begin_exec_tree(bNodeTree *ntree) void ntreeBeginExecTree(bNodeTree *ntree) { - int index; /* goes recursive over all groups */ - index= ntree_begin_exec_tree(ntree); + ntree->stacksize= ntree_begin_exec_tree(ntree); - if(index) { + if(ntree->stacksize) { + bNode *node; bNodeStack *ns; int a; - ns=ntree->stack= MEM_callocN(index*sizeof(bNodeStack), "node stack"); - for(a=0; a<index; a++, ns++) ns->hasinput= 1; + /* allocate stack */ + ns=ntree->stack= MEM_callocN(ntree->stacksize*sizeof(bNodeStack), "node stack"); + + /* tag inputs, the get_stack() gives own socket stackdata if not in use */ + for(a=0; a<ntree->stacksize; a++, ns++) ns->hasinput= 1; + + /* tag outputs, so we know when we can skip operations */ + for(node= ntree->nodes.first; node; node= node->next) { + bNodeSocket *sock; + for(sock= node->inputs.first; sock; sock= sock->next) { + if(sock->link) { + ns= ntree->stack + sock->link->fromsock->stack_index; + ns->hasoutput= 1; + } + } + } ntree->stack1= MEM_dupallocN(ntree->stack); } @@ -1315,7 +1356,21 @@ void ntreeEndExecTree(bNodeTree *ntree) { if(ntree->init & NTREE_EXEC_INIT) { + if(ntree->stack) { + + /* another callback candidate! */ + if(ntree->type==NTREE_COMPOSIT) { + bNodeStack *ns; + int a; + + for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) + if(ns->data) + free_compbuf(ns->data); + for(ns= ntree->stack1, a=0; a<ntree->stacksize; a++, ns++) + if(ns->data) + free_compbuf(ns->data); + } MEM_freeN(ntree->stack); ntree->stack= NULL; MEM_freeN(ntree->stack1); @@ -1352,37 +1407,23 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread) bNodeStack *stack; /* only when initialized */ - if(ntree->init & NTREE_EXEC_INIT) { - - if(thread) - stack= ntree->stack1; - else - stack= ntree->stack; + if((ntree->init & NTREE_EXEC_INIT)==0) + ntreeBeginExecTree(ntree); - for(node= ntree->nodes.first; node; node= node->next) { - if(node->typeinfo->execfunc) { - node_get_stack(node, stack, nsin, nsout); - node->typeinfo->execfunc(callerdata, node, nsin, nsout); - } - else if(node->type==NODE_GROUP && node->id) { - node_get_stack(node, stack, nsin, nsout); - node_group_execute(stack, callerdata, node, nsin, nsout); - } - } - } -} - -/* clear one pixel in all the preview images */ -void ntreeClearPixelTree(bNodeTree *ntree, int x, int y) -{ - bNode *node; - float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + if(thread) + stack= ntree->stack1; + else + stack= ntree->stack; - /* only when initialized */ - if(ntree->init & NTREE_EXEC_INIT) { - for(node= ntree->nodes.first; node; node= node->next) { - if(node->preview) - nodeAddToPreview(node, vec, x, y); + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->execfunc) { + node_get_stack(node, stack, nsin, nsout); + node->typeinfo->execfunc(callerdata, node, nsin, nsout); + } + else if(node->type==NODE_GROUP && node->id) { + node_get_stack(node, stack, nsin, nsout); + node_group_execute(stack, callerdata, node, nsin, nsout); } } } + diff --git a/source/blender/blenkernel/intern/node_composit.c b/source/blender/blenkernel/intern/node_composit.c new file mode 100644 index 00000000000..b7d70b167ba --- /dev/null +++ b/source/blender/blenkernel/intern/node_composit.c @@ -0,0 +1,1372 @@ +/** + * $Id$ + * + * ***** BEGIN GPL 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. + * + * 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) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "DNA_ID.h" +#include "DNA_image_types.h" +#include "DNA_node_types.h" +#include "DNA_material_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_vec_types.h" + +#include "BKE_blender.h" +#include "BKE_colortools.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_node.h" +#include "BKE_material.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" + +#include "MEM_guardedalloc.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "RE_pipeline.h" + +/* *************************** operations support *************************** */ + +/* general signal that's in output sockets, and goes over the wires */ +typedef struct CompBuf { + float *rect; + int x, y; + short type, malloc; + rcti disprect; /* cropped part of image */ + int xof, yof; /* relative to center of target image */ +} CompBuf; + +/* defines also used for pixel size */ +#define CB_RGBA 4 +#define CB_VAL 1 + +static CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc) +{ + CompBuf *cbuf= MEM_callocN(sizeof(CompBuf), "compbuf"); + + cbuf->x= sizex; + cbuf->y= sizey; + cbuf->type= type; + if(alloc) { + if(cbuf->type==CB_RGBA) + cbuf->rect= MEM_mallocN(4*sizeof(float)*sizex*sizey, "new rect"); + else + cbuf->rect= MEM_mallocN(sizeof(float)*sizex*sizey, "new rect"); + cbuf->malloc= 1; + } + cbuf->disprect.xmin= 0; + cbuf->disprect.ymin= 0; + cbuf->disprect.xmax= sizex; + cbuf->disprect.ymax= sizey; + + return cbuf; +} + +void free_compbuf(CompBuf *cbuf) +{ + if(cbuf->malloc && cbuf->rect) + MEM_freeN(cbuf->rect); + MEM_freeN(cbuf); +} + +#if 0 +/* on first call, disprect should be initialized to 'out', then you can call this on all 'src' images */ +static void get_overlap_rct(CompBuf *out, CompBuf *src, rcti *disprect) +{ + rcti rect; + /* output center is considered (0,0) */ + + if(src==NULL) return; + + /* translate src into output space */ + rect= src->disprect; + BLI_translate_rcti(&rect, out->xof-src->xof, out->xof-src->xof); + /* intersect rect with current disprect */ + + BLI_isect_rcti(&rect, disprect, disprect); +} + +static void get_scanline_rcti(CompBuf *out, rcti *disprect, CompBuf *src, rcti *srcrect) +{ + int xof, yof; + + /* translate src into output space */ + xof= out->xof-src->xof; + yof= out->xof-src->xof; + + srcrect->xmin= disprect->xmin + xof; + srcrect->ymin= disprect->ymin + yof; + srcrect->xmax= disprect->xmax + xof; + srcrect->ymax= disprect->ymax + yof; +} +#endif + +/* Pixel-to-Pixel operation, 1 Image in, 1 out */ +static void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col, + void (*func)(bNode *, float *, float *)) +{ + float *outfp, *srcfp, *out_data, *src_data; + int outx, outy; + int srcx, srcy; + int out_pix, out_stride, src_stride, src_pix, x, y; + + outx= out->x; + outy= out->y; + out_pix= out->type; + out_stride= out->x; + out_data= out->rect; + + /* handle case when input is constant color */ + if(src_buf==NULL) { + srcx= outx; srcy= outy; + src_stride= 0; + src_pix= 0; + src_data= src_col; + } + else { + srcx= src_buf->x; + srcy= src_buf->y; + src_stride= srcx; + src_pix= src_buf->type; + src_data= src_buf->rect; + } + + outx= MIN2(outx, srcx); + outy= MIN2(outy, srcy); + + for(y=0; y<outy; y++) { + /* set scanlines on right location */ + srcfp= src_data + src_pix*y*src_stride; + outfp= out_data + out_pix*y*out_stride; + + for(x=0; x<outx; x++) { + func(node, outfp, srcfp); + srcfp += src_pix; + outfp += out_pix; + } + } +} + +/* Pixel-to-Pixel operation, 2 Images in, 1 out */ +static void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col, + CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *)) +{ + float *outfp, *srcfp, *src_data, *facfp, *fac_data; + int outx= out->x, outy= out->y; + int srcx, srcy, facx, facy; + int out_pix, src_stride, src_pix, fac_stride, fac_pix, x, y; + + out_pix= out->type; + + /* handle case when input is constant color */ + if(src_buf==NULL) { + srcx= outx; srcy= outy; + src_stride= 0; + src_pix= 0; + src_data= src_col; + } + else { + srcx= src_buf->x; + srcy= src_buf->y; + src_stride= srcx; + src_pix= src_buf->type; + src_data= src_buf->rect; + } + + /* factor buf or constant? */ + if(fac_buf==NULL) { + facx= outx; facy= outy; + fac_stride= 0; + fac_pix= 0; + fac_data= fac; + } + else { + facx= fac_buf->x; + facy= fac_buf->y; + fac_stride= facx; + fac_pix= src_buf->type; + fac_data= fac_buf->rect; + } + + if(fac_data==NULL) { + printf("fac buffer error, node %s\n", node->name); + return; + } + + facx= MIN2(facx, srcx); + facy= MIN2(facy, srcy); + +#if 0 + if(src_buf) { + rcti disprect; + + disprect= out->disprect; + get_overlap_rct(out, src_buf, &disprect); + printf("%s\n", node->name); + printf("union %d %d %d %d\n", disprect.xmin,disprect.ymin,disprect.xmax,disprect.ymax); + } + /* new approach */ + outfp= out->rect_float + src.ymin*outx + ; + for(y=src.ymin; y<src.ymax; y++) { + + /* all operators available */ + if(y>=disp.ymin && y<disp.ymax) { + srcfp= src_data + (src_stride*(y+scrc.ymin) + src.xmin); + facfp= fac_data + (fac_stride*(y+fac.ymin) + fac.xmin); + + for(x= src.xmin; x<src.xmax; x++) { + if(x>=disp.xmin && x<disp.xmax) { + + srcfp+= src_pix; + facfp+= fac_pix; + } + else { + /* copy src1 */ + } + } + } + else { + /* copy src1 */ + srcfp= src_data + (src_stride*(y+scrc.ymin) + src.xmin); + + QUATCOPY(outfp, srcfp); + } + } +#endif + + outfp= out->rect; + for(y=0; y<outy; y++) { + /* set source scanline on right location */ + srcfp= src_data + src_pix*y*src_stride; + facfp= fac_data + fac_pix*y*fac_stride; + + for(x=0; x<outx; x++, outfp+=out_pix) { + if(x<facx && y<facy) + func(node, outfp, srcfp, facfp); + srcfp += src_pix; + facfp += fac_pix; + } + } +} + +/* Pixel-to-Pixel operation, 3 Images in, 1 out */ +static void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col, + CompBuf *fac_buf, float fac, void (*func)(bNode *, float *, float *, float *, float)) +{ + float *outfp, *src1fp, *src2fp, *facfp, *src1_data, *src2_data, *fac_data; + int outx= out->x, outy= out->y; + int src1x, src1y, src2x, src2y, facx, facy; + int src1_stride, src1_pix, src2_stride, src2_pix, fac_stride, fac_pix, x, y; + + /* handle case when input has constant color */ + if(src1_buf==NULL) { + src1x= outx; src1y= outy; + src1_stride= 0; + src1_pix= 0; + src1_data= src1_col; + } + else { + src1x= src1_buf->x; + src1y= src1_buf->y; + src1_stride= src1x; + src1_pix= src1_buf->type; + src1_data= src1_buf->rect; + } + + if(src2_buf==NULL) { + src2x= outx; src2y= outy; + src2_stride= 0; + src2_pix= 0; + src2_data= src2_col; + } + else { + src2x= src2_buf->x; + src2y= src2_buf->y; + src2_stride= src2x; + src2_pix= src2_buf->type; + src2_data= src2_buf->rect; + } + + /* factor buf or constant? */ + if(fac_buf==NULL) { + facx= outx; facy= outy; + fac_stride= 0; + fac_pix= 0; + fac_data= &fac; + } + else { + facx= fac_buf->x; + facy= fac_buf->y; + fac_stride= facx; + fac_pix= 1; + fac_data= fac_buf->rect; + } + + facx= MIN3(facx, src1x, src2x); + facy= MIN3(facy, src1y, src2y); + + outfp= out->rect; + for(y=0; y<outy; y++) { + + /* set source scanlines on right location */ + src1fp= src1_data + src1_pix*y*src1_stride; + src2fp= src2_data + src2_pix*y*src2_stride; + facfp= fac_data + y*fac_stride; + + for(x=0; x<outx; x++, outfp+=4) { + if(x<facx && y<facy) + func(node, outfp, src1fp, src2fp, *facfp); + src1fp+= src1_pix; + src2fp+= src2_pix; + facfp+= fac_pix; + } + } +} + +/* */ +static CompBuf *alphabuf_from_rgbabuf(CompBuf *cbuf) +{ + CompBuf *valbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); + float *valf, *rectf; + int tot; + + valf= valbuf->rect; + rectf= cbuf->rect + 3; + for(tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4) + *valf= *rectf; + + return valbuf; +} + +static void generate_preview(bNode *node, CompBuf *stackbuf) +{ + bNodePreview *preview= node->preview; + + if(preview) { + ImBuf *ibuf= IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0, 0); /* empty */ + + if(stackbuf->x > stackbuf->y) { + preview->xsize= 140; + preview->ysize= (140*stackbuf->y)/stackbuf->x; + } + else { + preview->ysize= 140; + preview->xsize= (140*stackbuf->x)/stackbuf->y; + } + ibuf->rect_float= stackbuf->rect; + ibuf= IMB_scalefastImBuf(ibuf, preview->xsize, preview->ysize); + + /* this ensures free-imbuf does the right stuff */ + SWAP(float *, ibuf->rect_float, node->preview->rect); + + IMB_freeImBuf(ibuf); + } +} + +/* ******************************************************** */ +/* ********* Composit Node type definitions ***************** */ +/* ******************************************************** */ + +/* SocketType syntax: + socket type, max connections (0 is no limit), name, 4 values for default, 2 values for range */ + +/* Verification rule: If name changes, a saved socket and its links will be removed! Type changes are OK */ + +/* **************** OUTPUT ******************** */ +static bNodeSocketType cmp_node_output_in[]= { + { SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 1, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void do_copy_rgba(bNode *node, float *out, float *in) +{ + QUATCOPY(out, in); +} +static void do_copy_a_rgba(bNode *node, float *out, float *in, float *fac) +{ + VECCOPY(out, in); + out[3]= *fac; +} + +static void node_composit_exec_output(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* image assigned to output */ + /* stack order input sockets: col, alpha */ + + if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ + Image *ima= (Image *)node->id; + CompBuf *cbuf; + int rectx, recty; + + /* scene size? */ + if(1) { + /* re-create output, derive size from scene */ + rectx= (G.scene->r.size*G.scene->r.xsch)/100; + recty= (G.scene->r.size*G.scene->r.ysch)/100; + + if(ima->ibuf) IMB_freeImBuf(ima->ibuf); + ima->ibuf= IMB_allocImBuf(rectx, recty, 32, IB_rectfloat, 0); // do alloc + + cbuf= alloc_compbuf(rectx, recty, CB_RGBA, 0); // no alloc + cbuf->rect= ima->ibuf->rect_float; + + /* when no alpha, we can simply copy */ + if(in[1]->data==NULL) + composit1_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, do_copy_rgba); + else + composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba); + + generate_preview(node, cbuf); + free_compbuf(cbuf); + } + else { /* test */ + if(ima->ibuf) IMB_freeImBuf(ima->ibuf); + ima->ibuf= IMB_allocImBuf(rectx, recty, 32, 0, 0); // do alloc + ima->ibuf->mall= IB_rectfloat; + cbuf= in[0]->data; + ima->ibuf->rect_float= cbuf->rect; + ima->ibuf->x= cbuf->x; + ima->ibuf->y= cbuf->y; + cbuf->rect= NULL; + } + + } + else if(in[0]->data) + generate_preview(node, in[0]->data); +} + +static bNodeType cmp_node_output= { + /* type code */ CMP_NODE_OUTPUT, + /* name */ "Output", + /* width+range */ 80, 60, 200, + /* class+opts */ NODE_CLASS_OUTPUT, NODE_PREVIEW, + /* input sock */ cmp_node_output_in, + /* output sock */ NULL, + /* storage */ "", + /* execfunc */ node_composit_exec_output + +}; + +/* **************** IMAGE ******************** */ +static bNodeSocketType cmp_node_image_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* image assigned to output */ + /* stack order input sockets: col, alpha */ + if(node->id) { + Image *ima= (Image *)node->id; + CompBuf *stackbuf; + + /* test if image is OK */ + if(ima->ok==0) return; + if(ima->ibuf==NULL) { + load_image(ima, IB_rect, G.sce, G.scene->r.cfra); + if(ima->ibuf==NULL) { + ima->ok= 0; + return; + } + } + if(ima->ibuf->rect_float==NULL) + IMB_float_from_rect(ima->ibuf); + + /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */ + stackbuf= alloc_compbuf(ima->ibuf->x, ima->ibuf->y, CB_RGBA, 0); + stackbuf->rect= ima->ibuf->rect_float; + + /* put ibuf on stack */ + out[0]->data= stackbuf; + + if(out[1]->hasoutput) + out[1]->data= alphabuf_from_rgbabuf(stackbuf); + + generate_preview(node, stackbuf); + } +} + +static bNodeType cmp_node_image= { + /* type code */ CMP_NODE_IMAGE, + /* name */ "Image", + /* width+range */ 120, 80, 300, + /* class+opts */ NODE_CLASS_GENERATOR, NODE_PREVIEW|NODE_OPTIONS, + /* input sock */ NULL, + /* output sock */ cmp_node_image_out, + /* storage */ "", + /* execfunc */ node_composit_exec_image + +}; + +/* **************** RENDER RESULT ******************** */ +static bNodeSocketType cmp_node_rresult_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_composit_exec_rresult(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + RenderResult *rr= RE_GetResult(RE_GetRender("Render")); + if(rr) { + RenderLayer *rl= rr->layers.first; + CompBuf *stackbuf; + + /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */ + stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0); + stackbuf->rect= rl->rectf; + + /* put on stack */ + out[0]->data= stackbuf; + + if(out[1]->hasoutput) + out[1]->data= alphabuf_from_rgbabuf(stackbuf); + + generate_preview(node, stackbuf); + } +} + +static bNodeType cmp_node_rresult= { + /* type code */ CMP_NODE_R_RESULT, + /* name */ "Render Result", + /* width+range */ 120, 80, 300, + /* class+opts */ NODE_CLASS_GENERATOR, NODE_PREVIEW, + /* input sock */ NULL, + /* output sock */ cmp_node_rresult_out, + /* storage */ "", + /* execfunc */ node_composit_exec_rresult + +}; + +/* **************** NORMAL ******************** */ +static bNodeSocketType cmp_node_normal_in[]= { + { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketType cmp_node_normal_out[]= { + { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f}, + { SOCK_VALUE, 0, "Dot", 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +/* generates normal, does dot product */ +static void node_composit_exec_normal(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + bNodeSocket *sock= node->outputs.first; + /* stack order input: normal */ + /* stack order output: normal, value */ + + VECCOPY(out[0]->vec, sock->ns.vec); + /* render normals point inside... the widget points outside */ + out[1]->vec[0]= -INPR(out[0]->vec, in[0]->vec); +} + +static bNodeType cmp_node_normal= { + /* type code */ CMP_NODE_NORMAL, + /* name */ "Normal", + /* width+range */ 100, 60, 200, + /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS, + /* input sock */ cmp_node_normal_in, + /* output sock */ cmp_node_normal_out, + /* storage */ "", + /* execfunc */ node_composit_exec_normal + +}; + +/* **************** CURVE VEC ******************** */ +static bNodeSocketType cmp_node_curve_vec_in[]= { + { SOCK_VECTOR, 1, "Vector", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketType cmp_node_curve_vec_out[]= { + { SOCK_VECTOR, 0, "Vector", 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_composit_exec_curve_vec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order input: vec */ + /* stack order output: vec */ + + curvemapping_evaluate_premulRGBF(node->storage, out[0]->vec, in[0]->vec); +} + +static bNodeType cmp_node_curve_vec= { + /* type code */ CMP_NODE_CURVE_VEC, + /* name */ "Vector Curves", + /* width+range */ 200, 140, 320, + /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS, + /* input sock */ cmp_node_curve_vec_in, + /* output sock */ cmp_node_curve_vec_out, + /* storage */ "CurveMapping", + /* execfunc */ node_composit_exec_curve_vec + +}; + +/* **************** CURVE RGB ******************** */ +static bNodeSocketType cmp_node_curve_rgb_in[]= { + { SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketType cmp_node_curve_rgb_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f}, + { -1, 0, "" } +}; + +static void do_curves(bNode *node, float *out, float *in) +{ + curvemapping_evaluateRGBF(node->storage, out, in); + out[3]= in[3]; +} + +static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order input: vec */ + /* stack order output: vec */ + + if(out[0]->hasoutput==0) + return; + + /* input no image? then only color operation */ + if(in[0]->data==NULL) { + curvemapping_evaluateRGBF(node->storage, out[0]->vec, in[0]->vec); + } + else { + /* make output size of input image */ + CompBuf *cbuf= in[0]->data; + CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs + + curvemapping_premultiply(node->storage, 0); + composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_curves); + curvemapping_premultiply(node->storage, 1); + + out[0]->data= stackbuf; + } + +} + +static bNodeType cmp_node_curve_rgb= { + /* type code */ CMP_NODE_CURVE_RGB, + /* name */ "RGB Curves", + /* width+range */ 200, 140, 320, + /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS, + /* input sock */ cmp_node_curve_rgb_in, + /* output sock */ cmp_node_curve_rgb_out, + /* storage */ "CurveMapping", + /* execfunc */ node_composit_exec_curve_rgb + +}; + +/* **************** VALUE ******************** */ +static bNodeSocketType cmp_node_value_out[]= { + { SOCK_VALUE, 0, "Value", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_composit_exec_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + bNodeSocket *sock= node->outputs.first; + + out[0]->vec[0]= sock->ns.vec[0]; +} + +static bNodeType cmp_node_value= { + /* type code */ CMP_NODE_VALUE, + /* name */ "Value", + /* width+range */ 80, 40, 120, + /* class+opts */ NODE_CLASS_GENERATOR, NODE_OPTIONS, + /* input sock */ NULL, + /* output sock */ cmp_node_value_out, + /* storage */ "", + /* execfunc */ node_composit_exec_value + +}; + +/* **************** RGB ******************** */ +static bNodeSocketType cmp_node_rgb_out[]= { + { SOCK_RGBA, 0, "RGBA", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_composit_exec_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + bNodeSocket *sock= node->outputs.first; + + VECCOPY(out[0]->vec, sock->ns.vec); +} + +static bNodeType cmp_node_rgb= { + /* type code */ CMP_NODE_RGB, + /* name */ "RGB", + /* width+range */ 100, 60, 140, + /* class+opts */ NODE_CLASS_GENERATOR, NODE_OPTIONS, + /* input sock */ NULL, + /* output sock */ cmp_node_rgb_out, + /* storage */ "", + /* execfunc */ node_composit_exec_rgb + +}; + +/* **************** MIX RGB ******************** */ +static bNodeSocketType cmp_node_mix_rgb_in[]= { + { SOCK_VALUE, 1, "Fac", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_mix_rgb_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void do_mix_rgb(bNode *node, float *out, float *in1, float *in2, float fac) +{ + float col[3]; + + VECCOPY(col, in1); + ramp_blend(node->custom1, col, col+1, col+2, fac, in2); + VECCOPY(out, col); + out[3]= in1[3]; +} + +static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order in: fac, Image, Image */ + /* stack order out: Image */ + float fac= in[0]->vec[0]; + + CLAMP(fac, 0.0f, 1.0f); + + /* input no image? then only color operation */ + if(in[1]->data==NULL && in[2]->data==NULL) { + do_mix_rgb(node, out[0]->vec, in[1]->vec, in[2]->vec, fac); + } + else { + /* make output size of first available input image */ + CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data; + CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs + + composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, fac, do_mix_rgb); + + out[0]->data= stackbuf; + } +} + +static bNodeType cmp_node_mix_rgb= { + /* type code */ CMP_NODE_MIX_RGB, + /* name */ "Mix", + /* width+range */ 80, 40, 120, + /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS, + /* input sock */ cmp_node_mix_rgb_in, + /* output sock */ cmp_node_mix_rgb_out, + /* storage */ "", + /* execfunc */ node_composit_exec_mix_rgb + +}; + +/* **************** FILTER ******************** */ +static bNodeSocketType cmp_node_filter_in[]= { + { SOCK_VALUE, 1, "Fac", 1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_filter_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac) +{ + float *row1, *row2, *row3; + float *fp, f1, f2, mfac= 1.0f-fac; + int rowlen, x, y, c; + + rowlen= in->x; + + if(in->type==CB_RGBA) { + + for(y=2; y<in->y; y++) { + /* setup rows */ + row1= in->rect + 4*(y-2)*rowlen; + row2= row1 + 4*rowlen; + row3= row2 + 4*rowlen; + fp= out->rect + 4*(y-1)*rowlen + 4; + + for(x=2; x<rowlen; x++) { + for(c=0; c<3; c++) { + f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]; + f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8]; + fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2); + fp++; row1++; row2++; row3++; + } + fp[0]= row2[4]; + /* no alpha... will clear it completely */ + fp++; row1++; row2++; row3++; + } + } + } +} + +static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac) +{ + float *row1, *row2, *row3; + float *fp, mfac= 1.0f-fac; + int rowlen, x, y, c; + + rowlen= in->x; + + if(in->type==CB_RGBA) { + + for(y=2; y<in->y; y++) { + /* setup rows */ + row1= in->rect + 4*(y-2)*rowlen; + row2= row1 + 4*rowlen; + row3= row2 + 4*rowlen; + fp= out->rect + 4*(y-1)*rowlen + 4; + + for(x=2; x<rowlen; x++) { + for(c=0; c<4; c++) { + fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]); + fp++; row1++; row2++; row3++; + } + } + } + } +} + +static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f}; + float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1}; + float laplace[9]= {1/8.0f, -1/8.0f, 1/8.0f, -1/8.0f, 1.0f, -1/8.0f, 1/8.0f, -1/8.0f, 1/8.0f}; + float sobel[9]= {1,2,1,0,0,0,-1,-2,-1}; + float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1}; + float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2}; + float shadow[9]= {1,2,1,0,1,0,-1,-2,-1}; + + /* stack order in: Image */ + /* stack order out: Image */ + + if(in[1]->data) { + /* make output size of first available input image */ + CompBuf *cbuf= in[1]->data; + CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs + + switch(node->custom1) { + case CMP_FILT_SOFT: + do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]); + break; + case CMP_FILT_SHARP: + do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]); + break; + case CMP_FILT_LAPLACE: + do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]); + break; + case CMP_FILT_SOBEL: + do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]); + break; + case CMP_FILT_PREWITT: + do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]); + break; + case CMP_FILT_KIRSCH: + do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]); + break; + case CMP_FILT_SHADOW: + do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]); + break; + } + + out[0]->data= stackbuf; + } +} + +static bNodeType cmp_node_filter= { + /* type code */ CMP_NODE_FILTER, + /* name */ "Filter", + /* width+range */ 80, 40, 120, + /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS, + /* input sock */ cmp_node_filter_in, + /* output sock */ cmp_node_filter_out, + /* storage */ "", + /* execfunc */ node_composit_exec_filter + +}; + + +/* **************** VALTORGB ******************** */ +static bNodeSocketType cmp_node_valtorgb_in[]= { + { SOCK_VALUE, 1, "Fac", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_valtorgb_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void do_colorband_composit(bNode *node, float *out, float *in) +{ + do_colorband(node->storage, in[0], out); +} + +static void node_composit_exec_valtorgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order in: fac */ + /* stack order out: col, alpha */ + + if(node->storage) { + /* input no image? then only color operation */ + if(in[0]->data==NULL) { + do_colorband(node->storage, in[0]->vec[0], out[0]->vec); + } + else { + /* make output size of input image */ + CompBuf *cbuf= in[0]->data; + CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs + + composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_colorband_composit); + + out[0]->data= stackbuf; + + if(out[1]->hasoutput) + out[1]->data= alphabuf_from_rgbabuf(stackbuf); + + } + } +} + +static bNodeType cmp_node_valtorgb= { + /* type code */ CMP_NODE_VALTORGB, + /* name */ "ColorRamp", + /* width+range */ 240, 200, 300, + /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS, + /* input sock */ cmp_node_valtorgb_in, + /* output sock */ cmp_node_valtorgb_out, + /* storage */ "ColorBand", + /* execfunc */ node_composit_exec_valtorgb + +}; + + +/* **************** RGBTOBW ******************** */ +static bNodeSocketType cmp_node_rgbtobw_in[]= { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_rgbtobw_out[]= { + { SOCK_VALUE, 0, "Val", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void do_rgbtobw(bNode *node, float *out, float *in) +{ + out[0]= in[0]*0.35f + in[1]*0.45f + in[2]*0.2f; +} + +static void node_composit_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order out: bw */ + /* stack order in: col */ + + /* input no image? then only color operation */ + if(in[0]->data==NULL) { + out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f; + } + else { + /* make output size of input image */ + CompBuf *cbuf= in[0]->data; + CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs + + composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_rgbtobw); + + out[0]->data= stackbuf; + } +} + +static bNodeType cmp_node_rgbtobw= { + /* type code */ CMP_NODE_RGBTOBW, + /* name */ "RGB to BW", + /* width+range */ 80, 40, 120, + /* class+opts */ NODE_CLASS_OPERATOR, 0, + /* input sock */ cmp_node_rgbtobw_in, + /* output sock */ cmp_node_rgbtobw_out, + /* storage */ "", + /* execfunc */ node_composit_exec_rgbtobw + +}; + +/* **************** ALPHAOVER ******************** */ +static bNodeSocketType cmp_node_alphaover_in[]= { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_alphaover_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void do_alphaover(bNode *node, float *out, float *src, float *dest) +{ + float mul= 1.0f - dest[3]; + + if(mul<=0.0f) { + QUATCOPY(out, dest); + } + else { + out[0]= (mul*src[0]) + dest[0]; + out[1]= (mul*src[1]) + dest[1]; + out[2]= (mul*src[2]) + dest[2]; + out[3]= (mul*src[3]) + dest[3]; + } +} + +static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order in: col col */ + /* stack order out: col */ + + /* input no image? then only color operation */ + if(in[0]->data==NULL) { + do_alphaover(node, out[0]->vec, in[0]->vec, in[1]->vec); + } + else { + /* make output size of input image */ + CompBuf *cbuf= in[0]->data; + CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs + + composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_alphaover); + + out[0]->data= stackbuf; + } +} + +static bNodeType cmp_node_alphaover= { + /* type code */ CMP_NODE_ALPHAOVER, + /* name */ "AlphaOver", + /* width+range */ 80, 40, 120, + /* class+opts */ NODE_CLASS_OPERATOR, 0, + /* input sock */ cmp_node_alphaover_in, + /* output sock */ cmp_node_alphaover_out, + /* storage */ "", + /* execfunc */ node_composit_exec_alphaover + +}; + +/* **************** GAUSS BLUR ******************** */ +static bNodeSocketType cmp_node_blur_in[]= { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_blur_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + + +static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + CompBuf *new, *work, *img= in[0]->data; + register float sum, val; + float rval, gval, bval, aval; + float *gausstab, *v; + int r, n, m; + int x, y; + int i; + int step, bigstep; + float *src, *dest; + + + if(img==NULL || out[0]->hasoutput==0) + return; + + /* make output size of input image */ + new= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs + out[0]->data= new; + + /* prepare for gauss tab */ + r = (1.5 * node->custom1 + 1.5); + n = 2 * r + 1; + + /* ugly : */ + if ((img->x <= n) || (img->y <= n)) { + printf("gauss filter too large/n"); + return; + } + + gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss"); + + sum = 0.0f; + v = gausstab; + for (x = -r; x <= r; x++) { + val = exp(-4*(float ) (x*x)/ (float) (r*r)); + sum += val; + *v++ = val; + } + + i = n; + v = gausstab; + while (i--) { + *v++ /= sum; + } + + /* helper image */ + work= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs + + /* horizontal */ + step = (n - 1); + + for (y = 0; y < img->y; y++) { + src = img->rect + 4*(y * img->x); + dest = work->rect + 4*(y * img->x); + + for (x = r; x > 0 ; x--) { + m = n - x; + gval = rval= bval= aval= 0.0f; + sum = 0.0; + v = gausstab + x; + for (i = 0; i < m; i++) { + val = *v++; + sum += val; + rval += val * (*src++); + gval += val * (*src++); + bval += val * (*src++); + aval += val * (*src++); + } + *dest++ = rval / sum; + *dest++ = gval / sum; + *dest++ = bval / sum; + *dest++ = aval / sum; + + src -= 4*m; + } + + for (x = 0; x <= (img->x - n); x++) { + gval = rval= bval= aval= 0.0f; + v = gausstab; + + for (i = 0; i < n; i++) { + val = *v++; + rval += val * (*src++); + gval += val * (*src++); + bval += val * (*src++); + aval += val * (*src++); + } + *dest++ = rval; + *dest++ = gval; + *dest++ = bval; + *dest++ = aval; + src -= 4*step; + } + + for (x = 1; x <= r ; x++) { + m = n - x; + gval = rval= bval= aval= 0.0f; + sum = 0.0; + v = gausstab; + for (i = 0; i < m; i++) { + val = *v++; + sum += val; + rval += val * (*src++); + gval += val * (*src++); + bval += val * (*src++); + aval += val * (*src++); + } + *dest++ = rval / sum; + *dest++ = gval / sum; + *dest++ = bval / sum; + *dest++ = aval / sum; + src -= 4*(m - 1); + } + } + + /* vertical */ + MEM_freeN(gausstab); + + /* prepare for gauss tab */ + r = (1.5 * node->custom2 + 1.5); + n = 2 * r + 1; + + /* ugly : */ + if ((img->x <= n) || (img->y <= n)) { + printf("gauss filter too large/n"); + return; + } + + gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss"); + + sum = 0.0f; + v = gausstab; + for (x = -r; x <= r; x++) { + val = exp(-4*(float ) (x*x)/ (float) (r*r)); + sum += val; + *v++ = val; + } + + i = n; + v = gausstab; + while (i--) { + *v++ /= sum; + } + + step = img->x; + bigstep = (n - 1) * step; + for (x = 0; x < step ; x++) { + dest = new->rect + 4*x; + src = work->rect + 4*x; + + for (y = r; y > 0; y--) { + m = n - y; + gval = rval= bval= aval= 0.0f; + sum = 0.0; + v = gausstab + y; + for (i = 0; i < m; i++) { + val = *v++; + sum += val; + rval += val * src[0]; + gval += val * src[1]; + bval += val * src[2]; + aval += val * src[3]; + src += 4 * step; + } + dest[0] = rval / sum; + dest[1] = gval / sum; + dest[2] = bval / sum; + dest[3] = aval / sum; + src -= 4 * m * step; + dest+= 4 * step; + } + for (y = 0; y <= (img->y - n); y++) { + gval = rval= bval= aval= 0.0f; + v = gausstab; + for (i = 0; i < n; i++) { + val = *v++; + rval += val * src[0]; + gval += val * src[1]; + bval += val * src[2]; + aval += val * src[3]; + src += 4 * step; + } + dest[0] = rval; + dest[1] = gval; + dest[2] = bval; + dest[3] = aval; + dest += 4 * step; + src -= 4 * bigstep; + } + for (y = 1; y <= r ; y++) { + m = n - y; + gval = rval= bval= aval= 0.0f; + sum = 0.0; + v = gausstab; + for (i = 0; i < m; i++) { + val = *v++; + sum += val; + rval += val * src[0]; + gval += val * src[1]; + bval += val * src[2]; + aval += val * src[3]; + src += 4 * step; + } + dest[0] = rval / sum; + dest[1] = gval / sum; + dest[2] = bval / sum; + dest[3] = aval / sum; + dest += 4* step; + src -= 4 * (m - 1) * step; + } + } + + free_compbuf(work); + MEM_freeN(gausstab); +} + +static bNodeType cmp_node_blur= { + /* type code */ CMP_NODE_BLUR, + /* name */ "Blur", + /* width+range */ 120, 80, 200, + /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS, + /* input sock */ cmp_node_blur_in, + /* output sock */ cmp_node_blur_out, + /* storage */ "", + /* execfunc */ node_composit_exec_blur + +}; + + +/* ****************** types array for all shaders ****************** */ + +bNodeType *node_all_composit[]= { + &node_group_typeinfo, + &cmp_node_output, + &cmp_node_value, + &cmp_node_rgb, + &cmp_node_mix_rgb, + &cmp_node_filter, + &cmp_node_valtorgb, + &cmp_node_rgbtobw, + &cmp_node_normal, + &cmp_node_curve_vec, + &cmp_node_curve_rgb, + &cmp_node_image, + &cmp_node_rresult, + &cmp_node_alphaover, + &cmp_node_blur, + NULL +}; + +/* ******************* execute and parse ************ */ + +void ntreeCompositExecTree(bNodeTree *ntree) +{ + + ntreeInitPreview(ntree, 0, 0); + ntreeBeginExecTree(ntree); + + /* allocate composit data */ + + ntreeExecTree(ntree, NULL, 0); /* threads */ + + ntreeEndExecTree(ntree); +} + diff --git a/source/blender/blenkernel/intern/node_shaders.c b/source/blender/blenkernel/intern/node_shaders.c index 944db32ccc1..4e65b36588c 100644 --- a/source/blender/blenkernel/intern/node_shaders.c +++ b/source/blender/blenkernel/intern/node_shaders.c @@ -38,6 +38,7 @@ #include "BKE_blender.h" #include "BKE_colortools.h" #include "BKE_node.h" +#include "BKE_material.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -46,7 +47,7 @@ #include "MEM_guardedalloc.h" -#include "render.h" /* <- shadeinput/output */ +#include "RE_shader_ext.h" /* <- ShadeInput Shaderesult TexResult */ /* ********* exec data struct, remains internal *********** */ @@ -727,11 +728,11 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) scd.shi= shi; scd.shr= shr; - ntreeExecTree(ntree, &scd, shi->ys & 1); /* threads */ + ntreeExecTree(ntree, &scd, shi->thread); /* threads */ } /* go over all used Geometry and Texture nodes, and return a texco flag */ -int ntreeShaderGetTexco(bNodeTree *ntree) +int ntreeShaderGetTexco(bNodeTree *ntree, int osa) { bNode *node; bNodeSocket *sock; @@ -741,8 +742,7 @@ int ntreeShaderGetTexco(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= node->next) { if(node->type==SH_NODE_TEXTURE) { - /* this r.osa is sorta weak... */ - if(R.osa && node->id) { + if(osa && node->id) { Tex *tex= (Tex *)node->id; if ELEM3(tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) texco |= TEXCO_OSA; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d60236d226c..0b52c92f50e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -995,10 +995,10 @@ void make_local_object(Object *ob) float bluroffs= 0.0; int no_speed_curve= 0; -void set_mblur_offs(int blur) +/* ugly call from render */ +void set_mblur_offs(float blur) { - bluroffs= R.r.blurfac*((float)blur); - bluroffs/= (float)R.r.osa; + bluroffs= blur; } void disable_speed_curve(int val) @@ -1012,9 +1012,9 @@ float bsystem_time(Object *ob, Object *par, float cfra, float ofs) /* returns float ( see frame_to_float in ipo.c) */ /* 2nd field */ - if(R.flag & R_SEC_FIELD) { - if(R.r.mode & R_FIELDSTILL); else cfra+= .5; - } +// if(R.flag & R_SEC_FIELD) { +// if(R.r.mode & R_FIELDSTILL); else cfra+= .5; +// } cfra+= bluroffs; diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index f0058ee6ad0..cb47c43da06 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -52,24 +52,19 @@ #include "DNA_sound_types.h" #include "DNA_vfont_types.h" #include "DNA_packedFile_types.h" - +#include "DNA_scene_types.h" #include "BLI_blenlib.h" #include "BKE_utildefines.h" -#include "BKE_bad_level_calls.h" - #include "BKE_global.h" #include "BKE_main.h" - #include "BKE_screen.h" - #include "BKE_sound.h" -//#include "sound.h" - #include "BKE_image.h" #include "BKE_font.h" #include "BKE_packedFile.h" +#include "BKE_bad_level_calls.h" /* <- waitcursor */ int seekPackedFile(PackedFile * pf, int offset, int whence) { @@ -309,7 +304,7 @@ int writePackedFile(char * filename, PackedFile *pf) } // make sure the path to the file exists... - RE_make_existing_file(name); + BLI_make_existing_file(name); file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); if (file >= 0) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index df9e626abbf..546a22c361b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -70,6 +70,7 @@ #include "BKE_key.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_scene.h" #include "BKE_world.h" @@ -153,6 +154,11 @@ void free_scene(Scene *sce) free_forest(sce->theDag); MEM_freeN(sce->theDag); } + + if(sce->nodetree) { + ntreeFreeTree(sce->nodetree); + MEM_freeN(sce->nodetree); + } } Scene *add_scene(char *name) @@ -172,8 +178,8 @@ Scene *add_scene(char *name) sce->r.ysch= 256; sce->r.xasp= 1; sce->r.yasp= 1; - sce->r.xparts= 1; - sce->r.yparts= 1; + sce->r.xparts= 4; + sce->r.yparts= 4; sce->r.size= 100; sce->r.planes= 24; sce->r.quality= 90; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index ea0134470f1..2633bbd2779 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -39,6 +39,7 @@ #include "BLI_blenlib.h" +#include "DNA_scene_types.h" #include "DNA_text_types.h" #include "BKE_bad_level_calls.h" diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 902b3a5edfe..aa36c0a5083 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -57,6 +57,7 @@ #include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_image_types.h" +#include "DNA_world_types.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -158,6 +159,10 @@ void open_plugin_tex(PluginTex *pit) /* ------------------------------------------------------------------------- */ +/* very badlevel define to bypass linking with BIF_interface.h */ +#define INT 96 +#define FLO 128 + PluginTex *add_plugin_tex(char *str) { PluginTex *pit; @@ -381,7 +386,7 @@ void free_texture(Tex *tex) { free_plugin_tex(tex->plugin); if(tex->coba) MEM_freeN(tex->coba); - if(tex->env) RE_free_envmap(tex->env); + if(tex->env) BKE_free_envmap(tex->env); BKE_icon_delete((struct ID*)tex); tex->id.icon_id = 0; } @@ -527,7 +532,7 @@ Tex *copy_texture(Tex *tex) } if(texn->coba) texn->coba= MEM_dupallocN(texn->coba); - if(texn->env) texn->env= RE_copy_envmap(texn->env); + if(texn->env) texn->env= BKE_copy_envmap(texn->env); return texn; } @@ -714,3 +719,69 @@ Tex *give_current_texture(Object *ob, int act) return tex; } + + +/* ------------------------------------------------------------------------- */ + +EnvMap *BKE_add_envmap(void) +{ + EnvMap *env; + + env= MEM_callocN(sizeof(EnvMap), "envmap"); + env->type= ENV_CUBE; + env->stype= ENV_STATIC; + env->clipsta= 0.1; + env->clipend= 100.0; + env->cuberes= 100; + + return env; +} + +/* ------------------------------------------------------------------------- */ + +EnvMap *BKE_copy_envmap(EnvMap *env) +{ + EnvMap *envn; + int a; + + envn= MEM_dupallocN(env); + envn->ok= 0; + for(a=0; a<6; a++) envn->cube[a]= 0; + if(envn->ima) id_us_plus((ID *)envn->ima); + + return envn; +} + +/* ------------------------------------------------------------------------- */ + +void BKE_free_envmapdata(EnvMap *env) +{ + Image *ima; + unsigned int a, part; + + for(part=0; part<6; part++) { + ima= env->cube[part]; + if(ima) { + if(ima->ibuf) IMB_freeImBuf(ima->ibuf); + + for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) { + if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); + } + MEM_freeN(ima); + env->cube[part]= 0; + } + } + env->ok= 0; +} + +/* ------------------------------------------------------------------------- */ + +void BKE_free_envmap(EnvMap *env) +{ + + BKE_free_envmapdata(env); + MEM_freeN(env); + +} + +/* ------------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 1f71b01d33a..3ff980110e7 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -178,38 +178,3 @@ void make_local_world(World *wrld) } } } - - -void init_render_world() -{ - int a; - char *cp; - - if(G.scene->world) { - R.wrld= *(G.scene->world); - - cp= (char *)&R.wrld.fastcol; - - cp[0]= 255.0*R.wrld.horr; - cp[1]= 255.0*R.wrld.horg; - cp[2]= 255.0*R.wrld.horb; - cp[3]= 1; - - VECCOPY(R.grvec, R.viewmat[2]); - Normalise(R.grvec); - Mat3CpyMat4(R.imat, R.viewinv); - - for(a=0; a<MAX_MTEX; a++) - if(R.wrld.mtex[a] && R.wrld.mtex[a]->tex) R.wrld.skytype |= WO_SKYTEX; - - while(R.wrld.aosamp*R.wrld.aosamp < R.osa) R.wrld.aosamp++; - } - else { - memset(&R.wrld, 0, sizeof(World)); - R.wrld.exp= 0.0; - R.wrld.range= 1.0; - } - - R.wrld.linfac= 1.0 + pow((2.0*R.wrld.exp + 0.5), -10); - R.wrld.logfac= log( (R.wrld.linfac-1.0)/R.wrld.linfac )/R.wrld.range; -} diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index 0d94215816a..d754a694d5d 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -1,5 +1,6 @@ /** * Functions for writing avi-format files. + * Added interface for generic movie support (ton) * * $Id$ * @@ -36,65 +37,103 @@ #include <string.h> #include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" + #include "BLI_blenlib.h" +#include "BKE_global.h" +#include "BKE_writeavi.h" + #include "AVI_avi.h" -#include "BKE_bad_level_calls.h" -#include "BKE_global.h" -/* RPW 11-21-2002 */ -#include "DNA_scene_types.h" -/* RPW - End */ +/* ********************** general blender movie support ***************************** */ + +#ifdef WITH_QUICKTIME +#include "quicktime_export.h" +#endif + +bMovieHandle *BKE_get_movie_handle(int imtype) +{ + static bMovieHandle mh; + + /* set the default handle, as builtin */ + mh.start_movie= start_avi; + mh.append_movie= append_avi; + mh.end_movie= end_avi; + + /* do the platform specific handles */ +#ifdef __sgi + if (imtype == R_MOVIE) { + + } +#endif +#if defined(_WIN32) && !defined(FREE_WINDOWS) + if (imtype == R_AVICODEC) { + + } +#endif +#ifdef WITH_QUICKTIME + if (imtype == R_QUICKTIME) { + mh.start_movie= start_qt; + mh.append_movie= append_qt; + mh.end_movie= end_qt; + } +#endif + + return &mh; +} + +/* ****************************************************************** */ -#include "BKE_writeavi.h" static AviMovie *avi=NULL; static int sframe; -void makeavistring (char *string) +void makeavistring (RenderData *rd, char *string) { char txt[64]; if (string==0) return; - strcpy(string, G.scene->r.pic); - BLI_convertstringcode(string, G.sce, G.scene->r.cfra); + strcpy(string, rd->pic); + BLI_convertstringcode(string, G.sce, rd->cfra); - RE_make_existing_file(string); + BLI_make_existing_file(string); if (BLI_strcasecmp(string + strlen(string) - 4, ".avi")) { - sprintf(txt, "%04d_%04d.avi", (G.scene->r.sfra) , (G.scene->r.efra) ); + sprintf(txt, "%04d_%04d.avi", (rd->sfra) , (rd->efra) ); strcat(string, txt); } } -void start_avi(void) +void start_avi(RenderData *rd, int rectx, int recty) { int x, y; char name[256]; AviFormat format; int quality, framerate; - makeavistring(name); + makeavistring(rd, name); - sframe = (G.scene->r.sfra); - x = R.rectx; - y = R.recty; + sframe = (rd->sfra); + x = rectx; + y = recty; - quality= R.r.quality; - framerate= R.r.frs_sec; + quality= rd->quality; + framerate= rd->frs_sec; avi = MEM_mallocN (sizeof(AviMovie), "avimovie"); /* RPW 11-21-2002 - if (R.r.imtype != AVI_FORMAT_MJPEG) format = AVI_FORMAT_AVI_RGB; + if (rd->imtype != AVI_FORMAT_MJPEG) format = AVI_FORMAT_AVI_RGB; */ - if (R.r.imtype != R_AVIJPEG ) format = AVI_FORMAT_AVI_RGB; + if (rd->imtype != R_AVIJPEG ) format = AVI_FORMAT_AVI_RGB; else format = AVI_FORMAT_MJPEG; if (AVI_open_compress (name, avi, 1, format) != AVI_ERROR_NONE) { - error("open movie"); + printf("cannot open or start AVI movie file"); MEM_freeN (avi); avi = NULL; return; @@ -107,13 +146,13 @@ void start_avi(void) avi->interlace= 0; avi->odd_fields= 0; -/* avi->interlace= R.r.mode & R_FIELDS; */ -/* avi->odd_fields= (R.r.mode & R_ODDFIELD)?1:0; */ +/* avi->interlace= rd->mode & R_FIELDS; */ +/* avi->odd_fields= (rd->mode & R_ODDFIELD)?1:0; */ printf("Created avi: %s\n", name); } -void append_avi(int frame) +void append_avi(int frame, int *pixels, int rectx, int recty) { unsigned int *rt1, *rt2, *rectot; int x, y; @@ -125,15 +164,15 @@ void append_avi(int frame) } /* note that libavi free's the buffer... stupid interface - zr */ - rectot= MEM_mallocN(R.rectx*R.recty*sizeof(int), "rectot"); + rectot= MEM_mallocN(rectx*recty*sizeof(int), "rectot"); rt1= rectot; - rt2= R.rectot + (R.recty-1)*R.rectx; + rt2= pixels + (recty-1)*rectx; /* flip y and convert to abgr */ - for (y=0; y < R.recty; y++, rt1+= R.rectx, rt2-= R.rectx) { - memcpy (rt1, rt2, R.rectx*sizeof(int)); + for (y=0; y < recty; y++, rt1+= rectx, rt2-= rectx) { + memcpy (rt1, rt2, rectx*sizeof(int)); cp= (char *)rt1; - for(x= R.rectx; x>0; x--) { + for(x= rectx; x>0; x--) { rt= cp[0]; cp[0]= cp[3]; cp[3]= rt; @@ -144,8 +183,8 @@ void append_avi(int frame) } } - AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32, rectot, R.rectx*R.recty*4); - printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe); + AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32, rectot, rectx*recty*4); +// printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe); } void end_avi(void) |