diff options
author | Andre Susano Pinto <andresusanopinto@gmail.com> | 2009-09-25 02:55:57 +0400 |
---|---|---|
committer | Andre Susano Pinto <andresusanopinto@gmail.com> | 2009-09-25 02:55:57 +0400 |
commit | 1305715d2d84f67027b870f263cef3a7f009c056 (patch) | |
tree | 50076f8e30adb6f12735fc486abfa11e138511ec /source/blender/render/intern | |
parent | d3e88cb3e0d4117ab845a7c77254a5ab05ce1657 (diff) |
*Added VlakPrimitive (this rayobject rimitive only stores ObjectRenderInstance and VlakRen pointers)
- it difers from RayFace that localy stored the vertex coordinates.
- basicaly this reduces memory usage
Diffstat (limited to 'source/blender/render/intern')
-rw-r--r-- | source/blender/render/intern/include/rayobject.h | 27 | ||||
-rw-r--r-- | source/blender/render/intern/include/render_types.h | 3 | ||||
-rw-r--r-- | source/blender/render/intern/raytrace/rayobject.cpp (renamed from source/blender/render/intern/source/rayobject.c) | 52 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayshade.c | 88 | ||||
-rw-r--r-- | source/blender/render/intern/source/renderdatabase.c | 5 |
5 files changed, 129 insertions, 46 deletions
diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index dbd68fe8b8b..337f9ca3fdd 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -57,17 +57,18 @@ extern "C" { In order to allow a mixture of RayFace+RayObjects, all RayObjects must be 4byte aligned, allowing us to use the - 2 least significant bits (with the mask 0x02) to define the + 2 least significant bits (with the mask 0x03) to define the type of RayObject. - This leads to 4 possible types of RayObject, but at the moment - only 2 are used: + This leads to 4 possible types of RayObject: - addr&2 - type of object + addr&3 - type of object 0 Self (reserved for each structure) - 1 RayFace + 1 RayFace (tri/quad primitive) 2 RayObject (generic with API callbacks) - 3 RayObject_Vlak + 3 VlakPrimitive + (vlak primitive - to be used when we have a vlak describing the data + eg.: on render code) 0 means it's reserved and has it own meaning inside each ray acceleration structure (this way each structure can use the allign offset to determine if a node represents a @@ -83,26 +84,16 @@ extern "C" { /* used to unalign a given ray object */ #define RE_rayobject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1)) #define RE_rayobject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2)) -#define RE_rayobject_unalignRayVlak(o) ((RayObject*)(((intptr_t)o)|3)) +#define RE_rayobject_unalignVlakPrimitive(o) ((RayObject*)(((intptr_t)o)|3)) /* used to test the type of ray object */ #define RE_rayobject_isAligned(o) ((((intptr_t)o)&3) == 0) #define RE_rayobject_isRayFace(o) ((((intptr_t)o)&3) == 1) #define RE_rayobject_isRayAPI(o) ((((intptr_t)o)&3) == 2) -#define RE_rayobject_isRayVlak(o) ((((intptr_t)o)&3) == 3) +#define RE_rayobject_isVlakPrimitive(o) ((((intptr_t)o)&3) == 3) /* - * This ray object represents faces directly from a given VlakRen structure. - * Thus allowing to save memory, but making code dependant on render structures -typedef struct RayVlak -{ - struct ObjectInstanceRen *ob; - struct VlakRen *face; -} RayVlak; - */ - -/* * This rayobject represents a generic object. With it's own callbacks for raytrace operations. * It's suitable to implement things like LOD. */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 67c69259213..8c106f60e1d 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -172,6 +172,7 @@ struct Render /* octree tables and variables for raytrace */ struct RayObject *raytree; struct RayFace *rayfaces; + struct VlakPrimitive *rayprimitives; float maxdist; /* needed for keeping an incorrect behaviour of SUN and HEMI lights (avoid breaking old scenes) */ /* occlusion tree */ @@ -289,6 +290,7 @@ typedef struct ObjectRen { /* used on makeraytree */ struct RayObject *raytree; struct RayFace *rayfaces; + struct VlakPrimitive *rayprimitives; struct ObjectInstanceRen *rayobi; } ObjectRen; @@ -313,6 +315,7 @@ typedef struct ObjectInstanceRen { /* used on makeraytree */ struct RayObject *raytree; + int transform_primitives; } ObjectInstanceRen; diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/raytrace/rayobject.cpp index df457a37123..dc5128b2d1f 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -30,6 +30,7 @@ #include "BKE_utildefines.h" #include "BLI_arithb.h" +#include "DNA_material_types.h" #include "RE_raytrace.h" #include "render_types.h" @@ -141,7 +142,6 @@ static int intersection2(VlakRen *face, float r0, float r1, float r2, float rx1, return 0; } -#include "DNA_material_types.h" static int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr) { /* for baking selected to active non-traceable materials might still @@ -178,7 +178,7 @@ static int rayface_check_cullface(RayFace *face, Isect *is) /* ray - triangle or quad intersection */ /* this function shall only modify Isect if it detects an hit */ -static int intersect_rayface(RayFace *face, Isect *is) +static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) { float co1[3],co2[3],co3[3],co4[3]; float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2; @@ -301,8 +301,8 @@ static int intersect_rayface(RayFace *face, Isect *is) { if(labda < 0.1f && is->orig.ob == face->ob) { - VlakRen * a = is->orig.face; - VlakRen * b = face->face; + VlakRen * a = (VlakRen*)is->orig.face; + VlakRen * b = (VlakRen*)face->face; /* so there's a shared edge or vertex, let's intersect ray with face itself, if that's true we can safely return 1, otherwise we assume @@ -327,7 +327,7 @@ static int intersect_rayface(RayFace *face, Isect *is) is->hit.ob = face->ob; is->hit.face = face->face; #ifdef RT_USE_LAST_HIT - is->last_hit = (RayObject*) RE_rayobject_unalignRayFace(face); + is->last_hit = hit_obj; #endif return 1; } @@ -361,6 +361,14 @@ RayObject* RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float return RE_rayobject_unalignRayFace(rayface); } +RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr) +{ + face->ob = obi; + face->face = vlr; + return RE_rayobject_unalignVlakPrimitive(face); +} + + int RE_rayobject_raycast(RayObject *r, Isect *isec) { int i; @@ -416,7 +424,25 @@ int RE_rayobject_intersect(RayObject *r, Isect *i) { if(RE_rayobject_isRayFace(r)) { - return intersect_rayface( (RayFace*) RE_rayobject_align(r), i); + return intersect_rayface(r, (RayFace*) RE_rayobject_align(r), i); + } + else if(RE_rayobject_isVlakPrimitive(r)) + { + //TODO optimize (useless copy to RayFace to avoid duplicate code) + VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r); + RayFace nface; + RE_rayface_from_vlak(&nface, face->ob, face->face); + + if(face->ob->transform_primitives) + { + Mat4MulVecfl(face->ob->mat, nface.v1); + Mat4MulVecfl(face->ob->mat, nface.v2); + Mat4MulVecfl(face->ob->mat, nface.v3); + if(RE_rayface_isQuad(&nface)) + Mat4MulVecfl(face->ob->mat, nface.v4); + } + + return intersect_rayface(r, &nface, i); } else if(RE_rayobject_isRayAPI(r)) { @@ -455,6 +481,16 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) DO_MINMAX( face->v3, min, max ); if(RE_rayface_isQuad(face)) DO_MINMAX( face->v4, min, max ); } + else if(RE_rayobject_isVlakPrimitive(r)) + { + VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r); + VlakRen *vlr = face->face; + + DO_MINMAX( vlr->v1->co, min, max ); + DO_MINMAX( vlr->v2->co, min, max ); + DO_MINMAX( vlr->v3->co, min, max ); + if(vlr->v4) DO_MINMAX( vlr->v4->co, min, max ); + } else if(RE_rayobject_isRayAPI(r)) { r = RE_rayobject_align( r ); @@ -465,7 +501,7 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) float RE_rayobject_cost(RayObject *r) { - if(RE_rayobject_isRayFace(r)) + if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) { return 1.0; } @@ -479,7 +515,7 @@ float RE_rayobject_cost(RayObject *r) void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max) { - if(RE_rayobject_isRayFace(r)) + if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) { return; } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 8cb11d11762..18278d90e72 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -61,6 +61,8 @@ #include "rayobject.h" #include "raycounter.h" + +#define USE_VLAK_PRIMITIVES 1 #define RAY_TRA 1 #define RAY_TRAFLIP 2 @@ -133,6 +135,11 @@ void freeraytree(Render *re) MEM_freeN(re->rayfaces); re->rayfaces = NULL; } + if(re->rayprimitives) + { + MEM_freeN(re->rayprimitives); + re->rayprimitives = NULL; + } for(obi=re->instancetable.first; obi; obi=obi->next) { @@ -203,6 +210,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) { RayObject *raytree; RayFace *face; + VlakPrimitive *vlakprimitive; int v; //Count faces @@ -217,7 +225,11 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) //Create Ray cast accelaration structure raytree = obr->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces ); - face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); + if(USE_VLAK_PRIMITIVES) + vlakprimitive = obr->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen primitives"); + else + face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); + obr->rayobi = obi; for(v=0;v<obr->totvlak;v++) @@ -225,17 +237,26 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); if(is_raytraceable_vlr(re, vlr)) { - RE_rayface_from_vlak( face, obi, vlr ); - RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); - face++; + if(USE_VLAK_PRIMITIVES) + { + RE_rayobject_add( raytree, RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr ) ); + vlakprimitive++; + } + else + { + RE_rayface_from_vlak( face, obi, vlr ); + RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); + face++; + } } } RE_rayobject_done( raytree ); } - if(obi->flag & R_TRANSFORMED) + if((obi->flag & R_TRANSFORMED) && obi->raytree == NULL) { + obi->transform_primitives = 0; obi->raytree = RE_rayobject_instance_create( obr->raytree, obi->mat, obi, obi->obr->rayobi ); } @@ -271,7 +292,8 @@ static void makeraytree_single(Render *re) ObjectInstanceRen *obi; RayObject *raytree; RayFace *face; - int faces = 0, obs = 0; + VlakPrimitive *vlakprimitive; + int faces = 0, obs = 0, special = 0; for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) @@ -282,7 +304,7 @@ static void makeraytree_single(Render *re) if(has_special_rayobject(re, obi)) { - faces++; + special++; } else { @@ -296,9 +318,16 @@ static void makeraytree_single(Render *re) } //Create raytree - raytree = re->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces ); + raytree = re->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces+special ); - face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); + if(USE_VLAK_PRIMITIVES) + { + vlakprimitive = re->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "Raytrace vlak-primitives"); + } + else + { + face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); + } for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) @@ -312,28 +341,46 @@ static void makeraytree_single(Render *re) { int v; ObjectRen *obr = obi->obr; + + if(obi->flag & R_TRANSFORMED) + { + obi->transform_primitives = 1; + } for(v=0;v<obr->totvlak;v++) { VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); if(is_raytraceable_vlr(re, vlr)) { - RE_rayface_from_vlak(face, obi, vlr); - if((obi->flag & R_TRANSFORMED)) + if(USE_VLAK_PRIMITIVES) { - Mat4MulVecfl(obi->mat, face->v1); - Mat4MulVecfl(obi->mat, face->v2); - Mat4MulVecfl(obi->mat, face->v3); - if(RE_rayface_isQuad(face)) - Mat4MulVecfl(obi->mat, face->v4); + RayObject *obj = RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr ); + RE_rayobject_add( raytree, obj ); + vlakprimitive++; + } + else + { + RE_rayface_from_vlak(face, obi, vlr); + if((obi->flag & R_TRANSFORMED)) + { + Mat4MulVecfl(obi->mat, face->v1); + Mat4MulVecfl(obi->mat, face->v2); + Mat4MulVecfl(obi->mat, face->v3); + if(RE_rayface_isQuad(face)) + Mat4MulVecfl(obi->mat, face->v4); + } + + RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); + face++; } - - RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); - face++; } } } } + + re->i.infostr= "Raytree.. building"; + re->stats_draw(re->sdh, &re->i); + RE_rayobject_done( raytree ); } @@ -342,7 +389,7 @@ void makeraytree(Render *re) float min[3], max[3], sub[3]; int i; - re->i.infostr= "Make raytree"; + re->i.infostr= "Raytree.. preparing"; re->stats_draw(re->sdh, &re->i); BENCH(makeraytree_single(re), tree_build); @@ -359,6 +406,7 @@ void makeraytree(Render *re) re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] ); re->i.infostr= "Raytree finished"; + re->stats_draw(re->sdh, &re->i); } void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 5f21a0e2e1a..784e42685b7 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -879,6 +879,11 @@ void free_renderdata_tables(Render *re) MEM_freeN(obr->rayfaces); obr->rayfaces = NULL; } + if(obr->rayprimitives) + { + MEM_freeN(obr->rayprimitives); + obr->rayprimitives = NULL; + } if(obr->raytree) { RE_rayobject_free(obr->raytree); |