diff --git a/intern/bmfont/intern/BMF_BitmapFont.cpp b/intern/bmfont/intern/BMF_BitmapFont.cpp index 2ea14b4b203..8e670c099a3 100644 --- a/intern/bmfont/intern/BMF_BitmapFont.cpp +++ b/intern/bmfont/intern/BMF_BitmapFont.cpp @@ -291,20 +291,20 @@ void BMF_BitmapFont::DrawStringBuf(char *str, int posx, int posy, float *col, un if (fbuf) { float *pixel, *max; unsigned char c; - int x, y; + int xi, yi; max = fbuf + (4 * (w * h)); while ((c = (unsigned char) *str++)) { BMF_CharData & cd = m_fontData->chars[c]; if (cd.data_offset != -1) { - for (y = 0; y < cd.height; y++) { - unsigned char* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y]; - for (x = cd.xorig; x < cd.width; x++) { - pixel = fbuf + 4 * (((posy + y - cd.yorig) * w) + (posx + x)); + for (yi = 0; yi < cd.height; yi++) { + unsigned char* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*yi]; + for (xi = cd.xorig; xi < cd.width; xi++) { + pixel = fbuf + 4 * (((posy + yi - cd.yorig) * w) + (posx + xi)); if ((pixel < max) && (pixel > fbuf)) { - int byteIdx = x/8; - int bitIdx = 7 - (x%8); + int byteIdx = xi/8; + int bitIdx = 7 - (xi%8); if (chrRow[byteIdx]&(1< #include -#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) +#if (defined (__sun__) || defined (__sun)) || (!defined(linux) && (defined (__sparc) || defined (__sparc__))) #include #endif - // just use default rounding for platforms where its not available #ifndef round #define round(x) (x) diff --git a/intern/elbeem/intern/solver_adap.cpp b/intern/elbeem/intern/solver_adap.cpp index b56b1c14f2c..5616d805232 100644 --- a/intern/elbeem/intern/solver_adap.cpp +++ b/intern/elbeem/intern/solver_adap.cpp @@ -11,11 +11,10 @@ #include "solver_relax.h" #include "particletracer.h" -#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) +#if (defined (__sun__) || defined (__sun)) || (!defined(linux) && (defined (__sparc) || defined (__sparc__))) #include #endif - /*****************************************************************************/ //! coarse step functions /*****************************************************************************/ diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp index 3d629d673f1..7b91724a640 100644 --- a/intern/elbeem/intern/solver_main.cpp +++ b/intern/elbeem/intern/solver_main.cpp @@ -13,7 +13,7 @@ #include "loop_tools.h" #include -#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) +#if (defined (__sun__) || defined (__sun)) || (!defined(linux) && (defined (__sparc) || defined (__sparc__))) #include #endif diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h index 7a838ff7614..8b9454f1a9d 100644 --- a/source/blender/blenkernel/BKE_bad_level_calls.h +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -91,8 +91,9 @@ extern struct ListBase editNurb; void mainqenter (unsigned short event, short val); void waitcursor(int); void allqueue(unsigned short event, short val); -#define REDRAWVIEW3D 0x4010 -#define REDRAWBUTSEDIT 0x4019 +#define REDRAWVIEW3D 0x4010 +#define REDRAWBUTSOBJECT 0x4018 +#define REDRAWBUTSEDIT 0x4019 struct Material; extern struct Material defmaterial; diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 1a0b83e45c5..8927584de1b 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -294,6 +294,7 @@ struct Object *modifiers_isDeformedByArmature(struct Object *ob); struct Object *modifiers_isDeformedByLattice(struct Object *ob); int modifiers_usesArmature(struct Object *ob, struct bArmature *arm); int modifiers_isDeformed(struct Object *ob); +void modifier_freeTemporaryData(struct ModifierData *md); int modifiers_indexInObject(struct Object *ob, struct ModifierData *md); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index c45989a6b5b..1c69fe613c7 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -169,6 +169,8 @@ typedef struct ParticleThreadContext { int from, cfrom, distr; + struct ParticleData *tpars; + /* path caching */ int editupdate, between, steps; int totchild, totparent; @@ -203,15 +205,18 @@ void psys_disable_all(struct Object *ob); void psys_enable_all(struct Object *ob); int psys_ob_has_hair(struct Object *ob); int psys_in_edit_mode(struct ParticleSystem *psys); +int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys); void psys_free_settings(struct ParticleSettings *part); void free_child_path_cache(struct ParticleSystem *psys); void psys_free_path_cache(struct ParticleSystem *psys); -void psys_free_render_memory(struct Object *ob, struct ParticleSystem *psys); void free_hair(struct ParticleSystem *psys); void free_keyed_keys(struct ParticleSystem *psys); void psys_free(struct Object * ob, struct ParticleSystem * psys); +void psys_particles_to_render_backup(struct Object *ob, struct ParticleSystem *psys); +void psys_render_backup_to_particles(struct Object *ob, struct ParticleSystem *psys); + void clear_particles_from_cache(struct Object *ob, struct ParticleSystem *psys, int cfra); //void psys_remove_from_particle_list(struct Object *ob, short nbr, struct ParticleSystem *psys); @@ -280,6 +285,7 @@ void psys_particle_on_dm(struct Object *ob, struct DerivedMesh *dm, int from, in void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd); void reset_particle(struct ParticleData *pa, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct Object *ob, float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot); +void psys_calc_dmfaces(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys); int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node); /* ParticleEffectorCache->type */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 4cc134476e4..dd56fe2df61 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1877,7 +1877,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], int needMapping, CustomDataMask dataMask) { Mesh *me = ob->data; - ModifierData *md = modifiers_getVirtualModifierList(ob); + ModifierData *firstmd, *md; LinkNode *datamasks, *curr; CustomDataMask mask; float (*deformedVerts)[3] = NULL; @@ -1886,6 +1886,8 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], int fluidsimMeshUsed = 0; int required_mode; + md = firstmd = modifiers_getVirtualModifierList(ob); + modifiers_clearErrors(ob); /* we always want to keep original indices */ @@ -2097,6 +2099,9 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], } } + for(md=firstmd; md; md=md->next) + modifier_freeTemporaryData(md); + /* Yay, we are done. If we have a DerivedMesh and deformed vertices * need to apply these back onto the DerivedMesh. If we have no * DerivedMesh then we need to build one. diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 4aebd099885..1eb7e232382 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -292,14 +292,6 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i dob->index= index; ob->lay= lay; - /* allowing duplicators for particle systems... a bit silly still */ - { - PartEff *paf= give_parteff(ob); - if(paf) { - Mat4Invert(ob->imat, ob->obmat); - Mat4CpyMat4(paf->imat, ob->imat); - } - } return dob; } @@ -809,7 +801,7 @@ ListBase *object_duplilist(Scene *sce, Object *ob) group_duplilist(duplilist, ob, 0); /* now recursive */ - /* make copy already, because in group dupli's deform displists can be makde, requiring parent matrices */ + /* make copy already, because in group dupli's deform displists can be made, requiring parent matrices */ for(dob= duplilist->first; dob; dob= dob->next) Mat4CpyMat4(dob->ob->obmat, dob->mat); } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index c50374388a9..de4f4555823 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1480,7 +1480,7 @@ void makeBevelList(Object *ob) while(nu) { if(nu->pntsu<=1) { - bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); + bl= MEM_callocN(sizeof(BevList)+1*sizeof(BevPoint), "makeBevelList"); BLI_addtail(&(cu->bev), bl); bl->nr= 0; } else { @@ -1490,8 +1490,7 @@ void makeBevelList(Object *ob) resolu= nu->resolu; if((nu->type & 7)==CU_POLY) { - - len= nu->pntsu; + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); BLI_addtail(&(cu->bev), bl); @@ -1544,7 +1543,7 @@ void makeBevelList(Object *ob) bevp->z= prevbezt->vec[1][2]; bevp->alfa= prevbezt->alfa; bevp->f1= SELECT; - bevp->f2= SELECT; + bevp->f2= 0; bevp++; bl->nr++; bl->flag= 1; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 1076641b4c5..a963b877912 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1900,7 +1900,7 @@ static void dag_object_time_update_flags(Object *ob) ParticleSystem *psys= ob->particlesystem.first; for(; psys; psys=psys->next) { - if(psys->flag & PSYS_ENABLED) { + if(psys_check_enabled(ob, psys)) { ob->recalc |= OB_RECALC_DATA; break; } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 50160771054..e7ce752424d 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5358,7 +5358,7 @@ static void particleSystemModifier_deformVerts( else return; - if((psys->flag&PSYS_ENABLED)==0) + if(!psys_check_enabled(ob, psys)) return; if(dm==0){ @@ -7513,3 +7513,14 @@ int modifiers_usesPointCache(Object *ob) return 0; } +void modifier_freeTemporaryData(ModifierData *md) +{ + if(md->type == eModifierType_Armature) { + ArmatureModifierData *amd= (ArmatureModifierData*)md; + + if(amd->prevCos) + MEM_freeN(amd->prevCos); + } +} + + diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 15c4943f6fb..d48be54fe10 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2201,7 +2201,7 @@ void object_handle_update(Object *ob) psys= ob->particlesystem.first; while(psys) { - if(psys->flag & PSYS_ENABLED) { + if(psys_check_enabled(ob, psys)) { particle_system_update(ob, psys); psys= psys->next; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 154ca9a5716..85ac809bf70 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -77,6 +77,7 @@ #include "BKE_bad_level_calls.h" #include "BKE_modifier.h" #include "BKE_mesh.h" +#include "BKE_cdderivedmesh.h" #include "blendef.h" #include "RE_render_ext.h" @@ -248,6 +249,23 @@ int psys_in_edit_mode(ParticleSystem *psys) { return ((G.f & G_PARTICLEEDIT) && psys==psys_get_current(OBACT) && psys->edit); } +int psys_check_enabled(Object *ob, ParticleSystem *psys) +{ + ParticleSystemModifierData *psmd; + + if(!(psys->flag & PSYS_ENABLED)) + return 0; + + psmd= psys_get_modifier(ob, psys); + if(G.rendering) { + if(!psys->renderdata || !(psmd->modifier.mode & eModifierMode_Render)) + return 0; + } + else if(!(psmd->modifier.mode & eModifierMode_Realtime)) + return 0; + + return 1; +} /************************************************/ /* Freeing stuff */ @@ -301,27 +319,6 @@ void psys_free_path_cache(ParticleSystem *psys) } free_child_path_cache(psys); } -void psys_free_render_memory(Object *ob, ParticleSystem *psys) -{ - ParticleSystemModifierData *psmd; - - /* this is a bad function, but saves a lot of memory rendering. - * particles should really be generated on the fly with render - * settings! */ - psys_free_path_cache(psys); - - if(psys->child){ - MEM_freeN(psys->child); - psys->child=0; - psys->totchild=0; - } - - psmd= psys_get_modifier(ob, psys); - psmd->flag &= ~eParticleSystemFlag_psys_updated; - - psys->recalc |= PSYS_ALLOC|PSYS_DISTR; - //DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); -} /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) { @@ -366,6 +363,92 @@ void psys_free(Object *ob, ParticleSystem * psys) } } +/* these two functions move away particle data and bring it back after + * rendering, to make different render settings possible without + * removing the previous data. this should be solved properly once */ + +typedef struct ParticleRenderDataup { + ChildParticle *child; + ParticleCacheKey **pathcache; + ParticleCacheKey **childcache; + int totchild, totcached, totchildcache; + DerivedMesh *dm; + int totdmvert, totdmedge, totdmface; +} ParticleRenderDataup; + +void psys_particles_to_render_backup(Object *ob, ParticleSystem *psys) +{ + ParticleRenderDataup *data; + ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); + + if(!G.rendering) + return; + + data= MEM_callocN(sizeof(ParticleRenderDataup), "ParticleRenderDataup"); + + data->child= psys->child; + data->totchild= psys->totchild; + data->pathcache= psys->pathcache; + data->totcached= psys->totcached; + data->childcache= psys->childcache; + data->totchildcache= psys->totchildcache; + + if(psmd->dm) + data->dm= CDDM_copy(psmd->dm); + data->totdmvert= psmd->totdmvert; + data->totdmedge= psmd->totdmedge; + data->totdmface= psmd->totdmface; + + psys->child= NULL; + psys->pathcache= NULL; + psys->childcache= NULL; + psys->totchild= psys->totcached= psys->totchildcache= 0; + + psys->renderdata= data; +} + +void psys_render_backup_to_particles(Object *ob, ParticleSystem *psys) +{ + ParticleRenderDataup *data; + ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); + + data= psys->renderdata; + if(!data) + return; + + if(psmd->dm) { + psmd->dm->needsFree= 1; + psmd->dm->release(psmd->dm); + } + + psys_free_path_cache(psys); + + if(psys->child){ + MEM_freeN(psys->child); + psys->child= 0; + psys->totchild= 0; + } + + psys->child= data->child; + psys->totchild= data->totchild; + psys->pathcache= data->pathcache; + psys->totcached= data->totcached; + psys->childcache= data->childcache; + psys->totchildcache= data->totchildcache; + + psmd->dm= data->dm; + psmd->totdmvert= data->totdmvert; + psmd->totdmedge= data->totdmedge; + psmd->totdmface= data->totdmface; + psmd->flag &= ~eParticleSystemFlag_psys_updated; + + if(psys->part->from==PART_FROM_FACE && psmd->dm) + psys_calc_dmfaces(ob, psmd->dm, psys); + + MEM_freeN(data); + psys->renderdata= NULL; +} + /************************************************/ /* Interpolated Particles */ /************************************************/ @@ -691,12 +774,13 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, float * #define PARTICLE_ERROR(_nor, _vec) _vec[0]=_vec[1]=_vec[2]=0.0; if(_nor){ _nor[0]=_nor[1]=0.0; _nor[2]=1.0; } void psys_particle_on_dm(Object *ob, DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor) { - float (*orcodata)[3] = dm->getVertDataArray(dm, CD_ORCO); + float (*orcodata)[3]; if(index < 0){ /* 'no dm' error has happened! */ PARTICLE_ERROR(nor, vec); return; } + orcodata= dm->getVertDataArray(dm, CD_ORCO); if (dm->deformedOnly || index_dmcache == DMCACHE_ISCHILD) { /* this works for meshes with deform verts only - constructive modifiers wont work properly*/ @@ -1406,7 +1490,7 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) /*---start figuring out what is actually wanted---*/ if(psys_in_edit_mode(psys)) - if(G.rendering==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0) + if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0) totchild=0; if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ @@ -1415,7 +1499,7 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) between=1; } - if(G.rendering) + if(psys->renderdata) steps=(int)pow(2.0,(double)part->ren_step); else{ totchild=(int)((float)totchild*(float)part->disp/100.0f); @@ -1870,7 +1954,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) return; - if(G.rendering) + if(psys->renderdata) steps = (int)pow(2.0, (double)psys->part->ren_step); else if(psys_in_edit_mode(psys)){ edit=psys->edit; @@ -2290,7 +2374,7 @@ void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData psys_particle_on_dm(ob, dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco, 0); /* see psys_face_mat for why this function is called */ - transform_mesh_orco_verts(ob->data, orco, 1, 1); + transform_mesh_orco_verts(ob->data, &orco, 1, 1); VECCOPY(hairmat[3],orco); } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 414b64cae6a..af1db36b648 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -92,7 +92,7 @@ static int get_current_display_percentage(ParticleSystem *psys) { ParticleSettings *part=psys->part; - if(G.rendering || (part->child_nbr && part->childtype)) + if(psys->renderdata || (part->child_nbr && part->childtype)) return 100; if(part->phystype==PART_PHYS_KEYED){ @@ -136,7 +136,7 @@ static void alloc_particles(ParticleSystem *psys, int new_totpart) } psys->particles=newpars; - child_nbr= (G.rendering)? psys->part->ren_child_nbr: psys->part->child_nbr; + child_nbr= (psys->renderdata)? psys->part->ren_child_nbr: psys->part->child_nbr; if(child_nbr && psys->part->childtype){ if(psys->child) MEM_freeN(psys->child); @@ -155,7 +155,7 @@ static void alloc_particles(ParticleSystem *psys, int new_totpart) } /* only run this if from == PART_FROM_FACE */ -static void psys_calc_dmfaces(Object *ob, DerivedMesh *dm, ParticleSystem *psys) +void psys_calc_dmfaces(Object *ob, DerivedMesh *dm, ParticleSystem *psys) { /* use for building derived mesh face-origin info, node - the allocated links - total derived mesh face count @@ -472,7 +472,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C ParticleThreadContext *ctx= thread->ctx; Object *ob= ctx->ob; DerivedMesh *dm= ctx->dm; - ParticleData *tpars=0, *tpa; + ParticleData *tpa; ParticleSettings *part= ctx->psys->part; float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3], ornor1[3]; float cur_d, min_d; @@ -494,6 +494,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C int w, maxw; psys_particle_on_dm(ctx->ob,ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0); + transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1); maxw = BLI_kdtree_find_n_nearest(ctx->tree,3,orco1,NULL,ptn); for(w=0; wverts[1]=0; //pa->verts[2]=0; - tpa=tpars+ctx->index[p]; + tpa=ctx->tpars+ctx->index[p]; pa->num=ctx->index[p]; pa->fuv[0]=tpa->fuv[0]; pa->fuv[1]=tpa->fuv[1]; @@ -633,6 +634,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams); psys_particle_on_dm(ob,dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0,orco1,ornor1); + transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1); maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); maxd=ptn[maxw-1].dist; @@ -778,7 +780,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm Object *ob= ctx->ob; ParticleSystem *psys= ctx->psys; Object *tob; - ParticleData *pa=0, *tpars; + ParticleData *pa=0, *tpars= 0; ParticleSettings *part; ParticleSystem *tpsys; ParticleSeam *seams= 0; @@ -820,6 +822,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm for(p=0,pa=psys->particles; pfrom,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,ornor); + transform_mesh_orco_verts((Mesh*)ob->data, &orco, 1, 1); BLI_kdtree_insert(tree, p, orco, ornor); } @@ -874,7 +877,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm } else{ /* no need to figure out distribution */ - int child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr; + int child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr; for(i=0; itotpart; p++,cpa++){ @@ -923,8 +926,10 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm tree=BLI_kdtree_new(totvert); for(p=0; pdata, &co, 1, 1); + } else VECCOPY(co,mv[p].co) BLI_kdtree_insert(tree,p,co,NULL); @@ -990,7 +995,8 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm /* 2.1 */ if((part->flag&PART_EDISTR || children) && ELEM(from,PART_FROM_PARTICLE,PART_FROM_VERT)==0){ - float totarea=0.0, *co1, *co2, *co3, *co4; + MVert *v1, *v2, *v3, *v4; + float totarea=0.0, co1[3], co2[3], co3[3], co4[3]; float (*orcodata)[3]; orcodata= dm->getVertDataArray(dm, CD_ORCO); @@ -999,21 +1005,31 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm MFace *mf=dm->getFaceData(dm,i,CD_MFACE); if(orcodata) { - co1= orcodata[mf->v1]; - co2= orcodata[mf->v2]; - co3= orcodata[mf->v3]; + VECCOPY(co1, orcodata[mf->v1]); + VECCOPY(co2, orcodata[mf->v2]); + VECCOPY(co3, orcodata[mf->v3]); + transform_mesh_orco_verts((Mesh*)ob->data, &co1, 1, 1); + transform_mesh_orco_verts((Mesh*)ob->data, &co2, 1, 1); + transform_mesh_orco_verts((Mesh*)ob->data, &co3, 1, 1); } else { - co1= ((MVert*)dm->getVertData(dm,mf->v1,CD_MVERT))->co; - co2= ((MVert*)dm->getVertData(dm,mf->v2,CD_MVERT))->co; - co3= ((MVert*)dm->getVertData(dm,mf->v3,CD_MVERT))->co; + v1= (MVert*)dm->getVertData(dm,mf->v1,CD_MVERT); + v2= (MVert*)dm->getVertData(dm,mf->v2,CD_MVERT); + v3= (MVert*)dm->getVertData(dm,mf->v3,CD_MVERT); + VECCOPY(co1, v1->co); + VECCOPY(co2, v2->co); + VECCOPY(co3, v3->co); } if (mf->v4){ - if(orcodata) - co4= orcodata[mf->v4]; - else - co4= ((MVert*)dm->getVertData(dm,mf->v4,CD_MVERT))->co; + if(orcodata) { + VECCOPY(co4, orcodata[mf->v4]); + transform_mesh_orco_verts((Mesh*)ob->data, &co4, 1, 1); + } + else { + v4= (MVert*)dm->getVertData(dm,mf->v4,CD_MVERT); + VECCOPY(co4, v4->co); + } cur= AreaQ3Dfl(co1, co2, co3, co4); } else @@ -1096,9 +1112,9 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm } } else { - float step, pos; + double step, pos; - step= (totpart <= 1)? 0.5f: 1.0f/(totpart-1); + step= (totpart <= 1)? 0.5: 1.0/(totpart-1); pos= 0.0f; i= 0; @@ -1157,6 +1173,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm ctx->cfrom= cfrom; ctx->distr= distr; ctx->dm= dm; + ctx->tpars= tpars; seed= 31415926 + ctx->psys->seed; @@ -1434,9 +1451,6 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS initialize_particle(pa,p,ob,psys,psmd); /* store the derived mesh face index for each particle */ - //if(psys->part->from==PART_FROM_FACE) - // psys_calc_dmfaces(ob, psmd->dm, psys); - icu=find_ipocurve(psys->part->ipo,PART_EMIT_FREQ); if(icu){ float time=psys->part->sta, end=psys->part->end; @@ -1715,9 +1729,6 @@ static void reset_all_particles(Object *ob, ParticleSystem *psys, ParticleSystem float *vg_tan=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); float *vg_rot=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); - //if (psys->part->from == PART_FROM_FACE) - // psys_calc_dmfaces(ob, psmd->dm, psys); - for(p=from, pa=psys->particles+from; ppart; ParticleEditSettings *pset=&G.scene->toolsettings->particle; int distr=0,alloc=0; - int child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr; + int child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr; if((psys->part->childtype && psys->totchild != psys->totpart*child_nbr) || psys->recalc&PSYS_ALLOC) alloc=1; @@ -4205,11 +4216,10 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst { ParticleSettings *part = psys->part; - if(psys->recalc & PSYS_DISTR) { + if(psys->recalc & PSYS_DISTR) /* need this for changing subsurf levels */ psys_calc_dmfaces(ob, psmd->dm, psys); - } - + if(psys->effectors.first) psys_end_effectors(psys); @@ -4377,6 +4387,10 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier psys->recalc &= ~PSYS_TYPE; alloc = 1; + + /* this is a bad level call, but currently type change + * can happen after redraw, so force redraw from here */ + allqueue(REDRAWBUTSOBJECT, 0); } else oldtotpart = psys->totpart; @@ -4386,7 +4400,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier else totpart = psys->part->totpart; - child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr; + child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr; if(oldtotpart != totpart || psys->recalc&PSYS_ALLOC || (psys->part->childtype && psys->totchild != psys->totpart*child_nbr)) alloc = 1; @@ -4428,7 +4442,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier /* set particles to be not calculated */ disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; - if(disp<1.0f) for(p=0, pa=psys->particles; pparticles; pr_rot[0] > disp) pa->flag |= PARS_NO_DISP; else @@ -4436,12 +4450,9 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier } /* ok now we're all set so let's go */ - if(psys->totpart) { - //if(psys->part->from==PART_FROM_FACE) { - // psys_calc_dmfaces(ob, psmd->dm, psys); - //} + if(psys->totpart) dynamics_step(ob,psys,psmd,cfra,vg_vel,vg_tan,vg_rot,vg_size); - } + psys->recalc = 0; psys->cfra=cfra; @@ -4513,21 +4524,24 @@ void particle_system_update(Object *ob, ParticleSystem *psys){ ParticleSystemModifierData *psmd=0; float cfra; - - if((psys->flag & PSYS_ENABLED)==0) return; - psmd=psys_get_modifier(ob,psys); + if(!psys_check_enabled(ob, psys)) + return; cfra=bsystem_time(ob,(float)CFRA,0.0); + psmd= psys_get_modifier(ob, psys); /* system was already updated from modifier stack */ - if(psmd->flag&eParticleSystemFlag_psys_updated){ + if(psmd->flag&eParticleSystemFlag_psys_updated) { psmd->flag &= ~eParticleSystemFlag_psys_updated; /* make sure it really was updated to cfra */ if(psys->cfra==cfra) return; } + if(!psmd->dm) + return; + /* baked path softbody */ if(psys->part->type==PART_HAIR && psys->soft) psys_to_softbody(ob, psys, 0); @@ -4561,6 +4575,6 @@ void particle_system_update(Object *ob, ParticleSystem *psys){ system_step(ob,psys,psmd,cfra); - Mat4CpyMat4(psys->imat, ob->imat); /* used for duplicators */ + Mat4Invert(psys->imat, ob->obmat); /* used for duplicators */ } diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 57248fb1d68..bcb51fa1393 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -368,7 +368,7 @@ void BLI_setInterruptCallBack(int (*f)(void)); char *BLI_strcasestr(const char *s, const char *find); int BLI_strcasecmp(const char *s1, const char *s2); int BLI_strncasecmp(const char *s1, const char *s2, int n); -void BLI_timestr(double time, char *str); +void BLI_timestr(double _time, char *str); /* time var is global */ /** * Trick to address 32 GB with an int (only for malloced pointers) diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index dc2e53483db..7c94cc80847 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1621,13 +1621,13 @@ void BLI_string_to_utf8(char *original, char *utf_8, char *code) } #endif // WITH_ICONV -void BLI_timestr(double time, char *str) +void BLI_timestr(double _time, char *str) { /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */ - int hr= ((int) time) / (60*60); - int min= ( ((int) time) / 60 ) % 60; - int sec= ((int) (time)) % 60; - int hun= ((int) (time * 100.0)) % 100; + int hr= ( (int) _time) / (60*60); + int min= (((int) _time) / 60 ) % 60; + int sec= ( (int) (_time)) % 60; + int hun= ( (int) (_time * 100.0)) % 100; if (hr) { sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 096ead210d3..9a6e69fe1b0 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7109,6 +7109,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) oldnewmap_insert(fd->libmap, psys->part, psys->part, 0); part->id.us--; + part->id.flag |= (ob->id.flag & LIB_NEEDLINK); psys->totpart=0; psys->flag=PSYS_ENABLED|PSYS_CURRENT; diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 31a5cc2ec4c..8cf63a005cb 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -84,8 +84,11 @@ void delete_armature(void); void deselectall_armature(int toggle, int doundo); void deselectall_posearmature (struct Object *ob, int test, int doundo); int draw_armature(struct Base *base, int dt); + void extrude_armature(int forked); void subdivide_armature(int numcuts); +void fill_bones_armature(void); +void merge_armature(void); void free_editArmature(void); diff --git a/source/blender/include/BIF_gl.h b/source/blender/include/BIF_gl.h index 611cefca51c..215e88dc002 100644 --- a/source/blender/include/BIF_gl.h +++ b/source/blender/include/BIF_gl.h @@ -57,11 +57,7 @@ #include #else #include -#if defined(__sun__) && !defined(__sparc__) -#include -#else #include -#endif #endif /* * these should be phased out. cpack should be replaced in diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 52eb3edf19f..b2a3913465f 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -230,7 +230,7 @@ typedef struct TransInfo { // for manipulator exceptions, like scaling using center point, drawing help lines #define T_USES_MANIPULATOR (1 << 7) -/* restrictions flags */ + /* restrictions flags */ #define T_ALL_RESTRICTIONS ((1 << 8)|(1 << 9)|(1 << 10)) #define T_NO_CONSTRAINT (1 << 8) #define T_NULL_ONE (1 << 9) @@ -239,14 +239,17 @@ typedef struct TransInfo { #define T_PROP_EDIT (1 << 11) #define T_PROP_CONNECTED (1 << 12) -/* if MMB is pressed or not */ + /* if MMB is pressed or not */ #define T_MMB_PRESSED (1 << 13) #define T_V3D_ALIGN (1 << 14) -#define T_2D_EDIT (1 << 15) /* for 2d views like uv or ipo */ + /* for 2d views like uv or ipo */ +#define T_2D_EDIT (1 << 15) #define T_CLIP_UV (1 << 16) #define T_FREE_CUSTOMDATA (1 << 17) + /* auto-ik is on */ +#define T_AUTOIK (1 << 18) /* ******************************************************************************** */ @@ -375,6 +378,8 @@ void sort_trans_data_dist(TransInfo *t); void add_tdi_poin(float *poin, float *old, float delta); void special_aftertrans_update(TransInfo *t); +void transform_autoik_update(TransInfo *t, short mode); + /* auto-keying stuff used by special_aftertrans_update */ void autokeyframe_ob_cb_func(struct Object *ob, int tmode); void autokeyframe_pose_cb_func(struct Object *ob, int tmode, short targetless_ik); @@ -458,3 +463,4 @@ char handleNumInput(NumInput *n, unsigned short event); #endif + diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 1b289650e2c..7f9fa49e7a9 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -126,7 +126,8 @@ typedef struct bKinematicConstraint { Object *tar; short iterations; /* Maximum number of iterations to try */ short flag; /* Like CONSTRAINT_IK_TIP */ - int rootbone; /* index to rootbone, if zero go all the way to mother bone */ + short rootbone; /* index to rootbone, if zero go all the way to mother bone */ + short max_rootbone; /* for auto-ik, maximum length of chain */ char subtarget[32]; /* String to specify sub-object target */ Object *poletar; /* Pole vector target */ diff --git a/source/blender/makesdna/DNA_listBase.h b/source/blender/makesdna/DNA_listBase.h index 10a1b59fb01..e81cb886d6f 100644 --- a/source/blender/makesdna/DNA_listBase.h +++ b/source/blender/makesdna/DNA_listBase.h @@ -43,11 +43,20 @@ extern "C" { #endif +/* generic - all structs which are used in linked-lists used this */ typedef struct Link { struct Link *next,*prev; } Link; + +/* use this when it is not worth defining a custom one... */ +typedef struct LinkData +{ + struct LinkData *next, *prev; + void *data; +} LinkData; + /* never change the size of this! genfile.c detects pointerlen with it */ typedef struct ListBase { diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 1080388bfab..16ecc4b88f0 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -279,6 +279,7 @@ extern Object workob; #define OB_DUPLIFACES 512 #define OB_DUPLIFACES_SCALE 1024 #define OB_DUPLIPARTS 2048 +#define OB_RENDER_DUPLI 4096 /* (short) ipoflag */ #define OB_DRAWKEY 1 @@ -342,6 +343,8 @@ extern Object workob; #define OB_CIRCLE 3 #define OB_SINGLE_ARROW 4 #define OB_CUBE 5 +#define OB_EMPTY_SPHERE 6 +#define OB_EMPTY_CONE 7 /* boundtype */ #define OB_BOUND_BOX 0 @@ -453,3 +456,4 @@ extern Object workob; #endif + diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index fc2fa7cab20..a00d7d484d9 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -198,6 +198,9 @@ typedef struct ParticleSystem{ /* if you change these remember to update array lengths to PSYS_TOT_VG! */ short vgroup[11], vg_neg, rt3[2]; + + /* temporary storage during render */ + void *renderdata; }ParticleSystem; /* general particle maximums */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2dfe0ac43b6..412c40c7eb0 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -363,7 +363,8 @@ typedef struct ToolSettings { short uvcalc_mapalign; short uvcalc_flag; - short pad2; + /* Auto-IK */ + short autoik_chainlen; /* Image Paint (8 byte aligned please!) */ struct ImagePaintSettings imapaint; @@ -443,6 +444,10 @@ typedef struct SculptData /* Symmetry is separate from the other BrushData because the same settings are always used for all brush types */ char symm; + + /* Added to store if the 'Rake' setting has been set */ + char rake; + char pad[7]; } SculptData; typedef struct Scene { diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c index b15aa6802f3..24395059c60 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c @@ -51,7 +51,7 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **in, bNod if(data) { ShadeInput *shi= ((ShaderCallData *)data)->shi; NodeGeometry *ngeo= (NodeGeometry*)node->storage; - ShadeInputUV *suv= &shi->uv[0]; + ShadeInputUV *suv= &shi->uv[shi->actuv]; static float defaultvcol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; static float front= 0.0; int i; diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index 9d151bee092..c78ed83f79e 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -362,47 +362,34 @@ static char Method_Exit_doc[] = "() - Exit the windowing interface"; */ PyObject *M_Button_List = NULL; -/* -* here we engage in some macro trickery to define the PyMethodDef table -*/ - -#define _MethodDef(func, prefix) \ - {#func, prefix##_##func, METH_VARARGS, prefix##_##func##_doc} - -/* So that _MethodDef(delete, Scene) expands to: - * {"delete", Scene_delete, METH_VARARGS, Scene_delete_doc} */ - -#undef MethodDef -#define MethodDef(func) _MethodDef(func, Method) - static struct PyMethodDef Draw_methods[] = { - MethodDef( Create ), - MethodDef( UIBlock ), - MethodDef( Button ), - MethodDef( Toggle ), - MethodDef( Menu ), - MethodDef( Slider ), - MethodDef( Scrollbar ), - MethodDef( ColorPicker ), - MethodDef( Normal ), - MethodDef( Number ), - MethodDef( String ), - MethodDef( GetStringWidth ), - MethodDef( Text ), - MethodDef( Label ), - MethodDef( PupMenu ), - MethodDef( PupIntInput ), - MethodDef( PupFloatInput ), - MethodDef( PupStrInput ), - MethodDef( PupBlock ), - MethodDef( Image ), + {"Create", (PyCFunction)Method_Create, METH_VARARGS, Method_Create_doc}, + {"UIBlock", (PyCFunction)Method_UIBlock, METH_VARARGS, Method_UIBlock_doc}, + {"Button", (PyCFunction)Method_Button, METH_VARARGS, Method_Button_doc}, + {"Toggle", (PyCFunction)Method_Toggle, METH_VARARGS, Method_Toggle_doc}, + {"Menu", (PyCFunction)Method_Menu, METH_VARARGS, Method_Menu_doc}, + {"Slider", (PyCFunction)Method_Slider, METH_VARARGS, Method_Slider_doc}, + {"Scrollbar", (PyCFunction)Method_Scrollbar, METH_VARARGS, Method_Scrollbar_doc}, + {"ColorPicker", (PyCFunction)Method_ColorPicker, METH_VARARGS, Method_ColorPicker_doc}, + {"Normal", (PyCFunction)Method_Normal, METH_VARARGS, Method_Normal_doc}, + {"Number", (PyCFunction)Method_Number, METH_VARARGS, Method_Number_doc}, + {"String", (PyCFunction)Method_String, METH_VARARGS, Method_String_doc}, + {"GetStringWidth", (PyCFunction)Method_GetStringWidth, METH_VARARGS, Method_GetStringWidth_doc}, + {"Text", (PyCFunction)Method_Text, METH_VARARGS, Method_Text_doc}, + {"Label", (PyCFunction)Method_Label, METH_VARARGS, Method_Label_doc}, + {"PupMenu", (PyCFunction)Method_PupMenu, METH_VARARGS, Method_PupMenu_doc}, + {"PupIntInput", (PyCFunction)Method_PupIntInput, METH_VARARGS, Method_PupIntInput_doc}, + {"PupFloatInput", (PyCFunction)Method_PupFloatInput, METH_VARARGS, Method_PupFloatInput_doc}, + {"PupStrInput", (PyCFunction)Method_PupStrInput, METH_VARARGS, Method_PupStrInput_doc}, + {"PupBlock", (PyCFunction)Method_PupBlock, METH_VARARGS, Method_PupBlock_doc}, + {"Image", (PyCFunction)Method_Image, METH_VARARGS, Method_Image_doc}, {"Exit", (PyCFunction)Method_Exit, METH_NOARGS, Method_Exit_doc}, - MethodDef( Redraw ), + {"Redraw", (PyCFunction)Method_Redraw, METH_VARARGS, Method_Redraw_doc}, {"Draw", (PyCFunction)Method_Draw, METH_NOARGS, Method_Draw_doc}, - MethodDef( Register ), + {"Register", (PyCFunction)Method_Register, METH_VARARGS, Method_Register_doc}, {"PushButton", (PyCFunction)Method_Button, METH_VARARGS, Method_Button_doc}, - MethodDef( BeginAlign ), - MethodDef( EndAlign), + {"BeginAlign", (PyCFunction)Method_BeginAlign, METH_VARARGS, Method_BeginAlign_doc}, + {"EndAlign", (PyCFunction)Method_EndAlign, METH_VARARGS, Method_EndAlign_doc}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/api2_2x/Geometry.c b/source/blender/python/api2_2x/Geometry.c index 344fdcf20a9..842479e35fb 100644 --- a/source/blender/python/api2_2x/Geometry.c +++ b/source/blender/python/api2_2x/Geometry.c @@ -287,7 +287,7 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args VectorObject *pt, *line_1, *line_2; float pt_in[3], pt_out[3], l1[3], l2[3]; float lambda; - PyObject *ret, *val1, *val2; + PyObject *ret; if( !PyArg_ParseTuple ( args, "O!O!O!", &vector_Type, &pt, diff --git a/source/blender/python/api2_2x/Key.c b/source/blender/python/api2_2x/Key.c index 88facd80b4e..90a628152e0 100644 --- a/source/blender/python/api2_2x/Key.c +++ b/source/blender/python/api2_2x/Key.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "BIF_space.h" #include "Ipocurve.h" @@ -60,9 +61,6 @@ #define KEY_TYPE_CURVE 1 #define KEY_TYPE_LATTICE 2 -/* macro from blenkernel/intern/key.c:98 */ -#define GS(a) (*((short *)(a))) - static int Key_compare( BPy_Key * a, BPy_Key * b ); static PyObject *Key_repr( BPy_Key * self ); static void Key_dealloc( BPy_Key * self ); diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index 8248816bc3d..323be4e89e5 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -5394,7 +5394,7 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args ) return EXPP_ReturnPyObjError( PyExc_TypeError, "sequence must contain at least one int or MFace" ); - face_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ), + face_table = MEM_callocN( len*sizeof( unsigned int ), "face_table" ); /* get the indices of faces to be removed */ @@ -5517,15 +5517,12 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args ) ++face_count; } } - - /* for each face, deselect each edge */ + + /* for each remaining face, select all edges */ tmpface = mesh->mface; fface = (struct fourEdges *)face_edges; for( i = mesh->totface; i--; ++tmpface, ++fface ) { if( tmpface->v1 != UINT_MAX ) { - FaceEdges (*face)[4]; - face = (void *)face_edges; - face += face_table[i]; fface->v[0]->sel = 1; fface->v[1]->sel = 1; fface->v[2]->sel = 1; @@ -5533,7 +5530,6 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args ) fface->v[3]->sel = 1; } } - /* now mark the selected edges for deletion */ edge_count = 0; diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index 5db09b11aee..86e36655c28 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -536,7 +536,7 @@ static int Sequence_setImages( BPy_Sequence * self, PyObject *value ) Strip *strip; StripElem *se; int i; - PyObject *list, *item; + PyObject *list; char *basepath, *name; if (self->seq->type != SEQ_IMAGE) { @@ -564,6 +564,8 @@ static int Sequence_setImages( BPy_Sequence * self, PyObject *value ) name = PyString_AsString(PyList_GetItem(list, i)); if (name) { strncpy(se->name, name, sizeof(se->name)); + } else { + PyErr_Clear(); } } diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c index 46fb6b2c910..b6411522179 100644 --- a/source/blender/radiosity/intern/source/radfactors.c +++ b/source/blender/radiosity/intern/source/radfactors.c @@ -912,8 +912,8 @@ void inithemiwindows() memset(vw, 0, sizeof(RadView)); vw->rectx= RG.hemires; vw->recty= RG.hemires; - vw->rectz= MEM_mallocN(4*vw->rectx*vw->recty, "initwindows"); - vw->rect= MEM_mallocN(4*vw->rectx*vw->recty, "initwindows"); + vw->rectz= MEM_mallocN(sizeof(int)*vw->rectx*vw->recty, "initwindows"); + vw->rect= MEM_mallocN(sizeof(int)*vw->rectx*vw->recty, "initwindows"); vw->mynear= RG.maxsize/2000.0; vw->myfar= 2.0*RG.maxsize; vw->wx1= -vw->mynear; diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c index 42c7fa58da5..ee52956bbd2 100644 --- a/source/blender/radiosity/intern/source/radrender.c +++ b/source/blender/radiosity/intern/source/radrender.c @@ -87,6 +87,7 @@ static float maxenergy; static VlakRen *findshoot_rr(Render *re) { RadFace *rf; + ObjectRen *obr; VlakRen *vlr=NULL, *shoot; float energy; int a; @@ -94,19 +95,21 @@ static VlakRen *findshoot_rr(Render *re) shoot= NULL; maxenergy= 0.0; - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - if(vlr->radface) { - rf= vlr->radface; - rf->flag &= ~RAD_SHOOT; - - energy= rf->unshot[0]*rf->area; - energy+= rf->unshot[1]*rf->area; - energy+= rf->unshot[2]*rf->area; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; + if(vlr->radface) { + rf= vlr->radface; + rf->flag &= ~RAD_SHOOT; + + energy= rf->unshot[0]*rf->area; + energy+= rf->unshot[1]*rf->area; + energy+= rf->unshot[2]*rf->area; - if(energy>maxenergy) { - shoot= vlr; - maxenergy= energy; + if(energy>maxenergy) { + shoot= vlr; + maxenergy= energy; + } } } } @@ -122,22 +125,22 @@ static VlakRen *findshoot_rr(Render *re) static void backface_test_rr(Render *re, VlakRen *shoot) { + ObjectRen *obr; VlakRen *vlr=NULL; RadFace *rf; float tvec[3]; int a; /* backface testing */ - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - if(vlr->radface) { - if(vlr!=shoot) { + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; + if(vlr->radface && vlr!=shoot) { rf= vlr->radface; VecSubf(tvec, shoot->radface->cent, rf->cent); - if( tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0) { + if(tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0) rf->flag |= RAD_BACKFACE; - } } } } @@ -145,17 +148,20 @@ static void backface_test_rr(Render *re, VlakRen *shoot) static void clear_backface_test_rr(Render *re) { + ObjectRen *obr; VlakRen *vlr=NULL; RadFace *rf; int a; /* backface flag clear */ - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->radface) { - rf= vlr->radface; - rf->flag &= ~RAD_BACKFACE; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; + + if(vlr->radface) { + rf= vlr->radface; + rf->flag &= ~RAD_BACKFACE; + } } } } @@ -165,6 +171,7 @@ extern RadView hemitop, hemiside; // radfactors.c /* hemi-zbuffering, delivers formfactors array */ static void makeformfactors_rr(Render *re, VlakRen *shoot) { + ObjectRen *obr; VlakRen *vlr=NULL; RadFace *rf; float len, vec[3], up[3], side[3], tar[5][3], *fp; @@ -207,16 +214,18 @@ static void makeformfactors_rr(Render *re, VlakRen *shoot) /* convert factors to real radiosity */ fp= RG.formfactors; - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->radface) { - rf= vlr->radface; - if(*fp!=0.0 && rf->area!=0.0) { - *fp *= shoot->radface->area/rf->area; - if(*fp>1.0) *fp= 1.0001; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; + + if(vlr->radface) { + rf= vlr->radface; + if(*fp!=0.0 && rf->area!=0.0) { + *fp *= shoot->radface->area/rf->area; + if(*fp>1.0) *fp= 1.0001; + } + fp++; } - fp++; } } } @@ -224,6 +233,7 @@ static void makeformfactors_rr(Render *re, VlakRen *shoot) /* based at RG.formfactors array, distribute shoot energy over other faces */ static void applyformfactors_rr(Render *re, VlakRen *shoot) { + ObjectRen *obr; VlakRen *vlr=NULL; RadFace *rf; float *fp, *ref, unr, ung, unb, r, g, b; @@ -235,30 +245,32 @@ static void applyformfactors_rr(Render *re, VlakRen *shoot) fp= RG.formfactors; - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->radface) { - rf= vlr->radface; - if(*fp!= 0.0) { - - ref= &(vlr->mat->r); - - r= (*fp)*unr*ref[0]; - g= (*fp)*ung*ref[1]; - b= (*fp)*unb*ref[2]; - - // if(rf->flag & RAD_BACKFACE) { - - rf->totrad[0]+= r; - rf->totrad[1]+= g; - rf->totrad[2]+= b; - - rf->unshot[0]+= r; - rf->unshot[1]+= g; - rf->unshot[2]+= b; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; + + if(vlr->radface) { + rf= vlr->radface; + if(*fp!= 0.0) { + + ref= &(vlr->mat->r); + + r= (*fp)*unr*ref[0]; + g= (*fp)*ung*ref[1]; + b= (*fp)*unb*ref[2]; + + // if(rf->flag & RAD_BACKFACE) { + + rf->totrad[0]+= r; + rf->totrad[1]+= g; + rf->totrad[2]+= b; + + rf->unshot[0]+= r; + rf->unshot[1]+= g; + rf->unshot[2]+= b; + } + fp++; } - fp++; } } /* shoot energy has been shot */ @@ -313,6 +325,7 @@ static RadFace *radfaces=NULL; static void initradfaces(Render *re) { + ObjectRen *obr; VlakRen *vlr= NULL; RadFace *rf; int a, b; @@ -326,58 +339,62 @@ static void initradfaces(Render *re) RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20; /* count first for fast malloc */ - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->mat->mode & MA_RADIO) { - if(vlr->mat->emit > 0.0) { - RG.totpatch++; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; + + if(vlr->mat->mode & MA_RADIO) { + if(vlr->mat->emit > 0.0) { + RG.totpatch++; + } + RG.totelem++; } - RG.totelem++; } } - + printf(" Rad elems: %d emittors %d\n", RG.totelem, RG.totpatch); if(RG.totelem==0 || RG.totpatch==0) return; /* make/init radfaces */ rf=radfaces= MEM_callocN(RG.totelem*sizeof(RadFace), "radfaces"); - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->mat->mode & MA_RADIO) { + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - /* during render, vlr->n gets flipped/corrected, we cannot have that */ - if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm); - else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm); - - rf->totrad[0]= vlr->mat->emit*vlr->mat->r; - rf->totrad[1]= vlr->mat->emit*vlr->mat->g; - rf->totrad[2]= vlr->mat->emit*vlr->mat->b; - VECCOPY(rf->unshot, rf->totrad); - - if(vlr->v4) { - rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co); - CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co); - } - else { - rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co); - CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co); - } - - RG.totenergy+= rf->unshot[0]*rf->area; - RG.totenergy+= rf->unshot[1]*rf->area; - RG.totenergy+= rf->unshot[2]*rf->area; - - for(b=0; b<3; b++) { - RG.min[b]= MIN2(RG.min[b], rf->cent[b]); - RG.max[b]= MAX2(RG.max[b], rf->cent[b]); - } + if(vlr->mat->mode & MA_RADIO) { + + /* during render, vlr->n gets flipped/corrected, we cannot have that */ + if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm); + else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm); + + rf->totrad[0]= vlr->mat->emit*vlr->mat->r; + rf->totrad[1]= vlr->mat->emit*vlr->mat->g; + rf->totrad[2]= vlr->mat->emit*vlr->mat->b; + VECCOPY(rf->unshot, rf->totrad); + + if(vlr->v4) { + rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co); + CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co); + } + else { + rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co); + CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co); + } + + RG.totenergy+= rf->unshot[0]*rf->area; + RG.totenergy+= rf->unshot[1]*rf->area; + RG.totenergy+= rf->unshot[2]*rf->area; + + for(b=0; b<3; b++) { + RG.min[b]= MIN2(RG.min[b], rf->cent[b]); + RG.max[b]= MAX2(RG.max[b], rf->cent[b]); + } -// uncommented; this isnt satisfying, but i leave it in the code for now (ton) -// if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED; - - vlr->radface= rf++; + // uncommented; this isnt satisfying, but i leave it in the code for now (ton) + // if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED; + + vlr->radface= rf++; + } } } RG.size[0]= (RG.max[0]- RG.min[0]); @@ -408,6 +425,7 @@ static void vecaddfac(float *vec, float *v1, float *v2, float fac) static void make_vertex_rad_values(Render *re) { + ObjectRen *obr; VertRen *v1=NULL; VlakRen *vlr=NULL; RadFace *rf; @@ -418,54 +436,55 @@ static void make_vertex_rad_values(Render *re) RG.radfactor= RG.radfac*pow(64*64, RG.igamma)/128.0; /* compatible with radio-tool */ /* accumulate vertexcolors */ - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->radface) { - rf= vlr->radface; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - /* apply correction */ - rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma); - rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma); - rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma); - - /* correct rf->rad values for color */ - if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r; - if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g; - if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b; - - col= RE_vertren_get_rad(re, vlr->v1, 1); - vecaddfac(col, col, rf->totrad, rf->area); - col[3]+= rf->area; - - col= RE_vertren_get_rad(re, vlr->v2, 1); - vecaddfac(col, col, rf->totrad, rf->area); - col[3]+= rf->area; - - col= RE_vertren_get_rad(re, vlr->v3, 1); - vecaddfac(col, col, rf->totrad, rf->area); - col[3]+= rf->area; - - if(vlr->v4) { - col= RE_vertren_get_rad(re, vlr->v4, 1); + if(vlr->radface) { + rf= vlr->radface; + + /* apply correction */ + rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma); + rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma); + rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma); + + /* correct rf->rad values for color */ + if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r; + if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g; + if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b; + + col= RE_vertren_get_rad(obr, vlr->v1, 1); vecaddfac(col, col, rf->totrad, rf->area); col[3]+= rf->area; + + col= RE_vertren_get_rad(obr, vlr->v2, 1); + vecaddfac(col, col, rf->totrad, rf->area); + col[3]+= rf->area; + + col= RE_vertren_get_rad(obr, vlr->v3, 1); + vecaddfac(col, col, rf->totrad, rf->area); + col[3]+= rf->area; + + if(vlr->v4) { + col= RE_vertren_get_rad(obr, vlr->v4, 1); + vecaddfac(col, col, rf->totrad, rf->area); + col[3]+= rf->area; + } + } + } + + /* make vertex colors */ + for(a=0; atotvert; a++) { + if((a & 255)==0) v1= RE_findOrAddVert(obr, a); else v1++; + + col= RE_vertren_get_rad(obr, v1, 0); + if(col && col[3]>0.0) { + col[0]/= col[3]; + col[1]/= col[3]; + col[2]/= col[3]; } } } - - /* make vertex colors */ - for(a=0; atotvert; a++) { - if((a & 255)==0) v1= RE_findOrAddVert(re, a); else v1++; - - col= RE_vertren_get_rad(re, v1, 0); - if(col && col[3]>0.0) { - col[0]/= col[3]; - col[1]/= col[3]; - col[2]/= col[3]; - } - } - } /* main call, extern */ diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index d20e3130fa4..39bf2be4256 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -41,6 +41,19 @@ typedef void RayTree; /* abstraction of face type */ typedef void RayFace; +/* object numbers above this are transformed */ +#define RE_RAY_TRANSFORM_OFFS 0x8000000 + +/* convert from pointer to index in array and back, with offset if the + * instance is transformed */ +#define RAY_OBJECT_SET(re, obi) \ + ((obi == NULL)? 0: \ + ((obi - (re)->objectinstance) + ((obi->flag & R_TRANSFORMED)? RE_RAY_TRANSFORM_OFFS: 0))) + +#define RAY_OBJECT_GET(re, i) \ + ((re)->objectinstance + ((i >= RE_RAY_TRANSFORM_OFFS)? i-RE_RAY_TRANSFORM_OFFS: i)) + + /* struct for intersection data */ typedef struct Isect { float start[3]; /* start+vec = end, in ray_tree_intersect */ @@ -50,8 +63,11 @@ typedef struct Isect { float labda, u, v; /* distance to hitpoint, uv weights */ RayFace *face; /* face is where to intersect with */ + int ob; RayFace *faceorig; /* start face */ + int oborig; RayFace *face_last; /* for shadow optimize, last intersected face */ + int ob_last; short isect; /* which half of quad */ short mode; /* RE_RAYSHADOW, RE_RAYMIRROR, RE_RAYSHADOW_TRA */ @@ -62,6 +78,7 @@ typedef struct Isect { /* octree only */ RayFace *facecontr; + int obcontr; float ddalabda; short faceisect; /* flag if facecontr was done or not */ @@ -73,18 +90,21 @@ typedef struct Isect { typedef void (*RayCoordsFunc)(RayFace *face, float **v1, float **v2, float **v3, float **v4); typedef int (*RayCheckFunc)(Isect *is, RayFace *face); +typedef float *(*RayObjectTransformFunc)(void *userdata, int ob); /* tree building and freeing */ RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, - RayCoordsFunc coordfunc, RayCheckFunc checkfunc); -void RE_ray_tree_add_face(RayTree *tree, RayFace *face); + RayCoordsFunc coordfunc, RayCheckFunc checkfunc, + RayObjectTransformFunc transformfunc, void *userdata); +void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face); void RE_ray_tree_done(RayTree *tree); void RE_ray_tree_free(RayTree *tree); /* intersection with full tree and single face */ int RE_ray_tree_intersect(RayTree *tree, Isect *is); int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc check); -int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc); +int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc, + RayCoordsFunc coordsfunc); /* retrieve the diameter of the tree structure, for setting intersection end distance */ diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 8a4f6bb2ec8..5b81052f5d2 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -64,8 +64,11 @@ struct ShadeInputCopy { struct Material *mat; struct VlakRen *vlr; + struct ObjectInstanceRen *obi; + struct ObjectRen *obr; int facenr; float facenor[3]; /* copy from face */ + short flippednor; /* is facenor flipped? */ struct VertRen *v1, *v2, *v3; /* vertices can be in any order for quads... */ short i1, i2, i3; /* original vertex indices */ short puno; @@ -93,8 +96,11 @@ typedef struct ShadeInput struct Material *mat; struct VlakRen *vlr; + struct ObjectInstanceRen *obi; + struct ObjectRen *obr; int facenr; float facenor[3]; /* copy from face */ + short flippednor; /* is facenor flipped? */ struct VertRen *v1, *v2, *v3; /* vertices can be in any order for quads... */ short i1, i2, i3; /* original vertex indices */ short puno; @@ -130,7 +136,7 @@ typedef struct ShadeInput ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */ ShadeInputCol col[8]; /* 8 = MAX_MCOL */ - int totuv, totcol; + int totuv, totcol, actuv, actcol; /* dx/dy OSA coordinates */ float dxco[3], dyco[3]; diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index f7f2222e98d..4a731878ffb 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -49,6 +49,7 @@ struct VertTableNode; struct VlakTableNode; struct GHash; struct RenderBuckets; +struct ObjectInstanceRen; #define TABLEINITSIZE 1024 #define LAMPINITSIZE 256 @@ -81,13 +82,15 @@ typedef struct RenderPart /* result of part rendering */ RenderResult *result; + int *recto; /* object table for objects */ int *rectp; /* polygon index table */ int *rectz; /* zbuffer */ long *rectdaps; /* delta acum buffer for pixel structs */ + int *rectbacko; /* object table for backside sss */ int *rectbackp; /* polygon index table for backside sss */ int *rectbackz; /* zbuffer for backside sss */ long *rectall; /* buffer for all faces for sss */ - + rcti disprect; /* part coordinates within total picture */ int rectx, recty; /* the size */ short crop, ready; /* crop is amount of pixels we crop, for filter */ @@ -161,21 +164,19 @@ struct Render /* render database */ int totvlak, totvert, tothalo, totstrand, totlamp; + struct HaloRen **sortedhalos; + ListBase lights; /* GroupObject pointers */ ListBase lampren; /* storage, for free */ - int vertnodeslen; - struct VertTableNode *vertnodes; - int vlaknodeslen; - struct VlakTableNode *vlaknodes; - int strandnodeslen; - struct StrandTableNode *strandnodes; - int blohalen; - struct HaloRen **bloha; ListBase objecttable; - ListBase strandbufs; struct RenderBuckets *strandbuckets; + struct ObjectInstanceRen *objectinstance; + ListBase instancetable; + struct GHash *objecthash; + int totinstance; + struct Image *backbuf, *bakebuf; struct GHash *orco_hash; @@ -235,23 +236,48 @@ typedef struct ShadBuf { } ShadBuf; /* ------------------------------------------------------------------------- */ -/* lookup of objects in database */ + typedef struct ObjectRen { struct ObjectRen *next, *prev; struct Object *ob, *par; - int index, startvert, endvert, startface, endface, startstrand, endstrand; - float *vectors; + struct Scene *sce; + int index, psysindex; + + int totvert, totvlak, totstrand, tothalo; + int vertnodeslen, vlaknodeslen, strandnodeslen, blohalen; + struct VertTableNode *vertnodes; + struct VlakTableNode *vlaknodes; + struct StrandTableNode *strandnodes; + struct HaloRen **bloha; + ListBase strandbufs; + + char (*mtface)[32]; + char (*mcol)[32]; + int actmtface, actmcol; } ObjectRen; +typedef struct ObjectInstanceRen { + struct ObjectInstanceRen *next, *prev; + + ObjectRen *obr; + Object *ob, *par; + int index, psysindex; + + float mat[4][4], imat[3][3]; + short flag; + + float *vectors; + int totvector; +} ObjectInstanceRen; + /* ------------------------------------------------------------------------- */ typedef struct VertRen { float co[3]; float n[3]; - float ho[4]; float *orco; - short clip; + short clip; unsigned short flag; /* in use for clipping zbuffer parts, temp setting stuff in convertblender.c */ float accum; /* accum for radio weighting, and for strand texco static particles */ int index; /* index allows extending vertren with any property */ @@ -279,10 +305,10 @@ typedef struct VlakRen { unsigned int lay; float n[3]; struct Material *mat; - char noflag, puno; + char puno; char flag, ec; RadFace *radface; - Object *ob; + ObjectRen *obr; int index; } VlakRen; @@ -312,7 +338,7 @@ typedef struct StrandBuffer { struct StrandVert *vert; int totvert; - struct Object *ob; + struct ObjectRen *obr; struct Material *ma; unsigned int lay; int overrideuv; @@ -393,7 +419,7 @@ typedef struct LampRen { short xold[BLENDER_MAX_THREADS], yold[BLENDER_MAX_THREADS]; /* last jitter table for area lights */ float area_size, area_sizey, area_sizez; float adapt_thresh; - + struct ShadBuf *shb; float *jitter; QMCSampler *qsa; @@ -417,8 +443,13 @@ typedef struct LampRen { /* ray optim */ VlakRen *vlr_last[BLENDER_MAX_THREADS]; + ObjectInstanceRen *obi_last[BLENDER_MAX_THREADS]; struct MTex *mtex[MAX_MTEX]; + + /* threading */ + int thread_assigned; + int thread_ready; } LampRen; /* **************** defines ********************* */ @@ -435,7 +466,7 @@ typedef struct LampRen { /* vlakren->flag (vlak = face in dutch) char!!! */ #define R_SMOOTH 1 -#define R_VISIBLE 2 +#define R_HIDDEN 2 /* strand flag, means special handling */ #define R_STRAND 4 #define R_NOPUNOFLIP 8 @@ -446,16 +477,14 @@ typedef struct LampRen { /* vertex normals are tangent or view-corrected vector, for hair strands */ #define R_TANGENT 128 -/* vlakren->noflag (char) */ -#define R_SNPROJ_X 1 -#define R_SNPROJ_Y 2 -#define R_SNPROJ_Z 4 -#define R_FLIPPED_NO 8 - /* strandbuffer->flag */ #define R_STRAND_BSPLINE 1 #define R_STRAND_B_UNITS 2 +/* objectinstance->flag */ +#define R_DUPLI_TRANSFORMED 1 +#define R_ENV_TRANSFORMED 2 +#define R_TRANSFORMED (1|2) #endif /* RENDER_TYPES_H */ diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 0d807d56180..600ece8ad50 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -49,13 +49,14 @@ struct ShadeResult; struct World; struct RenderPart; struct RenderLayer; +struct ObjectRen; /* ------------------------------------------------------------------------- */ typedef struct PixStr { struct PixStr *next; - int facenr, z; + int obi, facenr, z; unsigned short mask; short shadfac; } PixStr; diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h index febf90d9d6e..0346f2d6413 100644 --- a/source/blender/render/intern/include/renderdatabase.h +++ b/source/blender/render/intern/include/renderdatabase.h @@ -41,6 +41,7 @@ struct MTFace; struct CustomData; struct StrandBuffer; struct StrandRen; +struct ObjectInstanceRen; #define RE_QUAD_MASK 0x7FFFFFF #define RE_QUAD_OFFS 0x8000000 @@ -58,71 +59,65 @@ typedef struct VertTableNode { typedef struct VlakTableNode { struct VlakRen *vlak; - struct MTFace **mtface; - struct MCol **mcol; + struct MTFace *mtface; + struct MCol *mcol; int totmtface, totmcol; float *surfnor; - struct CustomDataNames **names; } VlakTableNode; typedef struct StrandTableNode { struct StrandRen *strand; float *winspeed; float *surfnor; - struct MCol **mcol; - float **uv; + struct MCol *mcol; + float *uv; int totuv, totmcol; - struct CustomDataNames **names; } StrandTableNode; -typedef struct CustomDataNames{ - struct CustomDataNames *next, *prev; - - char (*mtface)[32]; - char (*mcol)[32]; -} CustomDataNames; - /* renderdatabase.c */ void free_renderdata_tables(struct Render *re); void free_renderdata_vertnodes(struct VertTableNode *vertnodes); void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes); -void set_normalflags(Render *re); +void set_normalflags(struct Render *re, struct ObjectRen *obr); void project_renderdata(struct Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets); /* functions are not exported... so wrong names */ -struct VlakRen *RE_findOrAddVlak(struct Render *re, int nr); -struct VertRen *RE_findOrAddVert(struct Render *re, int nr); -struct StrandRen *RE_findOrAddStrand(struct Render *re, int nr); -struct HaloRen *RE_findOrAddHalo(struct Render *re, int nr); -struct HaloRen *RE_inithalo(struct Render *re, struct Material *ma, float *vec, float *vec1, float *orco, float hasize, - float vectsize, int seed); -struct HaloRen *RE_inithalo_particle(struct Render *re, struct DerivedMesh *dm, struct Material *ma, float *vec, float *vec1, - float *orco, float *uvco, float hasize, float vectsize, int seed); -void RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est); -struct StrandBuffer *RE_addStrandBuffer(struct Render *re, struct Object *ob, int totvert); +struct VlakRen *RE_findOrAddVlak(struct ObjectRen *obr, int nr); +struct VertRen *RE_findOrAddVert(struct ObjectRen *obr, int nr); +struct StrandRen *RE_findOrAddStrand(struct ObjectRen *obr, int nr); +struct HaloRen *RE_findOrAddHalo(struct ObjectRen *obr, int nr); +struct HaloRen *RE_inithalo(struct Render *re, struct ObjectRen *obr, struct Material *ma, float *vec, float *vec1, float *orco, float hasize, float vectsize, int seed); +struct HaloRen *RE_inithalo_particle(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, struct Material *ma, float *vec, float *vec1, float *orco, float *uvco, float hasize, float vectsize, int seed); +struct StrandBuffer *RE_addStrandBuffer(struct ObjectRen *obr, int totvert); -float *RE_vertren_get_sticky(struct Render *re, struct VertRen *ver, int verify); -float *RE_vertren_get_stress(struct Render *re, struct VertRen *ver, int verify); -float *RE_vertren_get_rad(struct Render *re, struct VertRen *ver, int verify); -float *RE_vertren_get_strand(struct Render *re, struct VertRen *ver, int verify); -float *RE_vertren_get_tangent(struct Render *re, struct VertRen *ver, int verify); -float *RE_vertren_get_winspeed(struct Render *re, struct VertRen *ver, int verify); +struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int psysindex); +void RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4]); +void RE_makeRenderInstances(struct Render *re); +void RE_instanceTransformNormal(struct ObjectInstanceRen *obi, float *nor, float *tnor); -struct MTFace *RE_vlakren_get_tface(struct Render *re, VlakRen *ren, int n, char **name, int verify); -struct MCol *RE_vlakren_get_mcol(struct Render *re, VlakRen *ren, int n, char **name, int verify); -float *RE_vlakren_get_surfnor(struct Render *re, VlakRen *ren, int verify); +float *RE_vertren_get_sticky(struct ObjectRen *obr, struct VertRen *ver, int verify); +float *RE_vertren_get_stress(struct ObjectRen *obr, struct VertRen *ver, int verify); +float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify); +float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify); +float *RE_vertren_get_tangent(struct ObjectRen *obr, struct VertRen *ver, int verify); +float *RE_vertren_get_winspeed(struct ObjectInstanceRen *obi, struct VertRen *ver, int verify); -float *RE_strandren_get_winspeed(struct Render *re, struct StrandRen *strand, int verify); -float *RE_strandren_get_surfnor(struct Render *re, struct StrandRen *strand, int verify); -float *RE_strandren_get_uv(struct Render *re, struct StrandRen *strand, int n, char **name, int verify); -struct MCol *RE_strandren_get_mcol(struct Render *re, struct StrandRen *strand, int n, char **name, int verify); +struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify); +struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify); +float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify); +int RE_vlakren_get_normal(struct Render *re, struct ObjectInstanceRen *obi, struct VlakRen *vlr, float *nor); -struct VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver); -struct VlakRen *RE_vlakren_copy(struct Render *re, struct VlakRen *vlr); +float *RE_strandren_get_surfnor(struct ObjectRen *obr, struct StrandRen *strand, int verify); +float *RE_strandren_get_uv(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify); +struct MCol *RE_strandren_get_mcol(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify); +float *RE_strandren_get_winspeed(struct ObjectInstanceRen *obi, struct StrandRen *strand, int verify); -void RE_vlakren_set_customdata_names(struct Render *re, struct CustomData *data); +struct VertRen *RE_vertren_copy(struct ObjectRen *obr, struct VertRen *ver); +struct VlakRen *RE_vlakren_copy(struct ObjectRen *obr, struct VlakRen *vlr); + +void RE_set_customdata_names(struct ObjectRen *obr, struct CustomData *data); /* haloren->type: flags */ #define HA_ONLYSKY 1 diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h index 8b786c6e098..20a266f8579 100644 --- a/source/blender/render/intern/include/shadbuf.h +++ b/source/blender/render/intern/include/shadbuf.h @@ -37,6 +37,8 @@ #include "render_types.h" +struct ObjectRen; + /** * Calculates shadowbuffers for a vector of shadow-giving lamps * @param lar The vector of lamps @@ -44,6 +46,8 @@ void makeshadowbuf(struct Render *re, LampRen *lar); void freeshadowbuf(struct LampRen *lar); +void threaded_makeshadowbufs(struct Render *re); + /** * Determines the shadow factor for a face and lamp. There is some * communication with global variables here. @@ -80,6 +84,7 @@ float ISB_getshadow(ShadeInput *shi, ShadBuf *shb); typedef struct ISBSample { float zco[3]; /* coordinate in lampview projection */ short *shadfac; /* initialized zero = full lighted */ + int obi; /* object for face lookup */ int facenr; /* index in faces list */ } ISBSample; @@ -87,6 +92,7 @@ typedef struct ISBSample { typedef struct ISBSampleA { float zco[3]; /* coordinate in lampview projection */ short *shadfac; /* NULL = full lighted */ + int obi; /* object for face lookup */ int facenr; /* index in faces list */ struct ISBSampleA *next; /* in end, we want the first items to align with ISBSample */ } ISBSampleA; @@ -94,6 +100,7 @@ typedef struct ISBSampleA { /* used for transparent storage only */ typedef struct ISBShadfacA { struct ISBShadfacA *next; + int obi; int facenr; float shadfac; } ISBShadfacA; diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index 3390c32ebfe..6ca63a2976d 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -32,6 +32,7 @@ struct LampRen; struct VlakRen; struct StrandSegment; struct StrandPoint; +struct ObjectInstanceRen obi; /* shadeinput.c */ @@ -52,12 +53,13 @@ typedef struct ShadeSample { /* also the node shader callback */ void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr); -void shade_input_set_triangle_i(struct ShadeInput *shi, struct VlakRen *vlr, short i1, short i2, short i3); -void shade_input_set_triangle(struct ShadeInput *shi, volatile int facenr, int normal_flip); +void shade_input_set_triangle_i(struct ShadeInput *shi, struct ObjectInstanceRen *obi, struct VlakRen *vlr, short i1, short i2, short i3); +void shade_input_set_triangle(struct ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip); void shade_input_copy_triangle(struct ShadeInput *shi, struct ShadeInput *from); void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float z); void shade_input_set_uv(struct ShadeInput *shi); void shade_input_set_normals(struct ShadeInput *shi); +void shade_input_flip_normals(struct ShadeInput *shi); void shade_input_set_shade_texco(struct ShadeInput *shi); void shade_input_set_strand(struct ShadeInput *shi, struct StrandRen *strand, struct StrandPoint *spoint); void shade_input_set_strand_texco(struct ShadeInput *shi, struct StrandRen *strand, struct StrandVert *svert, struct StrandPoint *spoint); diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h index 55c789de764..7f37317d4d5 100644 --- a/source/blender/render/intern/include/strand.h +++ b/source/blender/render/intern/include/strand.h @@ -43,6 +43,7 @@ struct RenderPart; struct RenderBuckets; struct RenderPrimitiveIterator; struct ZSpan; +struct ObjectInstanceRen; typedef struct StrandPoint { /* position within segment */ @@ -73,6 +74,7 @@ typedef struct StrandSegment { struct StrandVert *v[4]; struct StrandRen *strand; struct StrandBuffer *buffer; + struct ObjectInstanceRen *obi; float sqadaptcos; StrandPoint point1, point2; @@ -80,103 +82,7 @@ typedef struct StrandSegment { } StrandSegment; void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint); -void render_strand_segment(struct Render *re, struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg); -void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets); - -struct RenderBuckets *init_buckets(struct Render *re); -void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim); -void free_buckets(struct RenderBuckets *buckets); -void project_hoco_to_bucket(struct RenderBuckets *buckets, float *hoco, float *bucketco); - -struct RenderPrimitiveIterator *init_primitive_iterator(struct Render *re, struct RenderBuckets *buckets, struct RenderPart *pa); -void *next_primitive_iterator(struct RenderPrimitiveIterator *iter); -void free_primitive_iterator(struct RenderPrimitiveIterator *iter); - -#endif - -/* - * $Id$ - * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: none of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef STRAND_H -#define STRAND_H - -struct StrandVert; -struct StrandRen; -struct StrandBuffer; -struct ShadeSample; -struct StrandPart; -struct Render; -struct RenderPart; -struct RenderBuckets; -struct RenderPrimitiveIterator; -struct ZSpan; - -typedef struct StrandPoint { - /* position within segment */ - float t; - - /* camera space */ - float co[3]; - float nor[3]; - float tan[3]; - float strandco; - float width; - - /* derivatives */ - float dtco[3], dsco[3]; - float dtstrandco; - - /* outer points */ - float co1[3], co2[3]; - float hoco1[4], hoco2[4]; - float zco1[3], zco2[3]; - - /* screen space */ - float hoco[4]; - float x, y; -} StrandPoint; - -typedef struct StrandSegment { - struct StrandVert *v[4]; - struct StrandRen *strand; - struct StrandBuffer *buffer; - float sqadaptcos; - - StrandPoint point1, point2; - int shaded; -} StrandSegment; - -void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint); -void render_strand_segment(struct Render *re, struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg); +void render_strand_segment(struct Render *re, float winmat[][4], struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg); void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets); struct RenderBuckets *init_buckets(struct Render *re); diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h index 0d88d40e7ac..4d30c1e0dfb 100644 --- a/source/blender/render/intern/include/zbuf.h +++ b/source/blender/render/intern/include/zbuf.h @@ -35,6 +35,7 @@ struct RenderLayer; struct LampRen; struct VlakRen; struct ListBase; +struct ZSpan; void fillrect(int *rect, int x, int y, int val); @@ -46,19 +47,20 @@ void projectvert(float *v1, float winmat[][4], float *adr); void projectverto(float *v1, float winmat[][4], float *adr); int testclip(float *v); -void set_part_zbuf_clipflag(struct RenderPart *pa); -void zbuffer_shadow(struct Render *re, struct LampRen *lar, int *rectz, int size, float jitx, float jity); -void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag); +void zbuffer_shadow(struct Render *re, float winmat[][4], struct LampRen *lar, int *rectz, int size, float jitx, float jity); +void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag, void (*fillfunc)(struct RenderPart*, struct ZSpan*, int, void*), void *data); + unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass); unsigned short *zbuffer_strands_shade(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, float *pass); void convert_zbuf_to_distbuf(struct RenderPart *pa, struct RenderLayer *rl); -void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void *, int, int, int, int)); +void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void*, int, int, int, int, int)); typedef struct APixstr { - unsigned short mask[4]; /* jitter mask */ - int z[4]; /* distance */ - int p[4]; /* index */ - short shadfac[4]; /* optimize storage for irregular shadow */ + unsigned short mask[4]; /* jitter mask */ + int z[4]; /* distance */ + int p[4]; /* index */ + int obi[4]; /* object instance */ + short shadfac[4]; /* optimize storage for irregular shadow */ struct APixstr *next; } APixstr; @@ -81,6 +83,7 @@ typedef struct ZSpan { int *rectz, *arectz; /* zbuffers, arectz is for transparant */ int *rectz1; /* seconday z buffer for shadowbuffer (2nd closest z) */ int *rectp; /* polygon index buffer */ + int *recto; /* object buffer */ APixstr *apixbuf, *curpstr; /* apixbuf for transparent */ struct ListBase *apsmbase; @@ -88,25 +91,31 @@ typedef struct ZSpan { float shad_alpha; /* copy from material, used by irregular shadbuf */ int mask, apsmcounter; /* in use by apixbuf */ + float clipcrop; /* for shadow, was in R global before */ + void *sss_handle; /* used by sss */ - void (*sss_func)(void *, int, int, int, int); + void (*sss_func)(void *, int, int, int, int, int); - void (*zbuffunc)(struct ZSpan *, int, float *, float *, float *, float *); - void (*zbuflinefunc)(struct ZSpan *, int, float *, float *); + void (*zbuffunc)(struct ZSpan *, int, int, float *, float *, float *, float *); + void (*zbuflinefunc)(struct ZSpan *, int, int, float *, float *); } ZSpan; /* exported to shadbuf.c */ -void zbufclip4(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4); +void zbufclip4(struct ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4); void zbuf_free_span(struct ZSpan *zspan); /* to rendercore.c */ void zspan_scanconvert(struct ZSpan *zpan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) ); /* exported to edge render... */ -void zbufclip(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3); -void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty); -void zbufclipwire(struct ZSpan *zspan, int zvlnr, struct VlakRen *vlr); +void zbufclip(struct ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3); +void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty, float clipcrop); +void zbufclipwire(struct ZSpan *zspan, int obi, int zvlnr, int ec, float *ho1, float *ho2, float *ho3, float *ho4, int c1, int c2, int c3, int c4); + +/* exported to shadeinput.c */ +void zbuf_make_winmat(Render *re, float duplimat[][4], float winmat[][4]); +void zbuf_render_project(float winmat[][4], float *co, float *ho); #endif diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 9280b457a4c..de3bd6079a4 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -119,23 +119,15 @@ * Same is true for lamp coords & vec. * Duplicated data objects & dupliframe/duplivert objects are only stored once, * only the matrix is stored for all others, in yafray these objects are instances of the original. - * The main changes are in RE_rotateBlenderScene(). + * The main changes are in RE_Database_FromScene(). */ #endif /* disable yafray */ -/* ------------------------------------------------------------------------- */ -/* Local functions */ -/* ------------------------------------------------------------------------- */ -static short test_for_displace(Render *re, Object *ob); -static void do_displacement(Render *re, Object *ob, int startface, int numface, int startvert, int numvert ); -static int vlakren_customdata_layer_num(int n, int active); - /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */ /* or for checking vertex normal flips */ #define FLT_EPSILON10 1.19209290e-06F - /* ------------------------------------------------------------------------- */ /* Stuff for stars. This sits here because it uses gl-things. Part of @@ -143,14 +135,14 @@ this code may move down to the converter. */ /* ------------------------------------------------------------------------- */ /* this is a bad beast, since it is misused by the 3d view drawing as well. */ -static HaloRen *initstar(Render *re, float *vec, float hasize) +static HaloRen *initstar(Render *re, ObjectRen *obr, float *vec, float hasize) { HaloRen *har; float hoco[4]; projectverto(vec, re->winmat, hoco); - har= RE_findOrAddHalo(re, re->tothalo++); + har= RE_findOrAddHalo(obr, obr->tothalo++); /* projectvert is done in function zbufvlaggen again, because of parts */ VECCOPY(har->co, vec); @@ -171,6 +163,7 @@ void RE_make_stars(Render *re, void (*initfunc)(void), void (*vertexfunc)(float*), void (*termfunc)(void)) { extern unsigned char hash[512]; + ObjectRen *obr= NULL; World *wrld= NULL; HaloRen *har; Scene *scene; @@ -234,11 +227,14 @@ void RE_make_stars(Render *re, void (*initfunc)(void), if (initfunc) { initfunc(); } + + if(re) /* add render object for stars */ + obr= RE_addRenderObject(re, NULL, NULL, 0, 0); for (x = sx, fx = sx * stargrid; x <= ex; x++, fx += stargrid) { for (y = sy, fy = sy * stargrid; y <= ey ; y++, fy += stargrid) { for (z = sz, fz = sz * stargrid; z <= ez; z++, fz += stargrid) { - + BLI_srand((hash[z & 0xff] << 24) + (hash[y & 0xff] << 16) + (hash[x & 0xff] << 8)); vec[0] = fx + (hlfrand * BLI_drand()) - dblrand; vec[1] = fy + (hlfrand * BLI_drand()) - dblrand; @@ -281,7 +277,7 @@ void RE_make_stars(Render *re, void (*initfunc)(void), if (alpha != 0.0) { fac = force * BLI_drand(); - har = initstar(re, vec, fac); + har = initstar(re, obr, vec, fac); if (har) { har->alfa = sqrt(sqrt(alpha)); @@ -305,6 +301,9 @@ void RE_make_stars(Render *re, void (*initfunc)(void), } } if (termfunc) termfunc(); + + if(obr) + re->tothalo += obr->tothalo; } @@ -328,35 +327,35 @@ u | | F1 | F2 | /* ------------------------------------------------------------------------- */ -static void split_v_renderfaces(Render *re, int startvlak, int startvert, int usize, int vsize, int uIndex, int cyclu, int cyclv) +static void split_v_renderfaces(ObjectRen *obr, int startvlak, int startvert, int usize, int vsize, int uIndex, int cyclu, int cyclv) { int vLen = vsize-1+(!!cyclv); int v; for (v=0; vv2); + VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v); + VertRen *vert = RE_vertren_copy(obr, vlr->v2); if (cyclv) { vlr->v2 = vert; if (v==vLen-1) { - VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + 0); + VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0); vlr->v1 = vert; } else { - VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + v+1); + VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1); vlr->v1 = vert; } } else { vlr->v2 = vert; if (vv1 = vert; } if (v==0) { - vlr->v1 = RE_vertren_copy(re, vlr->v1); + vlr->v1 = RE_vertren_copy(obr, vlr->v1); } } } @@ -373,6 +372,8 @@ static int check_vnormal(float *n, float *veno) return 0; } +/* ------------------------------------------------------------------------- */ +/* Stress, tangents and normals */ /* ------------------------------------------------------------------------- */ static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2) @@ -389,20 +390,20 @@ static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2) acc[1]+= 1.0f; } -static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak) +static void calc_edge_stress(Render *re, ObjectRen *obr, Mesh *me) { float loc[3], size[3], *accum, *acc, *accumoffs, *stress; int a; - if(startvert==re->totvert) return; + if(obr->totvert==0) return; mesh_get_texspace(me, loc, NULL, size); - accum= MEM_callocN(2*sizeof(float)*(re->totvert-startvert), "temp accum for stress"); + accum= MEM_callocN(2*sizeof(float)*obr->totvert, "temp accum for stress"); /* de-normalize orco */ - for(a=startvert; atotvert; a++) { - VertRen *ver= RE_findOrAddVert(re, a); + for(a=0; atotvert; a++) { + VertRen *ver= RE_findOrAddVert(obr, a); if(ver->orco) { ver->orco[0]= ver->orco[0]*size[0] +loc[0]; ver->orco[1]= ver->orco[1]*size[1] +loc[1]; @@ -411,9 +412,9 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak) } /* add stress values */ - accumoffs= accum - 2*startvert; /* so we can use vertex index */ - for(a=startvlak; atotvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(re, a); + accumoffs= accum; /* so we can use vertex index */ + for(a=0; atotvlak; a++) { + VlakRen *vlr= RE_findOrAddVlak(obr, a); if(vlr->v1->orco && vlr->v4) { calc_edge_stress_add(accumoffs, vlr->v1, vlr->v2); @@ -427,14 +428,14 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak) } } - for(a=startvert; atotvert; a++) { - VertRen *ver= RE_findOrAddVert(re, a); + for(a=0; atotvert; a++) { + VertRen *ver= RE_findOrAddVert(obr, a); if(ver->orco) { /* find stress value */ acc= accumoffs + 2*ver->index; if(acc[1]!=0.0f) acc[0]/= acc[1]; - stress= RE_vertren_get_stress(re, ver, 1); + stress= RE_vertren_get_stress(obr, ver, 1); *stress= *acc; /* restore orcos */ @@ -474,9 +475,9 @@ void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, } /* gets tangent from tface or orco */ -static void calc_tangent_vector(Render *re, VlakRen *vlr) +static void calc_tangent_vector(ObjectRen *obr, VlakRen *vlr) { - MTFace *tface= RE_vlakren_get_tface(re, vlr, 0, NULL, 0); + MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4; float tang[3], *tav; float *uv1, *uv2, *uv3, *uv4; @@ -500,40 +501,40 @@ static void calc_tangent_vector(Render *re, VlakRen *vlr) tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, vlr->n, tang); - tav= RE_vertren_get_tangent(re, v1, 1); + tav= RE_vertren_get_tangent(obr, v1, 1); VECADD(tav, tav, tang); - tav= RE_vertren_get_tangent(re, v2, 1); + tav= RE_vertren_get_tangent(obr, v2, 1); VECADD(tav, tav, tang); - tav= RE_vertren_get_tangent(re, v3, 1); + tav= RE_vertren_get_tangent(obr, v3, 1); VECADD(tav, tav, tang); if(v4) { tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang); - tav= RE_vertren_get_tangent(re, v1, 1); + tav= RE_vertren_get_tangent(obr, v1, 1); VECADD(tav, tav, tang); - tav= RE_vertren_get_tangent(re, v3, 1); + tav= RE_vertren_get_tangent(obr, v3, 1); VECADD(tav, tav, tang); - tav= RE_vertren_get_tangent(re, v4, 1); + tav= RE_vertren_get_tangent(obr, v4, 1); VECADD(tav, tav, tang); } } -static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_tangent) +static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent) { int a; /* clear all vertex normals */ - for(a=startvert; atotvert; a++) { - VertRen *ver= RE_findOrAddVert(re, a); + for(a=0; atotvert; a++) { + VertRen *ver= RE_findOrAddVert(obr, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0f; } /* calculate cos of angles and point-masses, use as weight factor to add face normal to vertex */ - for(a=startvlak; atotvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(re, a); + for(a=0; atotvlak; a++) { + VlakRen *vlr= RE_findOrAddVlak(obr, a); if(vlr->flag & ME_SMOOTH) { VertRen *v1= vlr->v1; VertRen *v2= vlr->v2; @@ -599,13 +600,13 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_ if(do_tangent) { /* tangents still need to be calculated for flat faces too */ /* weighting removed, they are not vertexnormals */ - calc_tangent_vector(re, vlr); + calc_tangent_vector(obr, vlr); } } /* do solid faces */ - for(a=startvlak; atotvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(re, a); + for(a=0; atotvlak; a++) { + VlakRen *vlr= RE_findOrAddVlak(obr, a); if((vlr->flag & ME_SMOOTH)==0) { float *f1= vlr->v1->n; if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); @@ -621,11 +622,11 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_ } /* normalize vertex normals */ - for(a=startvert; atotvert; a++) { - VertRen *ver= RE_findOrAddVert(re, a); + for(a=0; atotvert; a++) { + VertRen *ver= RE_findOrAddVert(obr, a); Normalize(ver->n); if(do_tangent) { - float *tav= RE_vertren_get_tangent(re, ver, 0); + float *tav= RE_vertren_get_tangent(obr, ver, 0); if (tav) { /* orthonorm. */ float tdn = tav[0]*ver->n[0] + tav[1]*ver->n[1] + tav[2]*ver->n[2]; @@ -636,40 +637,20 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_ } } } - - /* vertex normal (puno) switch flags for during render */ - for(a=startvlak; atotvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(re, a); - - if((vlr->flag & R_NOPUNOFLIP)==0) { - float *v1= vlr->v1->n; - float *v2= vlr->v2->n; - float *v3= vlr->v3->n; - float *v4= vlr->v4?vlr->v4->n:NULL; - float *nor= vlr->n; - vlr->puno &= ~15; - if ((nor[0]*v1[0] + nor[1]*v1[1] + nor[2]*v1[2]) < -FLT_EPSILON10) vlr->puno= 1; - if ((nor[0]*v2[0] + nor[1]*v2[1] + nor[2]*v2[2]) < -FLT_EPSILON10) vlr->puno+= 2; - if ((nor[0]*v3[0] + nor[1]*v3[1] + nor[2]*v3[2]) < -FLT_EPSILON10) vlr->puno+= 4; - if(v4) { - if((nor[0]*v4[0] + nor[1]*v4[1] + nor[2]*v4[2]) < -FLT_EPSILON10 ) vlr->puno+= 8; - } - } - } } // NT same as calc_vertexnormals, but dont modify the existing vertex normals // only recalculate other render data. If this is at some point used for other things than fluidsim, // this could be made on option for the normal calc_vertexnormals -static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int do_tangent) +static void calc_fluidsimnormals(Render *re, ObjectRen *obr, int do_tangent) { int a; /* dont clear vertex normals here */ - // OFF for(a=startvert; atotvert; a++) { VertRen *ver= RE_findOrAddVert(re, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; } + // OFF for(a=0; atotvert; a++) { VertRen *ver= RE_findOrAddVert(obr, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; } /* calculate cos of angles and point-masses, use as weight factor to add face normal to vertex */ - for(a=startvlak; atotvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(re, a); + for(a=0; atotvlak; a++) { + VlakRen *vlr= RE_findOrAddVlak(obr, a); if(vlr->flag & ME_SMOOTH) { VertRen *v1= vlr->v1; VertRen *v2= vlr->v2; @@ -709,18 +690,18 @@ static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int d } //if(do_tangent) - // calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4); + // calc_tangent_vector(obr, vlr, fac1, fac2, fac3, fac4); } if(do_tangent) { /* tangents still need to be calculated for flat faces too */ /* weighting removed, they are not vertexnormals */ - calc_tangent_vector(re, vlr); + calc_tangent_vector(obr, vlr); } } /* do solid faces */ - for(a=startvlak; atotvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(re, a); + for(a=0; atotvlak; a++) { + VlakRen *vlr= RE_findOrAddVlak(obr, a); if((vlr->flag & ME_SMOOTH)==0) { float *f1= vlr->v1->n; if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); @@ -736,32 +717,14 @@ static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int d } /* normalize vertex normals */ - for(a=startvert; atotvert; a++) { - VertRen *ver= RE_findOrAddVert(re, a); + for(a=0; atotvert; a++) { + VertRen *ver= RE_findOrAddVert(obr, a); Normalize(ver->n); if(do_tangent) { - float *tav= RE_vertren_get_tangent(re, ver, 0); + float *tav= RE_vertren_get_tangent(obr, ver, 0); if(tav) Normalize(tav); } } - - /* vertex normal (puno) switch flags for during render */ - for(a=startvlak; atotvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(re, a); - if((vlr->flag & R_NOPUNOFLIP)==0) { - VertRen *v1= vlr->v1; - VertRen *v2= vlr->v2; - VertRen *v3= vlr->v3; - VertRen *v4= vlr->v4; - vlr->puno &= ~15; - if ((vlr->n[0]*v1->n[0]+vlr->n[1]*v1->n[1]+vlr->n[2]*v1->n[2])<0.0) vlr->puno= 1; - if ((vlr->n[0]*v2->n[0]+vlr->n[1]*v2->n[1]+vlr->n[2]*v2->n[2])<0.0) vlr->puno+= 2; - if ((vlr->n[0]*v3->n[0]+vlr->n[1]*v3->n[1]+vlr->n[2]*v3->n[2])<0.0) vlr->puno+= 4; - if(v4) { - if((vlr->n[0]*v4->n[0]+vlr->n[1]*v4->n[1]+vlr->n[2]*v4->n[2])<0.0) vlr->puno+= 8; - } - } - } } /* ------------------------------------------------------------------------- */ @@ -860,18 +823,17 @@ static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thr /* note; autosmooth happens in object space still, after applying autosmooth we rotate */ /* note2; actually, when original mesh and displist are equal sized, face normals are from original mesh */ -static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak, int degr) +static void autosmooth(Render *re, ObjectRen *obr, float mat[][4], int degr) { - ASvert *asv, *asverts, *asvertoffs; + ASvert *asv, *asverts; ASface *asf; VertRen *ver, *v1; VlakRen *vlr; float thresh; int a, b, totvert; - if(startvert==re->totvert) return; - asverts= MEM_callocN(sizeof(ASvert)*(re->totvert-startvert), "all smooth verts"); - asvertoffs= asverts-startvert; /* se we can use indices */ + if(obr->totvert==0) return; + asverts= MEM_callocN(sizeof(ASvert)*obr->totvert, "all smooth verts"); thresh= cos( M_PI*(0.5f+(float)degr)/180.0 ); @@ -879,24 +841,24 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak, /* step one: construct listbase of all vertices and pointers to faces */ - for(a=startvlak; atotvlak; a++) { - vlr= RE_findOrAddVlak(re, a); + for(a=0; atotvlak; a++) { + vlr= RE_findOrAddVlak(obr, a); /* skip wire faces */ if(vlr->v2 != vlr->v3) { - as_addvert(asvertoffs+vlr->v1->index, vlr->v1, vlr); - as_addvert(asvertoffs+vlr->v2->index, vlr->v2, vlr); - as_addvert(asvertoffs+vlr->v3->index, vlr->v3, vlr); + as_addvert(asverts+vlr->v1->index, vlr->v1, vlr); + as_addvert(asverts+vlr->v2->index, vlr->v2, vlr); + as_addvert(asverts+vlr->v3->index, vlr->v3, vlr); if(vlr->v4) - as_addvert(asvertoffs+vlr->v4->index, vlr->v4, vlr); + as_addvert(asverts+vlr->v4->index, vlr->v4, vlr); } } + totvert= obr->totvert; /* we now test all vertices, when faces have a normal too much different: they get a new vertex */ - totvert= re->totvert; - for(a=startvert, asv=asverts; atotface>1) { - ver= RE_findOrAddVert(re, a); - + ver= RE_findOrAddVert(obr, a); + asf= asv->faces.first; while(asf) { for(b=0; b<4; b++) { @@ -909,7 +871,7 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak, v1= as_findvertex(vlr, ver, asv, thresh); if(v1==NULL) { /* make a new vertex */ - v1= RE_vertren_copy(re, ver); + v1= RE_vertren_copy(obr, ver); } asf->nver[b]= v1; if(vlr->v1==ver) vlr->v1= v1; @@ -924,18 +886,18 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak, } /* free */ - for(a=0; atotvert; a++) { - ver= RE_findOrAddVert(re, a); + for(a=0; atotvert; a++) { + ver= RE_findOrAddVert(obr, a); MTC_Mat4MulVecfl(mat, ver->co); } - for(a=startvlak; atotvlak; a++) { - vlr= RE_findOrAddVlak(re, a); + for(a=0; atotvlak; a++) { + vlr= RE_findOrAddVlak(obr, a); /* skip wire faces */ if(vlr->v2 != vlr->v3) { @@ -948,14 +910,9 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak, } /* ------------------------------------------------------------------------- */ -/* End of autosmoothing: */ +/* Orco hash and Materials */ /* ------------------------------------------------------------------------- */ -/* ------------------------------------------------------------------------- */ -/* Orco hash */ -/* ------------------------------------------------------------------------- */ - - static float *get_object_orco(Render *re, Object *ob) { float *orco; @@ -995,59 +952,6 @@ static void free_mesh_orco_hash(Render *re) } } -/* ******************** END ORCO HASH ***************** */ - - -static void make_render_halos(Render *re, Object *ob, Mesh *me, int totvert, MVert *mvert, Material *ma, float *orco) -{ - HaloRen *har; - float xn, yn, zn, nor[3], view[3]; - float vec[3], hasize, mat[4][4], imat[3][3]; - int a, ok, seed= ma->seed1; - - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat3CpyMat4(imat, ob->imat); - - re->flag |= R_HALO; - - for(a=0; ahasize; - - VECCOPY(vec, mvert->co); - MTC_Mat4MulVecfl(mat, vec); - - if(ma->mode & MA_HALOPUNO) { - xn= mvert->no[0]; - yn= mvert->no[1]; - zn= mvert->no[2]; - - /* transpose ! */ - nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; - nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; - nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; - Normalize(nor); - - VECCOPY(view, vec); - Normalize(view); - - zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2]; - if(zn>=0.0) hasize= 0.0; - else hasize*= zn*zn*zn*zn; - } - - if(orco) har= RE_inithalo(re, ma, vec, NULL, orco, hasize, 0.0, seed); - else har= RE_inithalo(re, ma, vec, NULL, mvert->co, hasize, 0.0, seed); - if(har) har->lay= ob->lay; - } - if(orco) orco+= 3; - seed++; - } -} - -/* ------------------------------------------------------------------------- */ static Material *give_render_material(Render *re, Object *ob, int nr) { extern Material defmaterial; /* material.c */ @@ -1068,158 +972,12 @@ static Material *give_render_material(Render *re, Object *ob, int nr) return ma; } - - -static void render_particle_system(Render *re, Object *ob, Object *par, PartEff *paf) -{ - Particle *pa=0; - HaloRen *har=0; - Material *ma=0; - float xn, yn, zn, imat[3][3], tmat[4][4], mat[4][4], hasize, stime, ptime, ctime, vec[3], vec1[3], view[3], nor[3]; - float haloScale = 1.0; //NT scale halos - float iniAlpha = 0.0; // restore material alpha - int a, mat_nr=1, seed; - int useFluidsimParticles = 0; // FSPARTICLE - - ma= give_render_material(re, ob, paf->omat); - - if( (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) { - useFluidsimParticles = 1; - iniAlpha = ma->alpha; - } - - pa= paf->keys; - if(pa==NULL || paf->disp!=100 || useFluidsimParticles) { - build_particle_system(ob); - pa= paf->keys; - if(pa==NULL) return; - } - - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); /* this is correct, for imat texture */ - - /* enable duplicators to work */ - if(par) { - Mat4MulMat4(tmat, paf->imat, ob->obmat); - MTC_Mat4MulMat4(mat, tmat, re->viewmat); - - MTC_Mat4Invert(tmat, mat); - MTC_Mat3CpyMat4(imat, tmat); - } - else { - MTC_Mat4CpyMat4(mat, re->viewmat); - - MTC_Mat4Invert(tmat, re->viewmat); - MTC_Mat3CpyMat4(imat, tmat); - - } - - re->flag |= R_HALO; - - if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf; - else ptime= 0.0; - ctime= bsystem_time(ob, (float)re->scene->r.cfra, ptime); - seed= ma->seed1; - - for(a=0; atotpart; a++, pa+=paf->totkey, seed++) { - - /* offset time for calculating normal */ - stime= ctime; - ptime= ctime+1.0f; - if(ctime < pa->time) { - if(paf->flag & PAF_UNBORN) - ptime= pa->time+1.0f; - else - continue; - } - if(ctime > pa->time+pa->lifetime) { - if(paf->flag & PAF_DIED) - stime= pa->time+pa->lifetime-1.0f; - else - continue; - } - - /* watch it: also calculate the normal of a particle */ - if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) { - where_is_particle(paf, pa, stime, vec); - MTC_Mat4MulVecfl(mat, vec); - where_is_particle(paf, pa, ptime, vec1); - MTC_Mat4MulVecfl(mat, vec1); - } - else { - where_is_particle(paf, pa, ctime, vec); - MTC_Mat4MulVecfl(mat, vec); - } - - if(pa->mat_nr != mat_nr) { - mat_nr= pa->mat_nr; - ma= give_render_material(re, ob, mat_nr); - } - - if(ma->ipo) { - /* correction for lifetime */ - ptime= 100.0*(ctime-pa->time)/pa->lifetime; - calc_ipo(ma->ipo, ptime); - execute_ipo((ID *)ma, ma->ipo); - } - - //NT scale halos FSPARTICLE - if(useFluidsimParticles) { - // rescale to 1.0-10.0, then div by 5 afterwards, gives values in range 0.2-2.0 - double fspsize = ((double)pa->rt / 1000.0f) / 5.0 ; - haloScale = 1.0/(float)pow(fspsize, (double)ob->fluidsimSettings->particleInfSize); - ma->alpha = iniAlpha / (float)pow( fspsize, (double)ob->fluidsimSettings->particleInfAlpha); - if(ma->alpha>1.) ma->alpha = 1.; - } - - hasize= ma->hasize * haloScale; - - if(ma->mode & MA_HALOPUNO) { - xn= pa->no[0]; - yn= pa->no[1]; - zn= pa->no[2]; - - /* transpose ! */ - nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; - nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; - nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; - Normalize(nor); - - VECCOPY(view, vec); - Normalize(view); - - zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2]; - if(zn>=0.0) hasize= 0.0; - else hasize*= zn*zn*zn*zn; - } - - if(paf->stype==PAF_VECT) har= RE_inithalo(re, ma, vec, vec1, pa->co, hasize, paf->vectsize, seed); - else { - har= RE_inithalo(re, ma, vec, NULL, pa->co, hasize, 0.0, seed); - if(har && ma->mode & MA_HALO_SHADE) { - VecSubf(har->no, vec, vec1); - Normalize(har->no); - } - } - if(har) har->lay= ob->lay; - } - - /* restore material */ - for(a=1; a<=ob->totcol; a++) { - ma= give_render_material(re, ob, a); - if(ma) do_mat_ipo(ma); - } - - if(paf->disp!=100) { - MEM_freeN(paf->keys); - paf->keys= NULL; - } - - if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore... -} +/* ------------------------------------------------------------------------- */ +/* Particles */ +/* ------------------------------------------------------------------------- */ /* future thread problem... */ -static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *surfnor, +static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, float *orco, float *surfnor, float *uvco, int totuv, float *vec, float *vec1, float ctime, int first, int line, int adapt, float adapt_angle, float adapt_pix, int override_uv) { @@ -1280,13 +1038,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * /* single face line */ if(line) { - vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr= RE_findOrAddVlak(obr, obr->totvlak++); vlr->flag= flag; - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, re->totvert++); - vlr->v2= RE_findOrAddVert(re, re->totvert++); - vlr->v3= RE_findOrAddVert(re, re->totvert++); - vlr->v4= RE_findOrAddVert(re, re->totvert++); + vlr->obr= obr; + vlr->v1= RE_findOrAddVert(obr, obr->totvert++); + vlr->v2= RE_findOrAddVert(obr, obr->totvert++); + vlr->v3= RE_findOrAddVert(obr, obr->totvert++); + vlr->v4= RE_findOrAddVert(obr, obr->totvert++); VECCOPY(vlr->v1->co, vec); VecAddf(vlr->v1->co, vlr->v1->co, cross); @@ -1316,17 +1074,17 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * vlr->mat= ma; vlr->ec= ME_V2V3; - vlr->lay= ob->lay; + vlr->lay= obr->ob->lay; if(surfnor) { - float *snor= RE_vlakren_get_surfnor(re, vlr, 1); + float *snor= RE_vlakren_get_surfnor(obr, vlr, 1); VECCOPY(snor, surfnor); } if(uvco){ for(i=0; iuv[0][0]=mtf->uv[1][0]= mtf->uv[2][0]=mtf->uv[3][0]=(uvco+2*i)[0]; mtf->uv[0][1]=mtf->uv[1][1]= @@ -1334,7 +1092,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * } if(override_uv>=0){ MTFace *mtf; - mtf=RE_vlakren_get_tface(re,vlr,override_uv,NULL,0); + mtf=RE_vlakren_get_tface(obr,vlr,override_uv,NULL,0); mtf->uv[0][0]=mtf->uv[3][0]=0.0f; mtf->uv[1][0]=mtf->uv[2][0]=1.0f; @@ -1352,8 +1110,8 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * second=1; } - v1= RE_findOrAddVert(re, re->totvert++); - v2= RE_findOrAddVert(re, re->totvert++); + v1= RE_findOrAddVert(obr, obr->totvert++); + v2= RE_findOrAddVert(obr, obr->totvert++); VECCOPY(v1->co, vec); VecAddf(v1->co, v1->co, cross); @@ -1370,13 +1128,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * /* more vertices & faces to strand */ else { if(adapt==0 || second){ - vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr= RE_findOrAddVlak(obr, obr->totvlak++); vlr->flag= flag; - vlr->ob= ob; + vlr->obr= obr; vlr->v1= v1; vlr->v2= v2; - vlr->v3= RE_findOrAddVert(re, re->totvert++); - vlr->v4= RE_findOrAddVert(re, re->totvert++); + vlr->v3= RE_findOrAddVert(obr, obr->totvert++); + vlr->v4= RE_findOrAddVert(obr, obr->totvert++); v1= vlr->v4; // cycle v2= vlr->v3; // cycle @@ -1400,13 +1158,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * dy= re->winy*dvec[1]*re->winmat[1][1]/w; w= sqrt(dx*dx + dy*dy); if(Inpf(anor,nor)adapt_pix){ - vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr= RE_findOrAddVlak(obr, obr->totvlak++); vlr->flag= flag; - vlr->ob= ob; + vlr->obr= obr; vlr->v1= v1; vlr->v2= v2; - vlr->v3= RE_findOrAddVert(re, re->totvert++); - vlr->v4= RE_findOrAddVert(re, re->totvert++); + vlr->v3= RE_findOrAddVert(obr, obr->totvert++); + vlr->v4= RE_findOrAddVert(obr, obr->totvert++); v1= vlr->v4; // cycle v2= vlr->v3; // cycle @@ -1415,7 +1173,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * VECCOPY(avec,vec); } else{ - vlr= RE_findOrAddVlak(re, re->totvlak-1); + vlr= RE_findOrAddVlak(obr, obr->totvlak-1); } } @@ -1435,17 +1193,17 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * vlr->mat= ma; vlr->ec= ME_V2V3; - vlr->lay= ob->lay; + vlr->lay= obr->ob->lay; if(surfnor) { - float *snor= RE_vlakren_get_surfnor(re, vlr, 1); + float *snor= RE_vlakren_get_surfnor(obr, vlr, 1); VECCOPY(snor, surfnor); } if(uvco){ for(i=0; iuv[0][0]=mtf->uv[1][0]= mtf->uv[2][0]=mtf->uv[3][0]=(uvco+2*i)[0]; mtf->uv[0][1]=mtf->uv[1][1]= @@ -1453,7 +1211,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * } if(override_uv>=0){ MTFace *mtf; - mtf=RE_vlakren_get_tface(re,vlr,override_uv,NULL,0); + mtf=RE_vlakren_get_tface(obr,vlr,override_uv,NULL,0); mtf->uv[0][0]=mtf->uv[3][0]=0.0f; mtf->uv[1][0]=mtf->uv[2][0]=1.0f; @@ -1465,16 +1223,16 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * } } -static void static_particle_wire(Render *re, Object *ob, Material *ma, float *vec, float *vec1, int first, int line) +static void static_particle_wire(ObjectRen *obr, Material *ma, float *vec, float *vec1, int first, int line) { VlakRen *vlr; static VertRen *v1; if(line) { - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, re->totvert++); - vlr->v2= RE_findOrAddVert(re, re->totvert++); + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr= obr; + vlr->v1= RE_findOrAddVert(obr, obr->totvert++); + vlr->v2= RE_findOrAddVert(obr, obr->totvert++); vlr->v3= vlr->v2; vlr->v4= NULL; @@ -1488,18 +1246,18 @@ static void static_particle_wire(Render *re, Object *ob, Material *ma, float *ve vlr->mat= ma; vlr->ec= ME_V1V2; - vlr->lay= ob->lay; + vlr->lay= obr->ob->lay; } else if(first) { - v1= RE_findOrAddVert(re, re->totvert++); + v1= RE_findOrAddVert(obr, obr->totvert++); VECCOPY(v1->co, vec); } else { - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr= obr; vlr->v1= v1; - vlr->v2= RE_findOrAddVert(re, re->totvert++); + vlr->v2= RE_findOrAddVert(obr, obr->totvert++); vlr->v3= vlr->v2; vlr->v4= NULL; @@ -1512,11 +1270,11 @@ static void static_particle_wire(Render *re, Object *ob, Material *ma, float *ve vlr->mat= ma; vlr->ec= ME_V1V2; - vlr->lay= ob->lay; + vlr->lay= obr->ob->lay; } } -static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ob, float *vec, float *vel, float size, float tilt, short align, +static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, Object *bb_ob, float *vec, float *vel, float size, float tilt, short align, int lock, int p, int totpart, short uv_split, short anim, short split_offset, float random, float pa_time, float offset[2], int uv[3]) { VlakRen *vlr; @@ -1528,12 +1286,12 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ if(aligntotvlak++); - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, re->totvert++); - vlr->v2= RE_findOrAddVert(re, re->totvert++); - vlr->v3= RE_findOrAddVert(re, re->totvert++); - vlr->v4= RE_findOrAddVert(re, re->totvert++); + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr= obr; + vlr->v1= RE_findOrAddVert(obr, obr->totvert++); + vlr->v2= RE_findOrAddVert(obr, obr->totvert++); + vlr->v3= RE_findOrAddVert(obr, obr->totvert++); + vlr->v4= RE_findOrAddVert(obr, obr->totvert++); if(lock && align==PART_BB_VIEW){ VECCOPY(xvec,bb_ob->obmat[0]); @@ -1612,7 +1370,7 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ vlr->mat= ma; vlr->ec= ME_V2V3; - vlr->lay= ob->lay; + vlr->lay= obr->ob->lay; if(uv_split>1){ uvdx=uvdy=1.0f/(float)uv_split; @@ -1665,7 +1423,7 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ /* normal UVs */ if(uv[0]>=0){ - mtf=RE_vlakren_get_tface(re,vlr,uv[0],NULL,1); + mtf=RE_vlakren_get_tface(obr,vlr,uv[0],NULL,1); mtf->uv[0][0]=1.0f; mtf->uv[0][1]=1.0f; mtf->uv[1][0]=0.0f; @@ -1678,14 +1436,14 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ /* time-index UVs */ if(uv[1]>=0){ - mtf=RE_vlakren_get_tface(re,vlr,uv[1],NULL,1); + mtf=RE_vlakren_get_tface(obr,vlr,uv[1],NULL,1); mtf->uv[0][0]=mtf->uv[1][0]=mtf->uv[2][0]=mtf->uv[3][0]=pa_time; mtf->uv[0][1]=mtf->uv[1][1]=mtf->uv[2][1]=mtf->uv[3][1]=(float)p/(float)totpart; } /* split UVs */ if(uv_split>1 && uv[2]>=0){ - mtf=RE_vlakren_get_tface(re,vlr,uv[2],NULL,1); + mtf=RE_vlakren_get_tface(obr,vlr,uv[2],NULL,1); mtf->uv[0][0]=uvx+uvdx; mtf->uv[0][1]=uvy+uvdy; mtf->uv[1][0]=uvx; @@ -1696,28 +1454,29 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ mtf->uv[3][1]=uvy; } } -static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Material *ma, int path, int first, int line, +static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, int path, int first, int line, float time, float *loc, float *loc1, float *orco, float *surfnor, int totuv, float *uvco, float size, int seed, int override_uv, int adapt, float adapt_angle, float adapt_pix) { HaloRen *har=0; if(path){ if(ma->mode&MA_WIRE) - static_particle_wire(re, ob, ma, loc, loc1, first, line); + static_particle_wire(obr, ma, loc, loc1, first, line); else if(ma->mode & MA_HALO){ - har= RE_inithalo_particle(re, dm, ma, loc, loc1, orco, uvco, size, 1.0, seed); - if(har) har->lay= ob->lay; + har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, orco, uvco, size, 1.0, seed); + if(har) har->lay= obr->ob->lay; } else - static_particle_strand(re, ob, ma, orco, surfnor, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv); + static_particle_strand(re, obr, ma, orco, surfnor, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv); } else{ - har= RE_inithalo_particle(re, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed); - if(har) har->lay= ob->lay; + har= RE_inithalo_particle(re, obr, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed); + if(har) har->lay= obr->ob->lay; } } -static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *psys) +static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys) { + Object *ob= obr->ob; Object *tob=0, *bb_ob=re->scene->camera; Material *ma=0; CustomDataLayer *layer; @@ -1737,7 +1496,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random; - int i, a, k, max_k=0, totpart, totvlako, totverto, totuv=0, override_uv=-1; + int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1; int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}; char **uv_name=0; @@ -1749,9 +1508,9 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps part=psys->part; pars=psys->particles; - if(part==NULL || pars==NULL || (psys->flag & PSYS_ENABLED)==0) + if(part==NULL || pars==NULL || !psys_check_enabled(ob, psys)) return 0; - + if(part->draw_as==PART_DRAW_OB || part->draw_as==PART_DRAW_GR || part->draw_as==PART_DRAW_NOT) return 1; @@ -1785,7 +1544,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps execute_ipo((ID *)ma, ma->ipo); } - RE_vlakren_set_customdata_names(re, &psmd->dm->faceData); + RE_set_customdata_names(obr, &psmd->dm->faceData); totuv=CustomData_number_of_layers(&psmd->dm->faceData,CD_MTFACE); if(ma->texco & TEXCO_UV && totuv) { @@ -1845,9 +1604,6 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps Mat3CpyMat4(nmat, ob->imat); Mat3Transp(nmat); - totvlako= re->totvlak; - totverto= re->totvert; - totpart=psys->totpart; mesh_get_texspace(ob->data, loc_tex, NULL, size_tex); @@ -1877,7 +1633,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps } if(re->r.renderer==R_INTERN && part->draw&PART_DRAW_REN_STRAND) { - strandbuf= RE_addStrandBuffer(re, ob, (totpart+totchild)*(path_nbr+1)); + strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1)); strandbuf->ma= ma; strandbuf->lay= ob->lay; Mat4CpyMat4(strandbuf->winmat, re->winmat); @@ -1944,15 +1700,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){ layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE); for(i=0; idm->getFaceData(psmd->dm,pa->num,CD_MFACE); mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i); mtface+=pa->num; - n= vlakren_customdata_layer_num(i, layer->active); - - psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*n); + psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*i); } } @@ -2000,15 +1753,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ for(i=0; ichildtype==PART_CHILD_FACES){ - int n; MFace *mface=psmd->dm->getFaceData(psmd->dm,cpa->num,CD_MFACE); mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i); mtface+=cpa->num; - n= vlakren_customdata_layer_num(i, layer->active); - - psys_interpolate_uvs(mtface,mface->v4,cpa->fuv,uvco+2*n); + psys_interpolate_uvs(mtface,mface->v4,cpa->fuv,uvco+2*i); } else{ uvco[2*i]=uvco[2*i+1]=0.0f; @@ -2018,15 +1768,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps else if(ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){ for(i=0; iparticles+cpa->parent; - int n; MFace *mface=psmd->dm->getFaceData(psmd->dm,parent->num,CD_MFACE); mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i); mtface+=parent->num; - n= vlakren_customdata_layer_num(i, layer->active); - - psys_interpolate_uvs(mtface,mface->v4,parent->fuv,uvco+2*n); + psys_interpolate_uvs(mtface,mface->v4,parent->fuv,uvco+2*i); } } } @@ -2053,20 +1800,20 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps /* strand render setup */ if(strandbuf) { - strand= RE_findOrAddStrand(re, re->totstrand++); + strand= RE_findOrAddStrand(obr, obr->totstrand++); strand->buffer= strandbuf; strand->vert= svert; VECCOPY(strand->orco, orco); if(surfnor) { - float *snor= RE_strandren_get_surfnor(re, strand, 1); + float *snor= RE_strandren_get_surfnor(obr, strand, 1); VECCOPY(snor, surfnor); } if(uvco){ for(i=0; idraw_line[0]); VECADDFAC(loc1,loc,vel,part->draw_line[1]); - render_new_particle(re,ob,psmd->dm,ma,1,0,1,0.0f,loc0,loc1, + render_new_particle(re,obr,psmd->dm,ma,1,0,1,0.0f,loc0,loc1, orco,surfnor,totuv,uvco,hasize,seed,override_uv,0,0,0); } else if(part->draw_as==PART_DRAW_BB) { VECCOPY(vel,state.vel); //MTC_Mat4Mul3Vecfl(re->viewmat,vel); - particle_billboard(re,ob,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt), + particle_billboard(re,obr,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt), part->bb_align,part->draw&PART_DRAW_BB_LOCK, a,totpart+totchild,part->bb_uv_split,part->bb_anim,part->bb_split_offset,random,pa_time,part->bb_offset,uv); } @@ -2141,13 +1888,13 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps if(k==1){ VECSUB(loc0,loc1,loc); VECADD(loc0,loc1,loc0); - render_new_particle(re,ob,psmd->dm,ma,path,1,0,0.0f,loc1,loc0, + render_new_particle(re,obr,psmd->dm,ma,path,1,0,0.0f,loc1,loc0, orco,surfnor,totuv,uvco,hasize,seed,override_uv, adapt,adapt_angle,adapt_pix); } if(path_nbr==0 || k) - render_new_particle(re,ob,psmd->dm,ma,path,0,0,time,loc,loc1, + render_new_particle(re,obr,psmd->dm,ma,path,0,0,time,loc,loc1, orco,surfnor,totuv,uvco,hasize,seed,override_uv, adapt,adapt_angle,adapt_pix); @@ -2187,249 +1934,278 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps } if(path && (ma->mode_l & MA_TANGENT_STR)==0) - calc_vertexnormals(re, totverto, totvlako, 0); + calc_vertexnormals(re, obr, 0); return 1; } -static void render_static_particle_system(Render *re, Object *ob, PartEff *paf) +/* ------------------------------------------------------------------------- */ +/* Halo's */ +/* ------------------------------------------------------------------------- */ + +static void make_render_halos(Render *re, ObjectRen *obr, Mesh *me, int totvert, MVert *mvert, Material *ma, float *orco) { - Particle *pa=0; - HaloRen *har=0; - Material *ma=0; - VertRen *v1= NULL; - VlakRen *vlr; - float xn, yn, zn, imat[3][3], mat[4][4], hasize; - float mtime, ptime, ctime, vec[3], vec1[3], view[3], nor[3]; - float *orco= NULL, loc_tex[3], size_tex[3]; - int a, mat_nr=1, seed, totvlako, totverto, first; - - pa= paf->keys; - if(pa==NULL || (paf->flag & PAF_ANIMATED) || paf->disp!=100) { - build_particle_system(ob); - pa= paf->keys; - if(pa==NULL) return; - } - - totvlako= re->totvlak; - totverto= re->totvert; - - ma= give_render_material(re, ob, paf->omat); - if(ma->mode & MA_HALO) - re->flag |= R_HALO; + Object *ob= obr->ob; + HaloRen *har; + float xn, yn, zn, nor[3], view[3]; + float vec[3], hasize, mat[4][4], imat[3][3]; + int a, ok, seed= ma->seed1; MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); /* need to be that way, for imat texture */ - MTC_Mat3CpyMat4(imat, ob->imat); - - /* orcos */ - if(!(ma->mode & (MA_HALO|MA_WIRE))) { - orco= MEM_mallocN(3*sizeof(float)*paf->totpart, "static particle orcos"); - set_object_orco(re, paf, orco); - } - - mesh_get_texspace(ob->data, loc_tex, NULL, size_tex); - - if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf; - else ptime= 0.0; - ctime= bsystem_time(ob, (float)re->scene->r.cfra, ptime); - seed= ma->seed1; - for(a=0; atotpart; a++, pa+=paf->totkey) { - - where_is_particle(paf, pa, pa->time, vec1); - if(orco) { - orco[0] = (vec1[0]-loc_tex[0])/size_tex[0]; - orco[1] = (vec1[1]-loc_tex[1])/size_tex[1]; - orco[2] = (vec1[2]-loc_tex[2])/size_tex[2]; + re->flag |= R_HALO; + + for(a=0; ahasize; + + VECCOPY(vec, mvert->co); + MTC_Mat4MulVecfl(mat, vec); + + if(ma->mode & MA_HALOPUNO) { + xn= mvert->no[0]; + yn= mvert->no[1]; + zn= mvert->no[2]; + + /* transpose ! */ + nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalize(nor); + + VECCOPY(view, vec); + Normalize(view); + + zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2]; + if(zn>=0.0) hasize= 0.0; + else hasize*= zn*zn*zn*zn; + } + + if(orco) har= RE_inithalo(re, obr, ma, vec, NULL, orco, hasize, 0.0, seed); + else har= RE_inithalo(re, obr, ma, vec, NULL, mvert->co, hasize, 0.0, seed); + if(har) har->lay= ob->lay; } - MTC_Mat4MulVecfl(mat, vec1); - mtime= pa->time+pa->lifetime+paf->staticstep-1; - - first= 1; - for(ctime= pa->time; ctimestaticstep) { - - /* make sure hair grows until the end.. */ - if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime; - - /* watch it: also calc the normal of a particle */ - if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) { - where_is_particle(paf, pa, ctime+1.0, vec); - MTC_Mat4MulVecfl(mat, vec); - } - else { - where_is_particle(paf, pa, ctime, vec); - MTC_Mat4MulVecfl(mat, vec); - } - - if(pa->mat_nr != mat_nr) { - mat_nr= pa->mat_nr; - ma= give_render_material(re, ob, mat_nr); - } - - /* wires */ - if(ma->mode & MA_WIRE) { - if(ctime == pa->time) { - v1= RE_findOrAddVert(re, re->totvert++); - VECCOPY(v1->co, vec); - } - else { - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= v1; - vlr->v2= RE_findOrAddVert(re, re->totvert++); - vlr->v3= vlr->v2; - vlr->v4= NULL; - - v1= vlr->v2; // cycle - VECCOPY(v1->co, vec); - - VecSubf(vlr->n, vec, vec1); - Normalize(vlr->n); - VECCOPY(v1->n, vlr->n); - - vlr->mat= ma; - vlr->ec= ME_V1V2; - vlr->lay= ob->lay; - } - } - else { - if(ma->ipo) { - /* correction for lifetime */ - ptime= 100.0*(ctime-pa->time)/pa->lifetime; - calc_ipo(ma->ipo, ptime); - execute_ipo((ID *)ma, ma->ipo); - } - - if(ma->mode & MA_HALO) { - hasize= ma->hasize; - - if(ma->mode & MA_HALOPUNO) { - xn= pa->no[0]; - yn= pa->no[1]; - zn= pa->no[2]; - - /* transpose ! */ - nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; - nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; - nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; - Normalize(nor); - - VECCOPY(view, vec); - Normalize(view); - - zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2]; - if(zn>=0.0) hasize= 0.0; - else hasize*= zn*zn*zn*zn; - } - - if(paf->stype==PAF_VECT) har= RE_inithalo(re, ma, vec, vec1, pa->co, hasize, paf->vectsize, seed); - else { - har= RE_inithalo(re, ma, vec, NULL, pa->co, hasize, 0.0, seed); - if(har && (ma->mode & MA_HALO_SHADE)) { - VecSubf(har->no, vec, vec1); - Normalize(har->no); - har->lay= ob->lay; - } - } - if(har) har->lay= ob->lay; - } - else { /* generate pixel sized hair strand */ - float strandco= 1.0f; - - /* last strand, texco to end */ - if(ctime + paf->staticstep < mtime) - strandco= (ctime-pa->time)/(mtime-pa->time); - - static_particle_strand(re, ob, ma, orco, 0, 0, 0, vec, vec1, strandco, first, 0,0,0,0,-1); - } - } - - VECCOPY(vec1, vec); - first= 0; - } - + if(orco) orco+= 3; seed++; - if(orco) orco+=3; } - - if(paf->disp!=100) { - MEM_freeN(paf->keys); - paf->keys= NULL; - } - - if((ma->mode & MA_TANGENT_STR)==0) - calc_vertexnormals(re, totverto, totvlako, 0); } - -/* ------------------------------------------------------------------------- */ - static int verghalo(const void *a1, const void *a2) { - const struct halosort *x1=a1, *x2=a2; + const HaloRen *har1= a1, *har2= a2; - if( x1->z < x2->z ) return 1; - else if( x1->z > x2->z) return -1; + if(har1->zs < har2->zs) return 1; + else if(har1->zs > har2->zs) return -1; return 0; } -/* ------------------------------------------------------------------------- */ -static void sort_halos(Render *re) +static void sort_halos(Render *re, int totsort) { - struct halosort *hablock, *haso; - HaloRen *har = NULL, **bloha; + ObjectRen *obr; + HaloRen *har= NULL, **haso; int a; if(re->tothalo==0) return; - /* make datablock with halo pointers, sort */ - haso= hablock= MEM_mallocN(sizeof(struct halosort)*re->tothalo, "hablock"); + re->sortedhalos= MEM_callocN(sizeof(HaloRen*)*re->tothalo, "sorthalos"); + haso= re->sortedhalos; - for(a=0; atothalo; a++) { - if((a & 255)==0) har= re->bloha[a>>8]; - else har++; - haso->har= har; - haso->z= har->zs; - haso++; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atothalo; a++) { + if((a & 255)==0) har= obr->bloha[a>>8]; + else har++; + + *(haso++)= har; + } } - qsort(hablock, re->tothalo, sizeof(struct halosort), verghalo); - - /* re-assamble re->bloha */ - - bloha= re->bloha; - re->bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(re->blohalen),"Bloha"); - - haso= hablock; - for(a=0; atothalo; a++) { - har= RE_findOrAddHalo(re, a); - *har= *(haso->har); - - haso++; - } - - /* free */ - a= 0; - while(bloha[a]) { - MEM_freeN(bloha[a]); - a++; - } - MEM_freeN(bloha); - MEM_freeN(hablock); - + qsort(re->sortedhalos, totsort, sizeof(HaloRen*), verghalo); } /* ------------------------------------------------------------------------- */ -static void init_render_mball(Render *re, Object *ob) +/* Displacement Mapping */ +/* ------------------------------------------------------------------------- */ + +static short test_for_displace(Render *re, Object *ob) { + /* return 1 when this object uses displacement textures. */ + Material *ma; + int i; + + for (i=1; i<=ob->totcol; i++) { + ma=give_render_material(re, ob, i); + /* ma->mapto is ORed total of all mapto channels */ + if(ma && (ma->mapto & MAP_DISPLACE)) return 1; + } + return 0; +} + +static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, VertRen *vr, int vindex, float *scale) +{ + MTFace *tface; + short texco= shi->mat->texco; + float sample=0; + char *name; + int i; + + /* shi->co is current render coord, just make sure at least some vector is here */ + VECCOPY(shi->co, vr->co); + /* vertex normal is used for textures type 'col' and 'var' */ + VECCOPY(shi->vn, vr->n); + + if (texco & TEXCO_UV) { + shi->totuv= 0; + shi->actuv= obr->actmtface; + + for (i=0; (tface=RE_vlakren_get_tface(obr, shi->vlr, i, &name, 0)); i++) { + ShadeInputUV *suv= &shi->uv[i]; + + /* shi.uv needs scale correction from tface uv */ + suv->uv[0]= 2*tface->uv[vindex][0]-1.0f; + suv->uv[1]= 2*tface->uv[vindex][1]-1.0f; + suv->uv[2]= 0.0f; + suv->name= name; + shi->totuv++; + } + } + + /* set all rendercoords, 'texco' is an ORed value for all textures needed */ + if ((texco & TEXCO_ORCO) && (vr->orco)) { + VECCOPY(shi->lo, vr->orco); + } + if (texco & TEXCO_STICKY) { + float *sticky= RE_vertren_get_sticky(obr, vr, 0); + if(sticky) { + shi->sticky[0]= sticky[0]; + shi->sticky[1]= sticky[1]; + shi->sticky[2]= 0.0f; + } + } + if (texco & TEXCO_GLOB) { + VECCOPY(shi->gl, shi->co); + MTC_Mat4MulVecfl(re->viewinv, shi->gl); + } + if (texco & TEXCO_NORM) { + VECCOPY(shi->orn, shi->vn); + } + if(texco & TEXCO_REFL) { + /* not (yet?) */ + } + + shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0; + + do_material_tex(shi); + + //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2], + //vr->co[0], vr->co[1], vr->co[2]); + + /* 0.5 could become button once? */ + vr->co[0] += shi->displace[0] * scale[0] ; + vr->co[1] += shi->displace[1] * scale[1] ; + vr->co[2] += shi->displace[2] * scale[2] ; + + //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]); + + /* we just don't do this vertex again, bad luck for other face using same vertex with + different material... */ + vr->flag |= 1; + + /* Pass sample back so displace_face can decide which way to split the quad */ + sample = shi->displace[0]*shi->displace[0]; + sample += shi->displace[1]*shi->displace[1]; + sample += shi->displace[2]*shi->displace[2]; + + vr->accum=sample; + /* Should be sqrt(sample), but I'm only looking for "bigger". Save the cycles. */ + return; +} + +static void displace_render_face(Render *re, VlakRen *vlr, float *scale) +{ + ShadeInput shi; + + /* set up shadeinput struct for multitex() */ + shi.osatex= 0; /* signal not to use dx[] and dy[] texture AA vectors */ + shi.vlr= vlr; /* current render face */ + shi.mat= vlr->mat; /* current input material */ + + /* Displace the verts, flag is set when done */ + if (!vlr->v1->flag) + displace_render_vert(re, vlr->obr, &shi, vlr->v1,0, scale); + + if (!vlr->v2->flag) + displace_render_vert(re, vlr->obr, &shi, vlr->v2, 1, scale); + + if (!vlr->v3->flag) + displace_render_vert(re, vlr->obr, &shi, vlr->v3, 2, scale); + + if (vlr->v4) { + if (!vlr->v4->flag) + displace_render_vert(re, vlr->obr, &shi, vlr->v4, 3, scale); + + /* closest in displace value. This will help smooth edges. */ + if ( fabs(vlr->v1->accum - vlr->v3->accum) > fabs(vlr->v2->accum - vlr->v4->accum)) + vlr->flag |= R_DIVIDE_24; + else vlr->flag &= ~R_DIVIDE_24; + } + + /* Recalculate the face normal - if flipped before, flip now */ + if(vlr->v4) { + CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); + } + else { + CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); + } +} + +static void do_displacement(Render *re, ObjectRen *obr) +{ + VertRen *vr; + VlakRen *vlr; +// float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30}; + float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn + int i; //, texflag=0; + Object *obt; + + /* Object Size with parenting */ + obt=obr->ob; + while(obt){ + VecAddf(temp, obt->size, obt->dsize); + scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2]; + obt=obt->parent; + } + + /* Clear all flags */ + for(i=0; itotvert; i++){ + vr= RE_findOrAddVert(obr, i); + vr->flag= 0; + } + + for(i=0; itotvlak; i++){ + vlr=RE_findOrAddVlak(obr, i); + displace_render_face(re, vlr, scale); + } + + /* Recalc vertex normals */ + calc_vertexnormals(re, obr, 0); +} + +/* ------------------------------------------------------------------------- */ +/* Metaball */ +/* ------------------------------------------------------------------------- */ + +static void init_render_mball(Render *re, ObjectRen *obr) +{ + Object *ob= obr->ob; DispList *dl; VertRen *ver; VlakRen *vlr, *vlr1; Material *ma; float *data, *nors, mat[4][4], imat[3][3], xn, yn, zn; - int a, need_orco, startvert, *index; + int a, need_orco, *index; if (ob!=find_basis_mball(ob)) return; @@ -2449,19 +2225,19 @@ static void init_render_mball(Render *re, Object *ob) dl= ob->disp.first; if(dl==0) return; - startvert= re->totvert; data= dl->verts; nors= dl->nors; for(a=0; anr; a++, data+=3, nors+=3) { - ver= RE_findOrAddVert(re, re->totvert++); + ver= RE_findOrAddVert(obr, obr->totvert++); VECCOPY(ver->co, data); MTC_Mat4MulVecfl(mat, ver->co); - xn= nors[0]; - yn= nors[1]; - zn= nors[2]; + /* render normals are inverted */ + xn= -nors[0]; + yn= -nors[1]; + zn= -nors[2]; /* transpose ! */ ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; @@ -2476,11 +2252,11 @@ static void init_render_mball(Render *re, Object *ob) index= dl->index; for(a=0; aparts; a++, index+=4) { - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, startvert+index[0]); - vlr->v2= RE_findOrAddVert(re, startvert+index[1]); - vlr->v3= RE_findOrAddVert(re, startvert+index[2]); + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr= obr; + vlr->v1= RE_findOrAddVert(obr, index[0]); + vlr->v2= RE_findOrAddVert(obr, index[1]); + vlr->v3= RE_findOrAddVert(obr, index[2]); vlr->v4= 0; if(ob->transflag & OB_NEG_SCALE) @@ -2495,10 +2271,10 @@ static void init_render_mball(Render *re, Object *ob) /* mball -too bad- always has triangles, because quads can be non-planar */ if(index[3] && index[3]!=index[2]) { - vlr1= RE_findOrAddVlak(re, re->totvlak++); + vlr1= RE_findOrAddVlak(obr, obr->totvlak++); *vlr1= *vlr; vlr1->v2= vlr1->v3; - vlr1->v3= RE_findOrAddVert(re, startvert+index[3]); + vlr1->v3= RE_findOrAddVert(obr, index[3]); if(ob->transflag & OB_NEG_SCALE) CalcNormFloat(vlr1->v1->co, vlr1->v2->co, vlr1->v3->co, vlr1->n); else @@ -2518,17 +2294,450 @@ static void init_render_mball(Render *re, Object *ob) /* this enforces remake for real, orco displist is small (in scale) */ ob->recalc |= OB_RECALC_DATA; } -/* ------------------------------------------------------------------------- */ -/* convert */ -static int vlakren_customdata_layer_num(int n, int active) +/* ------------------------------------------------------------------------- */ +/* Surfaces and Curves */ +/* ------------------------------------------------------------------------- */ + +/* returns amount of vertices added for orco */ +static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, float *orco, float mat[4][4]) { - /* make the active layer the first */ - if (n == active) return 0; - else if (n < active) return n+1; - else return n; + Object *ob= obr->ob; + VertRen *v1, *v2, *v3, *v4, *ver; + VlakRen *vlr, *vlr1, *vlr2, *vlr3; + Curve *cu= ob->data; + float *data, n1[3], flen; + int u, v, orcoret= 0; + int p1, p2, p3, p4, a; + int sizeu, nsizeu, sizev, nsizev; + int startvert, startvlak; + + startvert= obr->totvert; + nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr; + + data= dl->verts; + for (u = 0; u < sizeu; u++) { + v1 = RE_findOrAddVert(obr, obr->totvert++); /* save this for possible V wrapping */ + VECCOPY(v1->co, data); data += 3; + if(orco) { + v1->orco= orco; orco+= 3; orcoret++; + } + MTC_Mat4MulVecfl(mat, v1->co); + + for (v = 1; v < sizev; v++) { + ver= RE_findOrAddVert(obr, obr->totvert++); + VECCOPY(ver->co, data); data += 3; + if(orco) { + ver->orco= orco; orco+= 3; orcoret++; + } + MTC_Mat4MulVecfl(mat, ver->co); + } + /* if V-cyclic, add extra vertices at end of the row */ + if (dl->flag & DL_CYCL_U) { + ver= RE_findOrAddVert(obr, obr->totvert++); + VECCOPY(ver->co, v1->co); + if(orco) { + ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0); + } + } + } + + /* Done before next loop to get corner vert */ + if (dl->flag & DL_CYCL_U) nsizev++; + if (dl->flag & DL_CYCL_V) nsizeu++; + + /* if U cyclic, add extra row at end of column */ + if (dl->flag & DL_CYCL_V) { + for (v = 0; v < nsizev; v++) { + v1= RE_findOrAddVert(obr, startvert + v); + ver= RE_findOrAddVert(obr, obr->totvert++); + VECCOPY(ver->co, v1->co); + if(orco) { + ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v); + } + } + } + + sizeu = nsizeu; + sizev = nsizev; + + startvlak= obr->totvlak; + + for(u = 0; u < sizeu - 1; u++) { + p1 = startvert + u * sizev; /* walk through face list */ + p2 = p1 + 1; + p3 = p2 + sizev; + p4 = p3 - 1; + + for(v = 0; v < sizev - 1; v++) { + v1= RE_findOrAddVert(obr, p1); + v2= RE_findOrAddVert(obr, p2); + v3= RE_findOrAddVert(obr, p3); + v4= RE_findOrAddVert(obr, p4); + + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr= obr; + vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4; + + flen= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1); + VECCOPY(vlr->n, n1); + + vlr->lay= ob->lay; + vlr->mat= matar[ dl->col]; + vlr->ec= ME_V1V2+ME_V2V3; + vlr->flag= dl->rt; + if( (cu->flag & CU_NOPUNOFLIP) ) { + vlr->flag |= R_NOPUNOFLIP; + } + + VecAddf(v1->n, v1->n, n1); + VecAddf(v2->n, v2->n, n1); + VecAddf(v3->n, v3->n, n1); + VecAddf(v4->n, v4->n, n1); + + p1++; p2++; p3++; p4++; + } + } + /* fix normals for U resp. V cyclic faces */ + sizeu--; sizev--; /* dec size for face array */ + if (dl->flag & DL_CYCL_V) { + + for (v = 0; v < sizev; v++) + { + /* optimize! :*/ + vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, v)); + vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, v)); + VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n); + VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n); + VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n); + VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n); + } + } + if (dl->flag & DL_CYCL_U) { + + for (u = 0; u < sizeu; u++) + { + /* optimize! :*/ + vlr= RE_findOrAddVlak(obr, UVTOINDEX(u, 0)); + vlr1= RE_findOrAddVlak(obr, UVTOINDEX(u, sizev-1)); + VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n); + VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n); + VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n); + VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n); + } + } + /* last vertex is an extra case: + + ^ ()----()----()----() + | | | || | + u | |(0,n)||(0,0)| + | | || | + ()====()====[]====() + | | || | + | |(m,n)||(m,0)| + | | || | + ()----()----()----() + v -> + + vertex [] is no longer shared, therefore distribute + normals of the surrounding faces to all of the duplicates of [] + */ + + if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)) + { + vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */ + vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0,0)); /* (0,0) */ + VecAddf(n1, vlr->n, vlr1->n); + vlr2= RE_findOrAddVlak(obr, UVTOINDEX(0, sizev-1)); /* (0,n) */ + VecAddf(n1, n1, vlr2->n); + vlr3= RE_findOrAddVlak(obr, UVTOINDEX(sizeu-1, 0)); /* (m,0) */ + VecAddf(n1, n1, vlr3->n); + VECCOPY(vlr->v3->n, n1); + VECCOPY(vlr1->v1->n, n1); + VECCOPY(vlr2->v2->n, n1); + VECCOPY(vlr3->v4->n, n1); + } + for(a = startvert; a < obr->totvert; a++) { + ver= RE_findOrAddVert(obr, a); + Normalize(ver->n); + } + + + return orcoret; } +static void init_render_surf(Render *re, ObjectRen *obr) +{ + Object *ob= obr->ob; + Nurb *nu=0; + Curve *cu; + ListBase displist; + DispList *dl; + Material *matar[32]; + float *orco=NULL, *orcobase=NULL, mat[4][4]; + int a, need_orco=0; + + cu= ob->data; + nu= cu->nurb.first; + if(nu==0) return; + + MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); + MTC_Mat4Invert(ob->imat, mat); + + /* material array */ + memset(matar, 0, 4*32); + matar[0]= give_render_material(re, ob, 0); + for(a=0; atotcol; a++) { + matar[a]= give_render_material(re, ob, a+1); + if(matar[a] && matar[a]->texco & TEXCO_ORCO) { + need_orco= 1; + } + } + + if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1; + + if(need_orco) orcobase= orco= get_object_orco(re, ob); + + displist.first= displist.last= 0; + makeDispListSurf(ob, &displist, 1); + + dl= displist.first; + /* walk along displaylist and create rendervertices/-faces */ + while(dl) { + /* watch out: u ^= y, v ^= x !! */ + if(dl->type==DL_SURF) { + orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); + } + + dl= dl->next; + } + freedisplist(&displist); +} + +static void init_render_curve(Render *re, ObjectRen *obr, int only_verts) +{ + Object *ob= obr->ob; + Curve *cu; + VertRen *ver; + VlakRen *vlr; + DispList *dl; + ListBase olddl={NULL, NULL}; + Material *matar[32]; + float len, *data, *fp, *orco=NULL, *orcobase= NULL; + float n[3], mat[4][4]; + int nr, startvert, startvlak, a, b; + int frontside, need_orco=0; + + cu= ob->data; + if(cu->nurb.first==NULL) return; + + /* no modifier call here, is in makedisp */ + + if(cu->resolu_ren) + SWAP(ListBase, olddl, cu->disp); + + /* test displist */ + if(cu->disp.first==NULL) + makeDispListCurveTypes(ob, 0); + dl= cu->disp.first; + if(cu->disp.first==NULL) return; + + MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); + MTC_Mat4Invert(ob->imat, mat); + + /* material array */ + memset(matar, 0, 4*32); + matar[0]= give_render_material(re, ob, 0); + for(a=0; atotcol; a++) { + matar[a]= give_render_material(re, ob, a+1); + if(matar[a]->texco & TEXCO_ORCO) { + need_orco= 1; + } + } + + if(need_orco) orcobase=orco= get_object_orco(re, ob); + + dl= cu->disp.first; + while(dl) { + if(dl->type==DL_INDEX3) { + int *index; + + startvert= obr->totvert; + data= dl->verts; + + n[0]= ob->imat[0][2]; + n[1]= ob->imat[1][2]; + n[2]= ob->imat[2][2]; + Normalize(n); + + for(a=0; anr; a++, data+=3) { + ver= RE_findOrAddVert(obr, obr->totvert++); + VECCOPY(ver->co, data); + + /* flip normal if face is backfacing, also used in face loop below */ + if(ver->co[2] < 0.0) { + VECCOPY(ver->n, n); + ver->flag = 1; + } + else { + ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2]; + ver->flag = 0; + } + + MTC_Mat4MulVecfl(mat, ver->co); + + if (orco) { + ver->orco = orco; + orco += 3; + } + } + + if(only_verts==0) { + startvlak= obr->totvlak; + index= dl->index; + for(a=0; aparts; a++, index+=3) { + + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr = obr; + vlr->v1= RE_findOrAddVert(obr, startvert+index[0]); + vlr->v2= RE_findOrAddVert(obr, startvert+index[1]); + vlr->v3= RE_findOrAddVert(obr, startvert+index[2]); + vlr->v4= NULL; + + if(vlr->v1->flag) { + VECCOPY(vlr->n, n); + } + else { + vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2]; + } + + vlr->mat= matar[ dl->col ]; + vlr->flag= 0; + if( (cu->flag & CU_NOPUNOFLIP) ) { + vlr->flag |= R_NOPUNOFLIP; + } + vlr->ec= 0; + vlr->lay= ob->lay; + } + } + } + else if (dl->type==DL_SURF) { + + /* cyclic U means an extruded full circular curve, we skip bevel splitting then */ + if (dl->flag & DL_CYCL_U) { + orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); + } + else { + int p1,p2,p3,p4; + + fp= dl->verts; + startvert= obr->totvert; + nr= dl->nr*dl->parts; + + while(nr--) { + ver= RE_findOrAddVert(obr, obr->totvert++); + + VECCOPY(ver->co, fp); + MTC_Mat4MulVecfl(mat, ver->co); + fp+= 3; + + if (orco) { + ver->orco = orco; + orco += 3; + } + } + + if(dl->bevelSplitFlag || only_verts==0) { + startvlak= obr->totvlak; + + for(a=0; aparts; a++) { + + frontside= (a >= dl->nr/2); + + DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts); + p1+= startvert; + p2+= startvert; + p3+= startvert; + p4+= startvert; + + for(; bnr; b++) { + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr= obr; + vlr->v1= RE_findOrAddVert(obr, p2); + vlr->v2= RE_findOrAddVert(obr, p1); + vlr->v3= RE_findOrAddVert(obr, p3); + vlr->v4= RE_findOrAddVert(obr, p4); + vlr->ec= ME_V2V3+ME_V3V4; + if(a==0) vlr->ec+= ME_V1V2; + + vlr->flag= dl->rt; + vlr->lay= ob->lay; + + /* this is not really scientific: the vertices + * 2, 3 en 4 seem to give better vertexnormals than 1 2 3: + * front and backside treated different!! + */ + + if(frontside) + CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n); + else + CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n); + + vlr->mat= matar[ dl->col ]; + + p4= p3; + p3++; + p2= p1; + p1++; + } + } + + if (dl->bevelSplitFlag) { + for(a=0; aparts-1+!!(dl->flag&DL_CYCL_V); a++) + if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F))) + split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U); + } + + /* vertex normals */ + for(a= startvlak; atotvlak; a++) { + vlr= RE_findOrAddVlak(obr, a); + + VecAddf(vlr->v1->n, vlr->v1->n, vlr->n); + VecAddf(vlr->v3->n, vlr->v3->n, vlr->n); + VecAddf(vlr->v2->n, vlr->v2->n, vlr->n); + VecAddf(vlr->v4->n, vlr->v4->n, vlr->n); + } + for(a=startvert; atotvert; a++) { + ver= RE_findOrAddVert(obr, a); + len= Normalize(ver->n); + if(len==0.0) ver->flag= 1; /* flag abuse, its only used in zbuf now */ + else ver->flag= 0; + } + for(a= startvlak; atotvlak; a++) { + vlr= RE_findOrAddVlak(obr, a); + if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n); + if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n); + if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n); + if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n); + } + } + } + } + + dl= dl->next; + } + + /* not very elegant... but we want original displist in UI */ + if(cu->resolu_ren) { + freedisplist(&cu->disp); + SWAP(ListBase, olddl, cu->disp); + } +} + +/* ------------------------------------------------------------------------- */ +/* Mesh */ +/* ------------------------------------------------------------------------- */ + struct edgesort { int v1, v2; int f; @@ -2606,13 +2815,13 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort) return edsort; } -static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge) +static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge) { struct edgesort ed, *edp; CustomDataLayer *layer; MTFace *mtface, *mtf; MCol *mcol, *mc; - int index, mtfn, mcn, n; + int index, mtfn, mcn; char *name; if(medge->v1 < medge->v2) { @@ -2636,8 +2845,7 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { mtface= &((MTFace*)layer->data)[edp->f]; - n= vlakren_customdata_layer_num(mtfn++, layer->active_rnd); - mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1); + mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); *mtf= *mtface; @@ -2648,8 +2856,7 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak } else if(layer->type == CD_MCOL && mcn < MAX_MCOL) { mcol= &((MCol*)layer->data)[edp->f*4]; - n= vlakren_customdata_layer_num(mcn++, layer->active_rnd); - mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1); + mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); mc[0]= mcol[edp->i1]; mc[1]= mc[2]= mc[3]= mcol[edp->i2]; @@ -2658,8 +2865,9 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak } } -static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts) +static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) { + Object *ob= obr->ob; Mesh *me; MVert *mvert = NULL; MFace *mface; @@ -2667,36 +2875,23 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts VertRen *ver; Material *ma; MSticky *ms = NULL; - PartEff *paf; DerivedMesh *dm; CustomDataMask mask; float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3], float *orco=0; - int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, totvlako, totverto, vertofs; + int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, vertofs; int end, do_autosmooth=0, totvert = 0; int useFluidmeshNormals= 0; // NT fluidsim, use smoothed normals? int use_original_normals= 0; me= ob->data; - paf = give_parteff(ob); - if(paf) { - /* warning; build_particle_system does modifier calls itself */ - if(paf->flag & PAF_STATIC) render_static_particle_system(re, ob, paf); - else render_particle_system(re, ob, par, paf); - if((paf->flag & PAF_SHOWE)==0) return; - } - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); MTC_Mat4Invert(ob->imat, mat); MTC_Mat3CpyMat4(imat, ob->imat); - if(me->totvert==0) { + if(me->totvert==0) return; - } - - totvlako= re->totvlak; - totverto= re->totvert; need_orco= 0; for(a=1; a<=ob->totcol; a++) { @@ -2767,16 +2962,16 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts ma= give_render_material(re, ob, 1); if(ma->mode & MA_HALO) { - make_render_halos(re, ob, me, totvert, mvert, ma, orco); + make_render_halos(re, obr, me, totvert, mvert, ma, orco); } else { for(a=0; atotvert++); + ver= RE_findOrAddVert(obr, obr->totvert++); VECCOPY(ver->co, mvert->co); if(do_autosmooth==0) /* autosmooth on original unrotated data to prevent differences between frames */ MTC_Mat4MulVecfl(mat, ver->co); - + if(useFluidmeshNormals) { /* normals are inverted in render */ xn = -mvert->no[0]/ 32767.0; @@ -2793,7 +2988,7 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts orco+=3; } if(ms) { - float *sticky= RE_vertren_get_sticky(re, ver, 1); + float *sticky= RE_vertren_get_sticky(obr, ver, 1); sticky[0]= ms->co[0]; sticky[1]= ms->co[1]; ms++; @@ -2802,12 +2997,12 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts if(!only_verts) { /* store customdata names, because DerivedMesh is freed */ - RE_vlakren_set_customdata_names(re, &dm->faceData); + RE_set_customdata_names(obr, &dm->faceData); /* still to do for keys: the correct local texture coordinate */ /* faces in order of color blocks */ - vertofs= re->totvert - totvert; + vertofs= obr->totvert - totvert; for(a1=0; (a1totcol || (a1==0 && ob->totcol==0)); a1++) { ma= give_render_material(re, ob, a1+1); @@ -2845,13 +3040,13 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts v3= mface->v3; v4= mface->v4; flag= mface->flag & ME_SMOOTH; - - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, vertofs+v1); - vlr->v2= RE_findOrAddVert(re, vertofs+v2); - vlr->v3= RE_findOrAddVert(re, vertofs+v3); - if(v4) vlr->v4= RE_findOrAddVert(re, vertofs+v4); + + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr= obr; + vlr->v1= RE_findOrAddVert(obr, vertofs+v1); + vlr->v2= RE_findOrAddVert(obr, vertofs+v2); + vlr->v3= RE_findOrAddVert(obr, vertofs+v3); + if(v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4); else vlr->v4= 0; /* render normals are inverted in render */ @@ -2879,12 +3074,12 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts vlr->ec= 0; /* mesh edges rendered separately */ vlr->lay= ob->lay; - if(len==0) re->totvlak--; + if(len==0) obr->totvlak--; else { CustomDataLayer *layer; MTFace *mtface, *mtf; MCol *mcol, *mc; - int index, mtfn= 0, mcn= 0, n; + int index, mtfn= 0, mcn= 0; char *name; for(index=0; indexfaceData.totlayer; index++) { @@ -2892,14 +3087,12 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts name= layer->name; if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { - n= vlakren_customdata_layer_num(mtfn++, layer->active_rnd); - mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1); + mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); mtface= (MTFace*)layer->data; *mtf= mtface[a]; } else if(layer->type == CD_MCOL && mcn < MAX_MCOL) { - n= vlakren_customdata_layer_num(mcn++, layer->active_rnd); - mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1); + mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); mcol= (MCol*)layer->data; memcpy(mc, &mcol[a*4], sizeof(MCol)*4); } @@ -2929,16 +3122,15 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts MVert *v0 = &mvert[medge->v1]; MVert *v1 = &mvert[medge->v2]; - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, vertofs+medge->v1); - vlr->v2= RE_findOrAddVert(re, vertofs+medge->v2); + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->obr= obr; + vlr->v1= RE_findOrAddVert(obr, vertofs+medge->v1); + vlr->v2= RE_findOrAddVert(obr, vertofs+medge->v2); vlr->v3= vlr->v2; vlr->v4= NULL; - if(edgetable) { - use_mesh_edge_lookup(re, dm, medge, vlr, edgetable, totedge); - } + if(edgetable) + use_mesh_edge_lookup(obr, dm, medge, vlr, edgetable, totedge); xn= -(v0->no[0]+v1->no[0]); yn= -(v0->no[1]+v1->no[1]); @@ -2963,28 +3155,30 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts if(!only_verts) { if (test_for_displace(re, ob ) ) { - calc_vertexnormals(re, totverto, totvlako, 0); - do_displacement(re, ob, totvlako, re->totvlak-totvlako, totverto, re->totvert-totverto); + calc_vertexnormals(re, obr, 0); + do_displacement(re, obr); } if(do_autosmooth) { - autosmooth(re, mat, totverto, totvlako, me->smoothresh); + autosmooth(re, obr, mat, me->smoothresh); } if(useFluidmeshNormals) { // do not recalculate, only init render data - calc_fluidsimnormals(re, totverto, totvlako, need_tangent); + calc_fluidsimnormals(re, obr, need_tangent); } else { - calc_vertexnormals(re, totverto, totvlako, need_tangent); + calc_vertexnormals(re, obr, need_tangent); } if(need_stress) - calc_edge_stress(re, me, totverto, totvlako); + calc_edge_stress(re, obr, me); } dm->release(dm); } +/* ------------------------------------------------------------------------- */ +/* Lamps and Shadowbuffers */ /* ------------------------------------------------------------------------- */ static void initshadowbuf(Render *re, LampRen *lar, float mat[][4]) @@ -3039,7 +3233,6 @@ static void initshadowbuf(Render *re, LampRen *lar, float mat[][4]) } - static void area_lamp_vectors(LampRen *lar) { float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac; @@ -3317,442 +3510,118 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) return go; } +/* layflag: allows material group to ignore layerflag */ +static void add_lightgroup(Render *re, Group *group, int exclusive) +{ + GroupObject *go, *gol; + + group->id.flag &= ~LIB_DOIT; + + /* it's a bit too many loops in loops... but will survive */ + /* note that 'exclusive' will remove it from the global list */ + for(go= group->gobject.first; go; go= go->next) { + go->lampren= NULL; + + if(go->ob->lay & re->scene->lay) { + if(go->ob && go->ob->type==OB_LAMP) { + for(gol= re->lights.first; gol; gol= gol->next) { + if(gol->ob==go->ob) { + go->lampren= gol->lampren; + break; + } + } + if(go->lampren==NULL) + gol= add_render_lamp(re, go->ob); + if(gol && exclusive) { + BLI_remlink(&re->lights, gol); + MEM_freeN(gol); + } + } + } + } +} + +static void set_material_lightgroups(Render *re) +{ + Group *group; + Material *ma; + + /* not for preview render */ + if(re->scene->r.scemode & R_PREVIEWBUTS) + return; + + for(group= G.main->group.first; group; group=group->id.next) + group->id.flag |= LIB_DOIT; + + /* it's a bit too many loops in loops... but will survive */ + /* hola! materials not in use...? */ + for(ma= G.main->mat.first; ma; ma=ma->id.next) { + if(ma->group && (ma->group->id.flag & LIB_DOIT)) + add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY); + } +} + +static void set_renderlayer_lightgroups(Render *re, Scene *sce) +{ + SceneRenderLayer *srl; + + for(srl= sce->r.layers.first; srl; srl= srl->next) { + if(srl->light_override) + add_lightgroup(re, srl->light_override, 0); + } +} + +/* ------------------------------------------------------------------------- */ +/* World */ /* ------------------------------------------------------------------------- */ -/* returns amount of vertices added for orco */ -static int dl_surf_to_renderdata(Render *re, Object *ob, DispList *dl, Material **matar, float *orco, float mat[4][4]) +void init_render_world(Render *re) { - VertRen *v1, *v2, *v3, *v4, *ver; - VlakRen *vlr, *vlr1, *vlr2, *vlr3; - Curve *cu= ob->data; - float *data, n1[3], flen; - int u, v, orcoret= 0; - int p1, p2, p3, p4, a; - int sizeu, nsizeu, sizev, nsizev; - int startvert, startvlak; + int a; + char *cp; - startvert= re->totvert; - nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr; - - data= dl->verts; - for (u = 0; u < sizeu; u++) { - v1 = RE_findOrAddVert(re, re->totvert++); /* save this for possible V wrapping */ - VECCOPY(v1->co, data); data += 3; - if(orco) { - v1->orco= orco; orco+= 3; orcoret++; - } - MTC_Mat4MulVecfl(mat, v1->co); + if(re->scene && re->scene->world) { + re->wrld= *(re->scene->world); - for (v = 1; v < sizev; v++) { - ver= RE_findOrAddVert(re, re->totvert++); - VECCOPY(ver->co, data); data += 3; - if(orco) { - ver->orco= orco; orco+= 3; orcoret++; - } - MTC_Mat4MulVecfl(mat, ver->co); - } - /* if V-cyclic, add extra vertices at end of the row */ - if (dl->flag & DL_CYCL_U) { - ver= RE_findOrAddVert(re, re->totvert++); - VECCOPY(ver->co, v1->co); - if(orco) { - ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0); - } - } - } - - /* Done before next loop to get corner vert */ - if (dl->flag & DL_CYCL_U) nsizev++; - if (dl->flag & DL_CYCL_V) nsizeu++; - - /* if U cyclic, add extra row at end of column */ - if (dl->flag & DL_CYCL_V) { - for (v = 0; v < nsizev; v++) { - v1= RE_findOrAddVert(re, startvert + v); - ver= RE_findOrAddVert(re, re->totvert++); - VECCOPY(ver->co, v1->co); - if(orco) { - ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v); - } - } + cp= (char *)&re->wrld.fastcol; + + cp[0]= 255.0*re->wrld.horr; + cp[1]= 255.0*re->wrld.horg; + cp[2]= 255.0*re->wrld.horb; + cp[3]= 1; + + VECCOPY(re->grvec, re->viewmat[2]); + Normalize(re->grvec); + Mat3CpyMat4(re->imat, re->viewinv); + + for(a=0; awrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX; + + /* AO samples should be OSA minimum */ + if(re->osa) + while(re->wrld.aosamp*re->wrld.aosamp < re->osa) + re->wrld.aosamp++; + if(!(re->r.mode & R_RAYTRACE)) + re->wrld.mode &= ~WO_AMB_OCC; + } + else { + memset(&re->wrld, 0, sizeof(World)); + re->wrld.exp= 0.0; + re->wrld.range= 1.0; } - sizeu = nsizeu; - sizev = nsizev; - - startvlak= re->totvlak; - - for(u = 0; u < sizeu - 1; u++) { - p1 = startvert + u * sizev; /* walk through face list */ - p2 = p1 + 1; - p3 = p2 + sizev; - p4 = p3 - 1; - - for(v = 0; v < sizev - 1; v++) { - v1= RE_findOrAddVert(re, p1); - v2= RE_findOrAddVert(re, p2); - v3= RE_findOrAddVert(re, p3); - v4= RE_findOrAddVert(re, p4); - - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4; - - flen= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1); - VECCOPY(vlr->n, n1); - - vlr->lay= ob->lay; - vlr->mat= matar[ dl->col]; - vlr->ec= ME_V1V2+ME_V2V3; - vlr->flag= dl->rt; - if( (cu->flag & CU_NOPUNOFLIP) ) { - vlr->flag |= R_NOPUNOFLIP; - } - - VecAddf(v1->n, v1->n, n1); - VecAddf(v2->n, v2->n, n1); - VecAddf(v3->n, v3->n, n1); - VecAddf(v4->n, v4->n, n1); - - p1++; p2++; p3++; p4++; - } - } - /* fix normals for U resp. V cyclic faces */ - sizeu--; sizev--; /* dec size for face array */ - if (dl->flag & DL_CYCL_V) { - - for (v = 0; v < sizev; v++) - { - /* optimize! :*/ - vlr= RE_findOrAddVlak(re, UVTOINDEX(sizeu - 1, v)); - vlr1= RE_findOrAddVlak(re, UVTOINDEX(0, v)); - VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n); - VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n); - VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n); - VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n); - } - } - if (dl->flag & DL_CYCL_U) { - - for (u = 0; u < sizeu; u++) - { - /* optimize! :*/ - vlr= RE_findOrAddVlak(re, UVTOINDEX(u, 0)); - vlr1= RE_findOrAddVlak(re, UVTOINDEX(u, sizev-1)); - VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n); - VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n); - VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n); - VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n); - } - } - /* last vertex is an extra case: - - ^ ()----()----()----() - | | | || | - u | |(0,n)||(0,0)| - | | || | - ()====()====[]====() - | | || | - | |(m,n)||(m,0)| - | | || | - ()----()----()----() - v -> - - vertex [] is no longer shared, therefore distribute - normals of the surrounding faces to all of the duplicates of [] - */ - - if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)) - { - vlr= RE_findOrAddVlak(re, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */ - vlr1= RE_findOrAddVlak(re, UVTOINDEX(0,0)); /* (0,0) */ - VecAddf(n1, vlr->n, vlr1->n); - vlr2= RE_findOrAddVlak(re, UVTOINDEX(0, sizev-1)); /* (0,n) */ - VecAddf(n1, n1, vlr2->n); - vlr3= RE_findOrAddVlak(re, UVTOINDEX(sizeu-1, 0)); /* (m,0) */ - VecAddf(n1, n1, vlr3->n); - VECCOPY(vlr->v3->n, n1); - VECCOPY(vlr1->v1->n, n1); - VECCOPY(vlr2->v2->n, n1); - VECCOPY(vlr3->v4->n, n1); - } - for(a = startvert; a < re->totvert; a++) { - ver= RE_findOrAddVert(re, a); - Normalize(ver->n); - } - - - return orcoret; + re->wrld.linfac= 1.0 + pow((2.0*re->wrld.exp + 0.5), -10); + re->wrld.logfac= log( (re->wrld.linfac-1.0)/re->wrld.linfac )/re->wrld.range; } -static void init_render_surf(Render *re, Object *ob) -{ - Nurb *nu=0; - Curve *cu; - ListBase displist; - DispList *dl; - Material *matar[32]; - float *orco=NULL, *orcobase=NULL, mat[4][4]; - int a, need_orco=0; - cu= ob->data; - nu= cu->nurb.first; - if(nu==0) return; - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); - - /* material array */ - memset(matar, 0, 4*32); - matar[0]= give_render_material(re, ob, 0); - for(a=0; atotcol; a++) { - matar[a]= give_render_material(re, ob, a+1); - if(matar[a] && matar[a]->texco & TEXCO_ORCO) { - need_orco= 1; - } - } - - if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1; - - if(need_orco) orcobase= orco= get_object_orco(re, ob); - - displist.first= displist.last= 0; - makeDispListSurf(ob, &displist, 1); - - dl= displist.first; - /* walk along displaylist and create rendervertices/-faces */ - while(dl) { - /* watch out: u ^= y, v ^= x !! */ - if(dl->type==DL_SURF) { - orco+= 3*dl_surf_to_renderdata(re, ob, dl, matar, orco, mat); - } - - dl= dl->next; - } - freedisplist(&displist); -} - -static void init_render_curve(Render *re, Object *ob, int only_verts) -{ - Curve *cu; - VertRen *ver; - VlakRen *vlr; - DispList *dl; - ListBase olddl={NULL, NULL}; - Material *matar[32]; - float len, *data, *fp, *orco=NULL, *orcobase= NULL; - float n[3], mat[4][4]; - int nr, startvert, startvlak, a, b; - int frontside, need_orco=0; - - cu= ob->data; - if(cu->nurb.first==NULL) return; - - /* no modifier call here, is in makedisp */ - - if(cu->resolu_ren) - SWAP(ListBase, olddl, cu->disp); - - /* test displist */ - if(cu->disp.first==NULL) - makeDispListCurveTypes(ob, 0); - dl= cu->disp.first; - if(cu->disp.first==NULL) return; - - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); - - /* material array */ - memset(matar, 0, 4*32); - matar[0]= give_render_material(re, ob, 0); - for(a=0; atotcol; a++) { - matar[a]= give_render_material(re, ob, a+1); - if(matar[a]->texco & TEXCO_ORCO) { - need_orco= 1; - } - } - - if(need_orco) orcobase=orco= get_object_orco(re, ob); - - dl= cu->disp.first; - while(dl) { - if(dl->type==DL_INDEX3) { - int *index; - - startvert= re->totvert; - data= dl->verts; - - n[0]= ob->imat[0][2]; - n[1]= ob->imat[1][2]; - n[2]= ob->imat[2][2]; - Normalize(n); - - for(a=0; anr; a++, data+=3) { - ver= RE_findOrAddVert(re, re->totvert++); - VECCOPY(ver->co, data); - - /* flip normal if face is backfacing, also used in face loop below */ - if(ver->co[2] < 0.0) { - VECCOPY(ver->n, n); - ver->flag = 1; - } - else { - ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2]; - ver->flag = 0; - } - - MTC_Mat4MulVecfl(mat, ver->co); - - if (orco) { - ver->orco = orco; - orco += 3; - } - } - - if(only_verts==0) { - startvlak= re->totvlak; - index= dl->index; - for(a=0; aparts; a++, index+=3) { - - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob = ob; - vlr->v1= RE_findOrAddVert(re, startvert+index[0]); - vlr->v2= RE_findOrAddVert(re, startvert+index[1]); - vlr->v3= RE_findOrAddVert(re, startvert+index[2]); - vlr->v4= NULL; - - if(vlr->v1->flag) { - VECCOPY(vlr->n, n); - } - else { - vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2]; - } - - vlr->mat= matar[ dl->col ]; - vlr->flag= 0; - if( (cu->flag & CU_NOPUNOFLIP) ) { - vlr->flag |= R_NOPUNOFLIP; - } - vlr->ec= 0; - vlr->lay= ob->lay; - } - } - } - else if (dl->type==DL_SURF) { - - /* cyclic U means an extruded full circular curve, we skip bevel splitting then */ - if (dl->flag & DL_CYCL_U) { - orco+= 3*dl_surf_to_renderdata(re, ob, dl, matar, orco, mat); - } - else { - int p1,p2,p3,p4; - - fp= dl->verts; - startvert= re->totvert; - nr= dl->nr*dl->parts; - - while(nr--) { - ver= RE_findOrAddVert(re, re->totvert++); - - VECCOPY(ver->co, fp); - MTC_Mat4MulVecfl(mat, ver->co); - fp+= 3; - - if (orco) { - ver->orco = orco; - orco += 3; - } - } - - if(dl->bevelSplitFlag || only_verts==0) { - startvlak= re->totvlak; - - for(a=0; aparts; a++) { - - frontside= (a >= dl->nr/2); - - DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts); - p1+= startvert; - p2+= startvert; - p3+= startvert; - p4+= startvert; - - for(; bnr; b++) { - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, p2); - vlr->v2= RE_findOrAddVert(re, p1); - vlr->v3= RE_findOrAddVert(re, p3); - vlr->v4= RE_findOrAddVert(re, p4); - vlr->ec= ME_V2V3+ME_V3V4; - if(a==0) vlr->ec+= ME_V1V2; - - vlr->flag= dl->rt; - vlr->lay= ob->lay; - - /* this is not really scientific: the vertices - * 2, 3 en 4 seem to give better vertexnormals than 1 2 3: - * front and backside treated different!! - */ - - if(frontside) - CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n); - else - CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n); - - vlr->mat= matar[ dl->col ]; - - p4= p3; - p3++; - p2= p1; - p1++; - } - } - - if (dl->bevelSplitFlag) { - for(a=0; aparts-1+!!(dl->flag&DL_CYCL_V); a++) - if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F))) - split_v_renderfaces(re, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U); - } - - /* vertex normals */ - for(a= startvlak; atotvlak; a++) { - vlr= RE_findOrAddVlak(re, a); - - VecAddf(vlr->v1->n, vlr->v1->n, vlr->n); - VecAddf(vlr->v3->n, vlr->v3->n, vlr->n); - VecAddf(vlr->v2->n, vlr->v2->n, vlr->n); - VecAddf(vlr->v4->n, vlr->v4->n, vlr->n); - } - for(a=startvert; atotvert; a++) { - ver= RE_findOrAddVert(re, a); - len= Normalize(ver->n); - if(len==0.0) ver->flag= 1; /* flag abuse, its only used in zbuf now */ - else ver->flag= 0; - } - for(a= startvlak; atotvlak; a++) { - vlr= RE_findOrAddVlak(re, a); - if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n); - if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n); - if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n); - if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n); - } - } - } - } - - dl= dl->next; - } - - /* not very elegant... but we want original displist in UI */ - if(cu->resolu_ren) { - freedisplist(&cu->disp); - SWAP(ListBase, olddl, cu->disp); - } -} +/* ------------------------------------------------------------------------- */ +/* Object Finalization */ +/* ------------------------------------------------------------------------- */ /* prevent phong interpolation for giving ray shadow errors (terminator problem) */ -static void set_phong_threshold(Render *re, Object *ob, int startface, int numface, int startvert, int numvert ) +static void set_phong_threshold(ObjectRen *obr) { // VertRen *ver; VlakRen *vlr; @@ -3763,8 +3632,8 @@ static void set_phong_threshold(Render *re, Object *ob, int startface, int numfa are taken into account. This threshold is meant to work on smooth geometry, not for extreme cases (ton) */ - for(i=startface; itotvlak; i++) { + vlr= RE_findOrAddVlak(obr, i); if(vlr->flag & R_SMOOTH) { dot= INPR(vlr->n, vlr->v1->n); dot= ABS(dot); @@ -3795,7 +3664,258 @@ static void set_phong_threshold(Render *re, Object *ob, int startface, int numfa if(tot) { thresh/= (float)tot; - ob->smoothresh= cos(0.5*M_PI-saacos(thresh)); + obr->ob->smoothresh= cos(0.5*M_PI-saacos(thresh)); + } +} + +/* per face check if all samples should be taken. + if raytrace, do always for raytraced material, or when material full_osa set */ +static void set_fullsample_flag(Render *re, ObjectRen *obr) +{ + VlakRen *vlr; + int a, trace; + + if(re->osa==0) + return; + + trace= re->r.mode & R_RAYTRACE; + + for(a=obr->totvlak-1; a>=0; a--) { + vlr= RE_findOrAddVlak(obr, a); + + if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA; + else if(trace) { + if(vlr->mat->mode & MA_SHLESS); + else if(vlr->mat->mode & (MA_RAYTRANSP|MA_RAYMIRROR)) + /* for blurry reflect/refract, better to take more samples + * inside the raytrace than as OSA samples */ + if ((vlr->mat->gloss_mir == 1.0) && (vlr->mat->gloss_tra == 1.0)) + vlr->flag |= R_FULL_OSA; + } + } +} + +static void check_non_flat_quads(ObjectRen *obr) +{ + VlakRen *vlr, *vlr1; + VertRen *v1, *v2, *v3, *v4; + float nor[3], xn, flen; + int a; + + for(a=obr->totvlak-1; a>=0; a--) { + vlr= RE_findOrAddVlak(obr, a); + + /* test if rendering as a quad or triangle, skip wire */ + if(vlr->v4 && (vlr->flag & R_STRAND)==0 && (vlr->mat->mode & MA_WIRE)==0) { + + /* check if quad is actually triangle */ + v1= vlr->v1; + v2= vlr->v2; + v3= vlr->v3; + v4= vlr->v4; + VECSUB(nor, v1->co, v2->co); + if( ABS(nor[0])v1= v2; + vlr->v2= v3; + vlr->v3= v4; + vlr->v4= NULL; + } + else { + VECSUB(nor, v2->co, v3->co); + if( ABS(nor[0])v2= v3; + vlr->v3= v4; + vlr->v4= NULL; + } + else { + VECSUB(nor, v3->co, v4->co); + if( ABS(nor[0])v4= NULL; + } + else { + VECSUB(nor, v4->co, v1->co); + if( ABS(nor[0])v4= NULL; + } + } + } + } + + if(vlr->v4) { + + /* Face is divided along edge with the least gradient */ + /* Flagged with R_DIVIDE_24 if divide is from vert 2 to 4 */ + /* 4---3 4---3 */ + /* |\ 1| or |1 /| */ + /* |0\ | |/ 0| */ + /* 1---2 1---2 0 = orig face, 1 = new face */ + + /* render normals are inverted in render! we calculate normal of single tria here */ + flen= CalcNormFloat(vlr->v4->co, vlr->v3->co, vlr->v1->co, nor); + if(flen==0.0) CalcNormFloat(vlr->v4->co, vlr->v2->co, vlr->v1->co, nor); + + xn= nor[0]*vlr->n[0] + nor[1]*vlr->n[1] + nor[2]*vlr->n[2]; + + if(ABS(xn) < 0.999995 ) { // checked on noisy fractal grid + float d1, d2; + + vlr1= RE_vlakren_copy(obr, vlr); + vlr1->flag |= R_FACE_SPLIT; + + /* split direction based on vnorms */ + CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, nor); + d1= nor[0]*vlr->v1->n[0] + nor[1]*vlr->v1->n[1] + nor[2]*vlr->v1->n[2]; + + CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, nor); + d2= nor[0]*vlr->v2->n[0] + nor[1]*vlr->v2->n[1] + nor[2]*vlr->v2->n[2]; + + if( fabs(d1) < fabs(d2) ) vlr->flag |= R_DIVIDE_24; + else vlr->flag &= ~R_DIVIDE_24; + + /* new vertex pointers */ + if (vlr->flag & R_DIVIDE_24) { + vlr1->v1= vlr->v2; + vlr1->v2= vlr->v3; + vlr1->v3= vlr->v4; + + vlr->v3 = vlr->v4; + + vlr1->flag |= R_DIVIDE_24; + } + else { + vlr1->v1= vlr->v1; + vlr1->v2= vlr->v3; + vlr1->v3= vlr->v4; + + vlr1->flag &= ~R_DIVIDE_24; + } + vlr->v4 = vlr1->v4 = NULL; + + /* new normals */ + CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); + CalcNormFloat(vlr1->v3->co, vlr1->v2->co, vlr1->v1->co, vlr1->n); + } + /* clear the flag when not divided */ + else vlr->flag &= ~R_DIVIDE_24; + } + } + } +} + +static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts) +{ + Object *ob= obr->ob; + + if(obr->totvert || obr->totvlak || obr->tothalo || obr->totstrand) { + /* the exception below is because displace code now is in init_render_mesh call, + I will look at means to have autosmooth enabled for all object types + and have it as general postprocess, like displace */ + if(ob->type!=OB_MESH && test_for_displace(re, ob)) + do_displacement(re, obr); + + if(!only_verts) { + /* phong normal interpolation can cause error in tracing + * (terminator problem) */ + ob->smoothresh= 0.0; + if((re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW)) + set_phong_threshold(obr); + + check_non_flat_quads(obr); + set_fullsample_flag(re, obr); + } + } +} + +/* ------------------------------------------------------------------------- */ +/* Database */ +/* ------------------------------------------------------------------------- */ + +static int render_object_type(int type) +{ + return ELEM5(type, OB_FONT, OB_CURVE, OB_SURF, OB_MESH, OB_MBALL); +} + +static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) +{ + Object *ob= obr->ob; + ParticleSystem *psys; + int i; + + if(obr->psysindex) { + if((!obr->prev || obr->prev->ob != ob) && ob->type==OB_MESH) { + /* the emitter mesh wasn't rendered so the modifier stack wasn't + * evaluated with render settings */ + DerivedMesh *dm; + dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); + dm->release(dm); + } + + for(psys=ob->particlesystem.first, i=0; ipsysindex-1; i++) + psys= psys->next; + + render_new_particle_system(re, obr, psys); + } + else { + if ELEM(ob->type, OB_FONT, OB_CURVE) + init_render_curve(re, obr, only_verts); + else if(ob->type==OB_SURF) + init_render_surf(re, obr); + else if(ob->type==OB_MESH) + init_render_mesh(re, obr, only_verts); + else if(ob->type==OB_MBALL) + init_render_mball(re, obr); + } + + finalize_render_object(re, obr, only_verts); + + re->totvert += obr->totvert; + re->totvlak += obr->totvlak; + re->tothalo += obr->tothalo; + re->totstrand += obr->totstrand; +} + +static void add_render_object(Render *re, Object *ob, Object *par, int index, int only_verts) +{ + ObjectRen *obr; + ParticleSystem *psys; + int show_emitter, allow_render= 1, psysindex; + + /* the emitter has to be processed first (render levels of modifiers) */ + /* so here we only check if the emitter should be rendered */ + if(ob->particlesystem.first) { + show_emitter= 0; + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + show_emitter += psys->part->draw & PART_DRAW_EMITTER; + psys_particles_to_render_backup(ob, psys); + } + + /* if no psys has "show emitter" selected don't render emitter */ + if(show_emitter == 0) + allow_render= 0; + } + + /* one render object for the data itself */ + if(allow_render) { + obr= RE_addRenderObject(re, ob, par, index, 0); + init_render_object_data(re, obr, only_verts); + + /* only add instance for objects that have not been used for dupli */ + if(!(ob->transflag & OB_RENDER_DUPLI)) + RE_addRenderInstance(re, obr, ob, par, index, 0, NULL); + } + + /* and one render object per particle system */ + if(ob->particlesystem.first) { + psysindex= 1; + for(psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) { + obr= RE_addRenderObject(re, ob, par, index, psysindex); + init_render_object_data(re, obr, only_verts); + psys_render_backup_to_particles(ob, psys); + + /* only add instance for objects that have not been used for dupli */ + if(!(ob->transflag & OB_RENDER_DUPLI)) + RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL); + } } } @@ -3806,75 +3926,14 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i static double lasttime= 0.0; double time; float mat[4][4]; - int startface, startvert, startstrand, allow_render=1; - - startface=re->totvlak; - startvert=re->totvert; - startstrand=re->totstrand; - ob->flag |= OB_DONE; - - /* the emitter has to be processed first (render levels of modifiers) */ - /* so here we only check if the emitter should be rendered */ - if(ob->particlesystem.first) { - ParticleSystem *psys = ob->particlesystem.first; - int showe = 0; - for(; psys; psys=psys->next) - showe += psys->part->draw & PART_DRAW_EMITTER; - - /* if no psys has "show emitter" selected don't render emitter */ - if(showe==0) allow_render = 0; - } - - if(allow_render) { - if(ob->type==OB_LAMP) - add_render_lamp(re, ob); - else if ELEM(ob->type, OB_FONT, OB_CURVE) - init_render_curve(re, ob, only_verts); - else if(ob->type==OB_SURF) - init_render_surf(re, ob); - else if(ob->type==OB_MESH) - init_render_mesh(re, ob, par, only_verts); - else if(ob->type==OB_MBALL) - init_render_mball(re, ob); - else { - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); - } - } - - if(ob->particlesystem.first) { - ParticleSystem *psys = ob->particlesystem.first; - DerivedMesh *dm = 0; - - /* the emitter mesh wasn't rendered so the modifier stack wasn't evaluated with render settings */ - if(allow_render==0 && ob->type==OB_MESH) - dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); - - for(; psys; psys=psys->next) { - render_new_particle_system(re, ob, psys); - psys_free_render_memory(ob, psys); - } - - if(dm) - dm->release(dm); - } - - /* generic post process here */ - if(startvert!=re->totvert || startstrand!=re->totstrand) - RE_addRenderObject(re, ob, par, index, startvert, re->totvert, startface, re->totvlak, startstrand, re->totstrand); - - if(startvert!=re->totvert) { - /* the exception below is because displace code now is in init_render_mesh call, - I will look at means to have autosmooth enabled for all object types - and have it as general postprocess, like displace */ - if (ob->type!=OB_MESH && test_for_displace(re, ob ) ) - do_displacement(re, ob, startface, re->totvlak-startface, startvert, re->totvert-startvert); - - /* phong normal interpolation can cause error in tracing (terminator prob) */ - ob->smoothresh= 0.0; - if( (re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW) ) - set_phong_threshold(re, ob, startface, re->totvlak-startface, startvert, re->totvert-startvert); + if(ob->type==OB_LAMP) + add_render_lamp(re, ob); + else if(render_object_type(ob->type)) + add_render_object(re, ob, par, index, only_verts); + else { + MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); + MTC_Mat4Invert(ob->imat, mat); } time= PIL_check_seconds_timer(); @@ -3888,6 +3947,8 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i re->i.totlamp= re->totlamp; re->stats_draw(&re->i); } + + ob->flag |= OB_DONE; } void RE_Database_Free(Render *re) @@ -3961,246 +4022,144 @@ void RE_Database_Free(Render *re) } } -/* per face check if all samples should be taken. - if raytrace, do always for raytraced material, or when material full_osa set */ -static void set_fullsample_flag(Render *re) +static int allow_render_object(Object *ob, int nolamps, int onlyselected, Object *actob) { - VlakRen *vlr; - int a, trace; + /* override not showing object when duplis are used with particles */ + if(ob->transflag & OB_DUPLIPARTS){ + int allow= 0; - if(re->osa==0) - return; - - trace= re->r.mode & R_RAYTRACE; - - for(a=re->totvlak-1; a>=0; a--) { - vlr= RE_findOrAddVlak(re, a); - - if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA; - else if(trace) { - if(vlr->mat->mode & MA_SHLESS); - else if(vlr->mat->mode & (MA_RAYTRANSP|MA_RAYMIRROR)) - /* for blurry reflect/refract, better to take more samples - * inside the raytrace than as OSA samples */ - if ((vlr->mat->gloss_mir == 1.0) && (vlr->mat->gloss_tra == 1.0)) - vlr->flag |= R_FULL_OSA; + if(ob->particlesystem.first) { + ParticleSystem *psys; + ParticleSettings *part; + + for(psys=ob->particlesystem.first; psys; psys=psys->next){ + part=psys->part; + + if((part->draw_as==PART_DRAW_OB && part->dup_ob) || (part->draw_as==PART_DRAW_GR && part->dup_group)) + if(part->draw & PART_DRAW_EMITTER) + allow= 1; + } } + + if(!allow) + return 0; } + else if(ob->transflag & OB_DUPLI) + return 0; + + if(nolamps && (ob->type==OB_LAMP)) + return 0; + + if(onlyselected && (ob!=actob && !(ob->flag & SELECT))) + return 0; + + return 1; } -static void check_non_flat_quads(Render *re) +static int allow_render_dupli_instance(Render *re, Object *ob, Object *obd) { - VlakRen *vlr, *vlr1; - VertRen *v1, *v2, *v3, *v4; - float nor[3], xn, flen; - int a; + return (render_object_type(obd->type) && + (!(ob->transflag & OB_DUPLIGROUP)) && + !(re->r.mode & R_RADIO)); +} - for(a=re->totvlak-1; a>=0; a--) { - vlr= RE_findOrAddVlak(re, a); +static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int only_verts) +{ + Base *base; + Object *ob; + Scene *sce; + float mat[4][4]; + + for(SETLOOPER(re->scene, base)) { + ob= base->object; + /* imat objects has to be done here, since displace can have texture using Object map-input */ + MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); + MTC_Mat4Invert(ob->imat, mat); + /* each object should only be rendered once */ + ob->flag &= ~OB_DONE; + ob->transflag &= ~OB_RENDER_DUPLI; + } + + for(SETLOOPER(re->scene, base)) { + ob= base->object; - /* test if rendering as a quad or triangle, skip wire */ - if(vlr->v4 && (vlr->flag & R_STRAND)==0 && (vlr->mat->mode & MA_WIRE)==0) { - - /* check if quad is actually triangle */ - v1= vlr->v1; - v2= vlr->v2; - v3= vlr->v3; - v4= vlr->v4; - VECSUB(nor, v1->co, v2->co); - if( ABS(nor[0])v1= v2; - vlr->v2= v3; - vlr->v3= v4; - vlr->v4= NULL; - } - else { - VECSUB(nor, v2->co, v3->co); - if( ABS(nor[0])v2= v3; - vlr->v3= v4; - vlr->v4= NULL; - } - else { - VECSUB(nor, v3->co, v4->co); - if( ABS(nor[0])v4= NULL; - } - else { - VECSUB(nor, v4->co, v1->co); - if( ABS(nor[0])v4= NULL; - } - } - } - } - - if(vlr->v4) { - - /* Face is divided along edge with the least gradient */ - /* Flagged with R_DIVIDE_24 if divide is from vert 2 to 4 */ - /* 4---3 4---3 */ - /* |\ 1| or |1 /| */ - /* |0\ | |/ 0| */ - /* 1---2 1---2 0 = orig face, 1 = new face */ - - /* render normals are inverted in render! we calculate normal of single tria here */ - flen= CalcNormFloat(vlr->v4->co, vlr->v3->co, vlr->v1->co, nor); - if(flen==0.0) CalcNormFloat(vlr->v4->co, vlr->v2->co, vlr->v1->co, nor); - - xn= nor[0]*vlr->n[0] + nor[1]*vlr->n[1] + nor[2]*vlr->n[2]; + /* if the object has been restricted from rendering in the outliner, ignore it */ + if(ob->restrictflag & OB_RESTRICT_RENDER) continue; - if(ABS(xn) < 0.999995 ) { // checked on noisy fractal grid - float d1, d2; + /* OB_DONE means the object itself got duplicated, so was already converted */ + if(ob->flag & OB_DONE) { + if(ob->transflag & OB_RENDER_DUPLI) + if(allow_render_object(ob, nolamps, onlyselected, actob)) + init_render_object(re, ob, NULL, 0, only_verts); + } + else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) { + if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) { + DupliObject *dob; + ListBase *lb; - vlr1= RE_vlakren_copy(re, vlr); - vlr1->flag |= R_FACE_SPLIT; + lb= object_duplilist(sce, ob); + for(dob= lb->first; dob; dob= dob->next) { + Object *obd= dob->ob; - /* split direction based on vnorms */ - CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, nor); - d1= nor[0]*vlr->v1->n[0] + nor[1]*vlr->v1->n[1] + nor[2]*vlr->v1->n[2]; + Mat4CpyMat4(obd->obmat, dob->mat); - CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, nor); - d2= nor[0]*vlr->v2->n[0] + nor[1]*vlr->v2->n[1] + nor[2]*vlr->v2->n[2]; - - if( fabs(d1) < fabs(d2) ) vlr->flag |= R_DIVIDE_24; - else vlr->flag &= ~R_DIVIDE_24; - - /* new vertex pointers */ - if (vlr->flag & R_DIVIDE_24) { - vlr1->v1= vlr->v2; - vlr1->v2= vlr->v3; - vlr1->v3= vlr->v4; + /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */ + if(dob->no_draw) + continue; - vlr->v3 = vlr->v4; + if(obd->restrictflag & OB_RESTRICT_RENDER) + continue; + + if(obd->type==OB_MBALL) + continue; + + if(!allow_render_object(obd, nolamps, onlyselected, actob)) + continue; + + if(allow_render_dupli_instance(re, ob, obd)) { + ParticleSystem *psys; + int psysindex; + float imat[4][4], mat[4][4]; + + /* compute difference between object matrix and + * object matrix with dupli transform, in viewspace */ + Mat4Invert(imat, dob->omat); + MTC_Mat4MulSerie(mat, re->viewmat, dob->mat, imat, re->viewinv, 0, 0, 0, 0); + + RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat); + + psysindex= 1; + for(psys=obd->particlesystem.first; psys; psys=psys->next) + RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat); - vlr1->flag |= R_DIVIDE_24; + obd->flag |= OB_DONE; + obd->transflag |= OB_RENDER_DUPLI; } - else { - vlr1->v1= vlr->v1; - vlr1->v2= vlr->v3; - vlr1->v3= vlr->v4; - - vlr1->flag &= ~R_DIVIDE_24; - } - vlr->v4 = vlr1->v4 = NULL; + else + init_render_object(re, obd, ob, dob->index, only_verts); - /* new normals */ - CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); - CalcNormFloat(vlr1->v3->co, vlr1->v2->co, vlr1->v1->co, vlr1->n); + if(re->test_break()) break; } - /* clear the flag when not divided */ - else vlr->flag &= ~R_DIVIDE_24; + free_object_duplilist(lb); + + if(allow_render_object(ob, nolamps, onlyselected, actob)) + init_render_object(re, ob, NULL, 0, only_verts); } + else if(allow_render_object(ob, nolamps, onlyselected, actob)) + init_render_object(re, ob, NULL, 0, only_verts); } - } -} -/* layflag: allows material group to ignore layerflag */ -static void add_lightgroup(Render *re, Group *group, int exclusive) -{ - GroupObject *go, *gol; - - group->id.flag &= ~LIB_DOIT; + if(re->test_break()) break; + } - /* it's a bit too many loops in loops... but will survive */ - /* note that 'exclusive' will remove it from the global list */ - for(go= group->gobject.first; go; go= go->next) { - go->lampren= NULL; - - if(go->ob->lay & re->scene->lay) { - if(go->ob && go->ob->type==OB_LAMP) { - for(gol= re->lights.first; gol; gol= gol->next) { - if(gol->ob==go->ob) { - go->lampren= gol->lampren; - break; - } - } - if(go->lampren==NULL) - gol= add_render_lamp(re, go->ob); - if(gol && exclusive) { - BLI_remlink(&re->lights, gol); - MEM_freeN(gol); - } - } - } - } -} - -static void set_material_lightgroups(Render *re) -{ - Group *group; - Material *ma; - - /* not for preview render */ - if(re->scene->r.scemode & R_PREVIEWBUTS) - return; - - for(group= G.main->group.first; group; group=group->id.next) - group->id.flag |= LIB_DOIT; - - /* it's a bit too many loops in loops... but will survive */ - /* hola! materials not in use...? */ - for(ma= G.main->mat.first; ma; ma=ma->id.next) { - if(ma->group && (ma->group->id.flag & LIB_DOIT)) - add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY); - } -} - -static void set_renderlayer_lightgroups(Render *re, Scene *sce) -{ - SceneRenderLayer *srl; - - for(srl= sce->r.layers.first; srl; srl= srl->next) { - if(srl->light_override) - add_lightgroup(re, srl->light_override, 0); - } -} - -void init_render_world(Render *re) -{ - int a; - char *cp; - - if(re->scene && re->scene->world) { - re->wrld= *(re->scene->world); - - cp= (char *)&re->wrld.fastcol; - - cp[0]= 255.0*re->wrld.horr; - cp[1]= 255.0*re->wrld.horg; - cp[2]= 255.0*re->wrld.horb; - cp[3]= 1; - - VECCOPY(re->grvec, re->viewmat[2]); - Normalize(re->grvec); - Mat3CpyMat4(re->imat, re->viewinv); - - for(a=0; awrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX; - - /* AO samples should be OSA minimum */ - if(re->osa) - while(re->wrld.aosamp*re->wrld.aosamp < re->osa) - re->wrld.aosamp++; - if(!(re->r.mode & R_RAYTRACE)) - re->wrld.mode &= ~WO_AMB_OCC; - } - else { - memset(&re->wrld, 0, sizeof(World)); - re->wrld.exp= 0.0; - re->wrld.range= 1.0; - } - - re->wrld.linfac= 1.0 + pow((2.0*re->wrld.exp + 0.5), -10); - re->wrld.logfac= log( (re->wrld.linfac-1.0)/re->wrld.linfac )/re->wrld.range; + if(!re->test_break()) + RE_makeRenderInstances(re); } /* used to be 'rotate scene' */ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) { extern int slurph_opt; /* key.c */ - Base *base; - Object *ob; Scene *sce; float mat[4][4]; unsigned int lay; @@ -4248,166 +4207,12 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) init_render_materials(re->r.mode, &re->wrld.ambr); set_node_shader_lamp_loop(shade_material_loop); - for(SETLOOPER(re->scene, base)) { - ob= base->object; - /* imat objects has to be done here, since displace can have texture using Object map-input */ - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); - /* each object should only be rendered once */ - ob->flag &= ~OB_DONE; - } - /* MAKE RENDER DATA */ - - for(SETLOOPER(re->scene, base)) { - ob= base->object; - - /* if the object has been restricted from rendering in the outliner, ignore it */ - if (ob->restrictflag & OB_RESTRICT_RENDER) continue; - - /* OB_DONE means the object itself got duplicated, so was already converted */ - if (ob->flag & OB_DONE) { -#ifndef DISABLE_YAFRAY - /* yafray: for some reason this part was removed, but yafray really needs it... - Dupliverts objects are treated as instances of an original 'sourceobject', - which needs to be included in the renderlist here. - exception: lamps, lattices, armatures & camera's */ - if ((re->r.renderer==R_YAFRAY) && ((ob->type!=OB_LATTICE) && (ob->type!=OB_ARMATURE) && - (ob->type!=OB_LAMP) && (ob->type!=OB_CAMERA))) - { - printf("Duplivert object %s, adding to renderlist\n", ob->id.name); - ob->flag &= ~OB_DONE; - init_render_object(re, ob, NULL, 0, 0); - ob->flag |= OB_DONE; - } -#endif /* disable yafray */ - } - else if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) { - int pdup=0; - if(ob->transflag & OB_DUPLI) { - - /* exception: mballs! */ -#ifndef DISABLE_YAFRAY - /* yafray: except for mballs, include at least one copy of a dupliframe object in the renderlist. */ - if (re->r.renderer==R_YAFRAY) { - if ((ob->type!=OB_MBALL) && ((ob->transflag & OB_DUPLIFRAMES)!=0)) { - printf("Dupliframe Object %s, adding to renderlist\n", ob->id.name); - init_render_object(re, ob, NULL, 0, 0); - } - } -#endif /* disable yafray */ - /* before make duplis, update particle for current frame */ - if(ob->transflag & OB_DUPLIVERTS) { - PartEff *paf= give_parteff(ob); - if(paf) { - if(paf->flag & PAF_ANIMATED) build_particle_system(ob); - } - } - if(ob->transflag & OB_DUPLIPARTS){ - if(ob->particlesystem.first){ - ParticleSystem *psys = ob->particlesystem.first; - ParticleSettings *part; + database_init_objects(re, lay, 0, 0, 0, 0); - for(; psys; psys=psys->next){ - part=psys->part; - - if((part->draw_as==PART_DRAW_OB && part->dup_ob) || (part->draw_as==PART_DRAW_GR && part->dup_group)) - if(part->draw & PART_DRAW_EMITTER) - pdup++; - } - } - } - - if(ob->type==OB_MBALL) { - init_render_object(re, ob, NULL, 0, 0); - } - else { - DupliObject *dob; - ListBase *lb= object_duplilist(sce, ob); - - for(dob= lb->first; dob; dob= dob->next) { - Object *obd= dob->ob; - - if (obd->restrictflag & OB_RESTRICT_RENDER) continue; - - Mat4CpyMat4(obd->obmat, dob->mat); - - /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */ - if(dob->no_draw) - continue; - - if(obd->type!=OB_MBALL) { -#ifndef DISABLE_YAFRAY - /* yafray: special case handling of duplivert/dupligroup objects. - Only one copy included in renderlist(see above), all others treated as instance of that. - So only need to store name and matrix. Exception are lamps. lattices, armatures and camera's */ - if (re->r.renderer==R_YAFRAY) { - /* dupligroup obs are included directly */ - if (obd->flag & OB_FROMGROUP) { - printf("Dupligroup object %s, adding to renderlist\n", obd->id.name); - init_render_object(re, obd, ob, dob->index, 0); - } - else if ((obd->type!=OB_LATTICE) && (obd->type!=OB_ARMATURE) && - (obd->type!=OB_LAMP) && (obd->type!=OB_CAMERA)) - { - printf("Adding dupli matrix for object %s\n", obd->id.name); - YAF_addDupliMtx(obd); - } - else init_render_object(re, obd, ob, dob->index, 0); - } - else init_render_object(re, obd, ob, dob->index, 0); -#else - init_render_object(re, obd, ob, dob->index, 0); -#endif /* disable yafray */ - } - - if(re->test_break()) break; - } - free_object_duplilist(lb); - } - } - else { -#ifndef DISABLE_YAFRAY - /* yafray: linked data objects treated similarly to dupliverts, - If object not known yet (not in renderlist), include in the renderlist, - otherwise treat as instance of it, so only name and matrix are stored - Exception: objects which have materials linked to object instead of mesh */ - if ((re->r.renderer==R_YAFRAY) && (ob->colbits==0)) - { - /* Special case, parent object dupli's: ignore if object itself is lamp or parent is lattice or empty */ - if (ob->parent) { - if ((ob->type!=OB_LAMP) && (ob->parent->type!=OB_EMPTY) && - (ob->parent->type!=OB_LATTICE) && YAF_objectKnownData(ob)) - printf("From parent: Added dupli matrix for linked data object %s\n", ob->id.name); - else - init_render_object(re, ob, NULL, 0, 0); - } - else if ((ob->type!=OB_EMPTY) && (ob->type!=OB_LAMP) && - (ob->type!=OB_ARMATURE) && YAF_objectKnownData(ob)) - printf("Added dupli matrix for linked data object %s\n", ob->id.name); - else - init_render_object(re, ob, NULL, 0, 0); - } - else init_render_object(re, ob, NULL, 0, 0); -#else - init_render_object(re, ob, NULL, 0, 0); -#endif /* disable yafray */ - } - - /* override not showing object when duplis are used with particles */ - if(pdup) - init_render_object(re, ob, NULL, 0, 0); - } - - if(re->test_break()) break; - } - - if(!re->test_break()) { - LampRen *lar; - - sort_halos(re); - + int tothalo; + set_material_lightgroups(re); for(sce= re->scene; sce; sce= sce->set) set_renderlayer_lightgroups(re, sce); @@ -4422,25 +4227,18 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) re->i.totlamp= re->totlamp; re->stats_draw(&re->i); - set_fullsample_flag(re); - check_non_flat_quads(re); - set_normalflags(re); - + /* don't sort stars */ + tothalo= re->tothalo; if(!re->test_break()) - if(re->wrld.mode & WO_STARS) + if(re->wrld.mode & WO_STARS) RE_make_stars(re, NULL, NULL, NULL); + sort_halos(re, tothalo); re->i.infostr= "Creating Shadowbuffers"; re->stats_draw(&re->i); /* SHADOW BUFFER */ - for(lar=re->lampren.first; lar; lar= lar->next) { - if(re->test_break()) break; - if(lar->shb) { - /* if type is irregular, this only sets the perspective matrix and autoclips */ - makeshadowbuf(re, lar); - } - } + threaded_makeshadowbufs(re); /* yafray: 'direct' radiosity, environment maps and raytree init not needed for yafray render */ /* although radio mode could be useful at some point, later */ @@ -4478,12 +4276,24 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) re->stats_draw(&re->i); } +/* exported call to recalculate hoco for vertices, when winmat changed */ +void RE_DataBase_ApplyWindow(Render *re) +{ + project_renderdata(re, projectverto, 0, 0, 0); +} + +void RE_DataBase_GetView(Render *re, float mat[][4]) +{ + Mat4CpyMat4(mat, re->viewmat); +} + +/* ------------------------------------------------------------------------- */ +/* Speed Vectors */ +/* ------------------------------------------------------------------------- */ + static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset) { extern int slurph_opt; /* key.c */ - Base *base; - Object *ob; - Scene *sce; float mat[4][4]; unsigned int lay; @@ -4513,62 +4323,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset) RE_SetView(re, mat); } - for(SETLOOPER(re->scene, base)) { - ob= base->object; - /* imat objects has to be done here, since displace can have texture using Object map-input */ - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); - /* each object should only be rendered once */ - ob->flag &= ~OB_DONE; - } - /* MAKE RENDER DATA */ - - for(SETLOOPER(re->scene, base)) { - ob= base->object; - - if (ob->restrictflag & OB_RESTRICT_RENDER) continue; - - /* OB_DONE means the object itself got duplicated, so was already converted */ - if(ob->flag & OB_DONE); - else if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) { - if(ob->transflag & OB_DUPLI) { - - /* before make duplis, update particle for current frame */ - if(ob->transflag & OB_DUPLIVERTS) { - PartEff *paf= give_parteff(ob); - if(paf) { - if(paf->flag & PAF_ANIMATED) build_particle_system(ob); - } - } - - if(ob->type==OB_MBALL) { - init_render_object(re, ob, NULL, 0, 1); - } - else { - DupliObject *dob; - ListBase *lb= object_duplilist(sce, ob); - - for(dob= lb->first; dob; dob= dob->next) { - Object *obd= dob->ob; - - if (obd->restrictflag & OB_RESTRICT_RENDER) continue; - - Mat4CpyMat4(obd->obmat, dob->mat); - - if(obd->type!=OB_MBALL) { - init_render_object(re, obd, ob, dob->index, 1); - } - } - free_object_duplilist(lb); - } - } - else { - init_render_object(re, ob, NULL, 0, 1); - } - } - if(re->test_break()) break; - } + database_init_objects(re, lay, 0, 0, 0, 1); if(!re->test_break()) project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); @@ -4663,58 +4419,54 @@ static void calculate_speedvector(float *vectors, int step, float winsq, float w } } -static void calculate_speedvectors(Render *re, ObjectRen *obren, float *vectors, int step) +static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step) { + ObjectRen *obr= obi->obr; VertRen *ver= NULL; StrandRen *strand= NULL; - float *speed, ho[4]; + float *speed, ho[4], winmat[4][4]; float winsq= re->winx*re->winy, winroot= sqrt(winsq); - int a, startvert, endvert, startstrand, endstrand; + int a; - startvert= obren->startvert; - endvert= obren->endvert; - startstrand= obren->startstrand; - endstrand= obren->endstrand; - - if(re->vertnodes) { - /* set first vertex OK */ - a= startvert-1; - ver= re->vertnodes[a>>8].vert + (a & 255); - - for(a=startvert; avertnodes[a>>8].vert; + if(obi->flag & R_TRANSFORMED) + Mat4MulMat4(winmat, obi->mat, re->winmat); + else + Mat4CpyMat4(winmat, re->winmat); + + if(obr->vertnodes) { + for(a=0; atotvert; a++, vectors+=2) { + if((a & 255)==0) ver= obr->vertnodes[a>>8].vert; else ver++; - speed= RE_vertren_get_winspeed(re, ver, 1); - calculate_speedvector(vectors, step, winsq, winroot, ver->co, ver->ho, speed); + speed= RE_vertren_get_winspeed(obi, ver, 1); + projectvert(ver->co, winmat, ho); + calculate_speedvector(vectors, step, winsq, winroot, ver->co, ho, speed); } } - if(re->strandnodes) { - /* set first strand OK */ - a= startstrand-1; - strand= re->strandnodes[a>>8].strand + (a & 255); - - for(a=startstrand; astrandnodes[a>>8].strand; + if(obr->strandnodes) { + for(a=0; atotstrand; a++, vectors+=2) { + if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; else strand++; - speed= RE_strandren_get_winspeed(re, strand, 1); - projectverto(strand->vert->co, re->winmat, ho); + speed= RE_strandren_get_winspeed(obi, strand, 1); + projectvert(strand->vert->co, winmat, ho); calculate_speedvector(vectors, step, winsq, winroot, strand->vert->co, ho, speed); } } } -static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, int endvert, int step, Object *fsob) +static int load_fluidsimspeedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step) { + ObjectRen *obr= obi->obr; + Object *fsob= obr->ob; VertRen *ver= NULL; float *speed, div, zco[2]; float zmulx= re->winx/2, zmuly= re->winy/2, len; float winsq= re->winx*re->winy, winroot= sqrt(winsq); int a, j; - float hoco[4], fsvec[4], camco[4]; - float mat[4][4]; + float hoco[4], ho[4], fsvec[4], camco[4]; + float mat[4][4], winmat[4][4]; float imat[4][4]; MVert *vverts; @@ -4725,28 +4477,30 @@ static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, MTC_Mat4Invert(imat, mat); /* set first vertex OK */ - a= startvert-1; - ver= re->vertnodes[a>>8].vert + (a & 255); - if( (!fsob->fluidsimSettings) || (!fsob->fluidsimSettings->meshSurfNormals) ) return 0; vverts = fsob->fluidsimSettings->meshSurfNormals; //fprintf(stderr, "GZ_VEL obj '%s', calc load_fluidsimspeedvectors\n",fsob->id.name); // NT DEBUG - if( endvert-startvert != fsob->fluidsimSettings->meshSurface->totvert ) { - //fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", endvert-startvert , fsob->fluidsimSettings->meshSurface->totvert); // DEBUG + if( obr->totvert != fsob->fluidsimSettings->meshSurface->totvert ) { + //fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", obr->totvert, fsob->fluidsimSettings->meshSurface->totvert); // DEBUG return 0; } + + if(obi->flag & R_TRANSFORMED) + Mat4MulMat4(winmat, obi->mat, re->winmat); + else + Mat4CpyMat4(winmat, re->winmat); - for(a=startvert; atotvert; a++, vectors+=2) { if((a & 255)==0) - ver= re->vertnodes[a>>8].vert; + ver= obr->vertnodes[a>>8].vert; else ver++; // get fluid velocity fsvec[3] = 0.; //fsvec[0] = fsvec[1] = fsvec[2] = fsvec[3] = 0.; fsvec[2] = 2.; // NT fixed test - for(j=0;j<3;j++) fsvec[j] = vverts[a-startvert].co[j]; + for(j=0;j<3;j++) fsvec[j] = vverts[a].co[j]; // transform (=rotate) to cam space camco[0]= imat[0][0]*fsvec[0] + imat[0][1]*fsvec[1] + imat[0][2]*fsvec[2]; @@ -4754,12 +4508,13 @@ static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, camco[2]= imat[2][0]*fsvec[0] + imat[2][1]*fsvec[1] + imat[2][2]*fsvec[2]; // get homogenous coordinates - projectverto(camco, re->winmat, hoco); + projectvert(camco, winmat, hoco); + projectvert(ver->co, winmat, ho); /* now map hocos to screenspace, uses very primitive clip still */ // use ho[3] of original vertex, xy component of vel. direction - if(ver->ho[3]<0.1f) div= 10.0f; - else div= 1.0f/ver->ho[3]; + if(ho[3]<0.1f) div= 10.0f; + else div= 1.0f/ho[3]; zco[0]= zmulx*hoco[0]*div; zco[1]= zmuly*hoco[1]*div; @@ -4770,7 +4525,7 @@ static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, zco[0]*= len; zco[1]*= len; } - speed= RE_vertren_get_winspeed(re, ver, 1); + speed= RE_vertren_get_winspeed(obi, ver, 1); // set both to the same value speed[0]= speed[2]= zco[0]; speed[1]= speed[3]= zco[1]; @@ -4784,47 +4539,44 @@ static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, /* result should be that we can free entire database */ static void copy_dbase_object_vectors(Render *re, ListBase *lb) { - ObjectRen *obren, *obrenlb; - VertRen *ver; - StrandRen *strand; - float *vec, ho[4]; + ObjectInstanceRen *obi, *obilb; + ObjectRen *obr; + VertRen *ver= NULL; + StrandRen *strand= NULL; + float *vec, ho[4], winmat[4][4]; int a, totvector; - for(obren= re->objecttable.first; obren; obren= obren->next) { - obrenlb= MEM_dupallocN(obren); - BLI_addtail(lb, obrenlb); + for(obi= re->instancetable.first; obi; obi= obi->next) { + obr= obi->obr; - totvector= obren->endvert - obren->startvert; - totvector+= obren->endstrand - obren->startstrand; + obilb= MEM_mallocN(sizeof(ObjectInstanceRen), "ObInstanceVector"); + memcpy(obilb, obi, sizeof(ObjectInstanceRen)); + BLI_addtail(lb, obilb); + + obilb->totvector= totvector= obr->totvert + obr->totstrand; if(totvector > 0) { - vec= obrenlb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array"); + vec= obilb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array"); - if(obren->endvert > obren->startvert) { - /* first vertex */ - a= obren->startvert-1; - ver= re->vertnodes[a>>8].vert + (a & 255); + if(obi->flag & R_TRANSFORMED) + Mat4MulMat4(winmat, obi->mat, re->winmat); + else + Mat4CpyMat4(winmat, re->winmat); - for(a=obren->startvert; aendvert; a++, vec+=2) { - if((a & 255)==0) ver= re->vertnodes[a>>8].vert; - else ver++; - - speedvector_project(NULL, vec, ver->co, ver->ho); - } + for(a=0; atotvert; a++, vec+=2) { + if((a & 255)==0) ver= obr->vertnodes[a>>8].vert; + else ver++; + + projectvert(ver->co, winmat, ho); + speedvector_project(NULL, vec, ver->co, ho); } - if(obren->endstrand > obren->startstrand) { - /* first strand */ - a= obren->startstrand-1; - strand= re->strandnodes[a>>8].strand + (a & 255); - - for(a=obren->startstrand; aendstrand; a++, vec+=2) { - if((a & 255)==0) strand= re->strandnodes[a>>8].strand; - else strand++; - - projectverto(strand->vert->co, re->winmat, ho); - speedvector_project(NULL, vec, strand->vert->co, ho); - } + for(a=0; atotstrand; a++, vec+=2) { + if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; + else strand++; + + projectvert(strand->vert->co, winmat, ho); + speedvector_project(NULL, vec, strand->vert->co, ho); } } } @@ -4832,17 +4584,17 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb) static void free_dbase_object_vectors(ListBase *lb) { - ObjectRen *obren; + ObjectInstanceRen *obi; - for(obren= lb->first; obren; obren= obren->next) - if(obren->vectors) - MEM_freeN(obren->vectors); + for(obi= lb->first; obi; obi= obi->next) + if(obi->vectors) + MEM_freeN(obi->vectors); BLI_freelistN(lb); } void RE_Database_FromScene_Vectors(Render *re, Scene *sce) { - ObjectRen *obren, *oldobren; + ObjectInstanceRen *obi, *oldobi; ListBase *table; ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL}; int step; @@ -4884,40 +4636,41 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) else table= &oldtable; - oldobren= table->first; - for(obren= re->objecttable.first; obren && oldobren; obren= obren->next, oldobren= oldobren->next) { + oldobi= table->first; + for(obi= re->instancetable.first; obi && oldobi; obi= obi->next, oldobi= oldobi->next) { int ok= 1; + obi->totvector= obi->obr->totvert + obi->obr->totstrand; + /* find matching object in old table */ - if(oldobren->ob!=obren->ob || oldobren->par!=obren->par || oldobren->index!=obren->index) { + if(oldobi->ob!=obi->ob || oldobi->par!=obi->par || oldobi->index!=obi->index || oldobi->psysindex!=obi->psysindex) { ok= 0; - for(oldobren= table->first; oldobren; oldobren= oldobren->next) - if(oldobren->ob==obren->ob && oldobren->par==obren->par && oldobren->index==obren->index) + for(oldobi= table->first; oldobi; oldobi= oldobi->next) + if(oldobi->ob==obi->ob && oldobi->par==obi->par && oldobi->index==obi->index && oldobi->psysindex==obi->psysindex) break; - if(oldobren==NULL) - oldobren= table->first; + if(oldobi==NULL) + oldobi= table->first; else ok= 1; } if(ok==0) { - printf("speed table: missing object %s\n", obren->ob->id.name+2); + printf("speed table: missing object %s\n", obi->ob->id.name+2); continue; } // NT check for fluidsim special treatment - if((obren->ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obren->ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)) { + if((obi->ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obi->ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)) { // use preloaded per vertex simulation data , only does calculation for step=1 // NOTE/FIXME - velocities and meshes loaded unnecessarily often during the database_fromscene_vectors calls... - load_fluidsimspeedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step, obren->ob); + load_fluidsimspeedvectors(re, obi, oldobi->vectors, step); } else { /* check if both have same amounts of vertices */ - if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert || - obren->endstrand-obren->startstrand != oldobren->endstrand-oldobren->startstrand) { - printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2); + if(obi->totvector!=oldobi->totvector) { + printf("Warning: object %s has different amount of vertices on other frame\n", obi->ob->id.name+2); continue; } - calculate_speedvectors(re, obren, oldobren->vectors, step); + calculate_speedvectors(re, obi, oldobi->vectors, step); } // not fluidsim } } @@ -4931,11 +4684,9 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) } -/* exported call to recalculate hoco for vertices, when winmat changed */ -void RE_DataBase_ApplyWindow(Render *re) -{ - project_renderdata(re, projectverto, 0, 0, 0); -} +/* ------------------------------------------------------------------------- */ +/* Baking */ +/* ------------------------------------------------------------------------- */ /* setup for shaded view or bake, so only lamps and materials are initialized */ /* type: @@ -4947,11 +4698,9 @@ void RE_DataBase_ApplyWindow(Render *re) */ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) { - Base *base; - Object *ob; - Scene *sce; float mat[4][4]; unsigned int lay; + int onlyselected, nolamps; re->scene= scene; @@ -5000,88 +4749,23 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) init_ao_sphere(&re->wrld); } - /* still bad... doing all */ init_render_textures(re); init_render_materials(re->r.mode, &re->wrld.ambr); set_node_shader_lamp_loop(shade_material_loop); - - for(SETLOOPER(re->scene, base)) { - ob= base->object; - /* imat objects has to be done here, since displace can have texture using Object map-input */ - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); - /* each object should only be rendered once */ - ob->flag &= ~OB_DONE; - } /* MAKE RENDER DATA */ - for(SETLOOPER(re->scene, base)) { - ob= base->object; - - /* if the object has been restricted from rendering in the outliner, ignore it */ - if (ob->restrictflag & OB_RESTRICT_RENDER) continue; - - /* OB_DONE means the object itself got duplicated, so was already converted */ - if(ob->flag & OB_DONE); - else if( (base->lay & lay) || ((base->lay & re->scene->lay)) ) { - - /* check for dupli lamps or non selected groups */ - if(ob->transflag & OB_DUPLI) { - DupliObject *dob; - ListBase *lb= object_duplilist(sce, ob); - - for(dob= lb->first; dob; dob= dob->next) { - Object *obd= dob->ob; - - if(obd->type==OB_LAMP) { - if( ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL) ) { - Mat4CpyMat4(obd->obmat, dob->mat); - init_render_object(re, obd, ob, dob->index, 0); - } - } - else if( ELEM(type, RE_BAKE_AO, RE_BAKE_ALL) ) { - if((base->flag & SELECT)==0) { - Mat4CpyMat4(obd->obmat, dob->mat); - init_render_object(re, obd, ob, dob->index, 0); - } - } - } - free_object_duplilist(lb); - } - else { - if(ob->type==OB_LAMP) { - if( ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL) ) - init_render_object(re, ob, NULL, 0, 0); - } - else if(type!=RE_BAKE_LIGHT) { - if( !ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE) || (ob->flag & SELECT) || (ob == actob) ) - init_render_object(re, ob, NULL, 0, 0); - } - } - } - } + nolamps= !ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL); + onlyselected= ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE); + + database_init_objects(re, lay, nolamps, onlyselected, actob, 0); + set_material_lightgroups(re); - check_non_flat_quads(re); - /* don't call set_normalflags(), no flipping */ - - if(type!=RE_BAKE_LIGHT) { - if(re->r.mode & R_SHADOW) { - LampRen *lar; - - /* SHADOW BUFFER */ - for(lar=re->lampren.first; lar; lar= lar->next) { - - if(re->test_break()) break; - if(lar->shb) { - /* if type is irregular, this only sets the perspective matrix and autoclips */ - /* but, that's not supported for bake... */ - makeshadowbuf(re, lar); - } - } - } - } + /* SHADOW BUFFER */ + if(type!=RE_BAKE_LIGHT) + if(re->r.mode & R_SHADOW) + threaded_makeshadowbufs(re); /* raytree */ if(!re->test_break()) @@ -5089,17 +4773,9 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) makeraytree(re); } -void RE_DataBase_GetView(Render *re, float mat[][4]) -{ - Mat4CpyMat4(mat, re->viewmat); -} - - - - -/* **************************************************************** */ -/* sticky texture coords */ -/* **************************************************************** */ +/* ------------------------------------------------------------------------- */ +/* Sticky texture coords */ +/* ------------------------------------------------------------------------- */ void RE_make_sticky(void) { @@ -5165,172 +4841,3 @@ void RE_make_sticky(void) } } - - -/* **************************************************************** */ -/* Displacement mapping */ -/* **************************************************************** */ -static short test_for_displace(Render *re, Object *ob) -{ - /* return 1 when this object uses displacement textures. */ - Material *ma; - int i; - - for (i=1; i<=ob->totcol; i++) { - ma=give_render_material(re, ob, i); - /* ma->mapto is ORed total of all mapto channels */ - if(ma && (ma->mapto & MAP_DISPLACE)) return 1; - } - return 0; -} - -static void displace_render_vert(Render *re, ShadeInput *shi, VertRen *vr, int vindex, float *scale) -{ - MTFace *tface; - short texco= shi->mat->texco; - float sample=0; - char *name; - int i; - - /* shi->co is current render coord, just make sure at least some vector is here */ - VECCOPY(shi->co, vr->co); - /* vertex normal is used for textures type 'col' and 'var' */ - VECCOPY(shi->vn, vr->n); - - if (texco & TEXCO_UV) { - shi->totuv= 0; - - for (i=0; (tface=RE_vlakren_get_tface(re, shi->vlr, i, &name, 0)); i++) { - ShadeInputUV *suv= &shi->uv[i]; - - /* shi.uv needs scale correction from tface uv */ - suv->uv[0]= 2*tface->uv[vindex][0]-1.0f; - suv->uv[1]= 2*tface->uv[vindex][1]-1.0f; - suv->uv[2]= 0.0f; - suv->name= name; - shi->totuv++; - } - } - - /* set all rendercoords, 'texco' is an ORed value for all textures needed */ - if ((texco & TEXCO_ORCO) && (vr->orco)) { - VECCOPY(shi->lo, vr->orco); - } - if (texco & TEXCO_STICKY) { - float *sticky= RE_vertren_get_sticky(re, vr, 0); - if(sticky) { - shi->sticky[0]= sticky[0]; - shi->sticky[1]= sticky[1]; - shi->sticky[2]= 0.0f; - } - } - if (texco & TEXCO_GLOB) { - VECCOPY(shi->gl, shi->co); - MTC_Mat4MulVecfl(re->viewinv, shi->gl); - } - if (texco & TEXCO_NORM) { - VECCOPY(shi->orn, shi->vn); - } - if(texco & TEXCO_REFL) { - /* not (yet?) */ - } - - shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0; - - do_material_tex(shi); - - //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2], - //vr->co[0], vr->co[1], vr->co[2]); - - /* 0.5 could become button once? */ - vr->co[0] += shi->displace[0] * scale[0] ; - vr->co[1] += shi->displace[1] * scale[1] ; - vr->co[2] += shi->displace[2] * scale[2] ; - - //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]); - - /* we just don't do this vertex again, bad luck for other face using same vertex with - different material... */ - vr->flag |= 1; - - /* Pass sample back so displace_face can decide which way to split the quad */ - sample = shi->displace[0]*shi->displace[0]; - sample += shi->displace[1]*shi->displace[1]; - sample += shi->displace[2]*shi->displace[2]; - - vr->accum=sample; - /* Should be sqrt(sample), but I'm only looking for "bigger". Save the cycles. */ - return; -} - -static void displace_render_face(Render *re, VlakRen *vlr, float *scale) -{ - ShadeInput shi; - - /* set up shadeinput struct for multitex() */ - shi.osatex= 0; /* signal not to use dx[] and dy[] texture AA vectors */ - shi.vlr= vlr; /* current render face */ - shi.mat= vlr->mat; /* current input material */ - - /* Displace the verts, flag is set when done */ - if (!vlr->v1->flag) - displace_render_vert(re, &shi, vlr->v1,0, scale); - - if (!vlr->v2->flag) - displace_render_vert(re, &shi, vlr->v2, 1, scale); - - if (!vlr->v3->flag) - displace_render_vert(re, &shi, vlr->v3, 2, scale); - - if (vlr->v4) { - if (!vlr->v4->flag) - displace_render_vert(re, &shi, vlr->v4, 3, scale); - - /* closest in displace value. This will help smooth edges. */ - if ( fabs(vlr->v1->accum - vlr->v3->accum) > fabs(vlr->v2->accum - vlr->v4->accum)) - vlr->flag |= R_DIVIDE_24; - else vlr->flag &= ~R_DIVIDE_24; // E: typo?, was missing '=' - } - - /* Recalculate the face normal - if flipped before, flip now */ - if(vlr->v4) { - CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); - } - else { - CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); - } -} - - -static void do_displacement(Render *re, Object *ob, int startface, int numface, int startvert, int numvert ) -{ - VertRen *vr; - VlakRen *vlr; -// float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30}; - float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn - int i; //, texflag=0; - Object *obt; - - /* Object Size with parenting */ - obt=ob; - while(obt){ - VecAddf(temp, obt->size, obt->dsize); - scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2]; - obt=obt->parent; - } - - /* Clear all flags */ - for(i=startvert; iflag= 0; - } - - for(i=startface; itotvlak= re->totvlak; envre->totvert= re->totvert; envre->tothalo= re->tothalo; + envre->totstrand= re->totstrand; envre->totlamp= re->totlamp; envre->lights= re->lights; - envre->vertnodeslen= re->vertnodeslen; - envre->vertnodes= re->vertnodes; - envre->blohalen= re->blohalen; - envre->bloha= re->bloha; - envre->vlaknodeslen= re->vlaknodeslen; - envre->vlaknodes= re->vlaknodes; - envre->strandnodeslen= re->strandnodeslen; - envre->strandnodes= re->strandnodes; + envre->objecttable= re->objecttable; envre->strandbuckets= re->strandbuckets; envre->customdata_names= re->customdata_names; envre->raytree= re->raytree; + envre->totinstance= re->totinstance; + envre->instancetable= re->instancetable; + envre->objectinstance= re->objectinstance; return envre; } @@ -171,19 +168,16 @@ static void envmap_free_render_copy(Render *envre) envre->totvlak= 0; envre->totvert= 0; envre->tothalo= 0; + envre->totstrand= 0; envre->totlamp= 0; + envre->totinstance= 0; envre->lights.first= envre->lights.last= NULL; - envre->vertnodeslen= 0; - envre->vertnodes= NULL; - envre->blohalen= 0; - envre->bloha= NULL; - envre->vlaknodeslen= 0; - envre->vlaknodes= NULL; - envre->strandnodeslen= 0; - envre->strandnodes= NULL; + envre->objecttable.first= envre->objecttable.last= NULL; envre->strandbuckets= NULL; envre->customdata_names.first= envre->customdata_names.last= NULL; envre->raytree= NULL; + envre->instancetable.first= envre->instancetable.last= NULL; + envre->objectinstance= NULL; RE_FreeRender(envre); } @@ -225,11 +219,11 @@ static void envmap_transmatrix(float mat[][4], int part) static void env_rotate_scene(Render *re, float mat[][4], int mode) { GroupObject *go; - VlakRen *vlr = NULL; - VertRen *ver = NULL; + ObjectRen *obr; + ObjectInstanceRen *obi; LampRen *lar = NULL; HaloRen *har = NULL; - float xn, yn, zn, imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3]; + float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3]; int a; if(mode==0) { @@ -240,46 +234,36 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) MTC_Mat4CpyMat4(tmat, mat); MTC_Mat3CpyMat4(imat, mat); } - - for(a=0; atotvert; a++) { - if((a & 255)==0) ver= RE_findOrAddVert(re, a); - else ver++; - - MTC_Mat4MulVecfl(tmat, ver->co); - - xn= ver->n[0]; - yn= ver->n[1]; - zn= ver->n[2]; - /* no transpose ! */ - ver->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn; - ver->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn; - ver->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn; - Normalize(ver->n); + + for(obi=re->instancetable.first; obi; obi=obi->next) { + /* append or set matrix depending on dupli */ + if(obi->flag & R_DUPLI_TRANSFORMED) + Mat4MulMat4(obi->mat, tmat, obi->mat); + else if(mode==1) + Mat4CpyMat4(obi->mat, tmat); + else + Mat4One(obi->mat); + + Mat3CpyMat4(cmat, obi->mat); + Mat3Inv(obi->imat, cmat); + + /* indicate the renderer has to use transform matrices */ + if(mode==0) + obi->flag &= ~R_ENV_TRANSFORMED; + else + obi->flag |= R_ENV_TRANSFORMED; } - for(a=0; atothalo; a++) { - if((a & 255)==0) har= re->bloha[a>>8]; - else har++; - - MTC_Mat4MulVecfl(tmat, har->co); - } + + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atothalo; a++) { + if((a & 255)==0) har= obr->bloha[a>>8]; + else har++; - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; - else vlr++; - - xn= vlr->n[0]; - yn= vlr->n[1]; - zn= vlr->n[2]; - /* no transpose ! */ - vlr->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn; - vlr->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn; - vlr->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn; - Normalize(vlr->n); + MTC_Mat4MulVecfl(tmat, har->co); + } } - set_normalflags(re); - for(go=re->lights.first; go; go= go->next) { lar= go->lampren; @@ -314,6 +298,7 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) static void env_layerflags(Render *re, unsigned int notlay) { + ObjectRen *obr; VlakRen *vlr = NULL; int a; @@ -327,23 +312,47 @@ static void env_layerflags(Render *re, unsigned int notlay) notlay= ~notlay; - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; - else vlr++; - if((vlr->lay & notlay)==0) - vlr->flag &= ~R_VISIBLE; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + if((vlr->lay & notlay)==0) + vlr->flag |= R_HIDDEN; + } } } static void env_hideobject(Render *re, Object *ob) { + ObjectRen *obr; VlakRen *vlr = NULL; int a; - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; - else vlr++; - if(vlr->ob == ob) vlr->flag &= ~R_VISIBLE; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + if(obr->ob == ob) + vlr->flag |= R_HIDDEN; + } + } +} + +static void env_showobjects(Render *re) +{ + ObjectRen *obr; + VlakRen *vlr = NULL; + int a; + + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + vlr->flag &= ~R_HIDDEN; + } } } @@ -419,6 +428,7 @@ static void render_envmap(Render *re, EnvMap *env) } /* rotate back */ + env_showobjects(envre); env_rotate_scene(envre, tmat, 0); if(re->test_break()==0) { diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index 8d9f687a32e..23b5e597070 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -984,6 +984,5 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *dxt, f texres->tb*= fx; } - return retval; } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 1c3867a702c..da2542aabaa 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1251,7 +1251,6 @@ static void render_tile_processor(Render *re, int firsttile) } freeparts(re); - R.strandbuckets= NULL; } /* calculus for how much 1 pixel rendered should rotate the 3d geometry */ @@ -1485,7 +1484,6 @@ static void threaded_tile_processor(Render *re) BLI_end_threads(&threads); freeparts(re); re->viewplane= viewplane; /* restore viewplane, modified by pano render */ - R.strandbuckets= NULL; } /* currently only called by preview renders and envmap */ diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index a9699104e01..69e90a7537c 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -88,6 +88,13 @@ static int vlr_check_intersect(Isect *is, RayFace *face) return (is->lay & vlr->lay); } +static float *vlr_get_transform(void *userdata, int i) +{ + ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)userdata, i); + + return (obi->flag & R_TRANSFORMED)? (float*)obi->mat: NULL; +} + void freeraytree(Render *re) { if(re->raytree) { @@ -98,25 +105,46 @@ void freeraytree(Render *re) void makeraytree(Render *re) { + ObjectInstanceRen *obi; + ObjectRen *obr; VlakRen *vlr= NULL; - float min[3], max[3]; + float min[3], max[3], co1[3], co2[3], co3[3], co4[3]; double lasttime= PIL_check_seconds_timer(); int v, totface = 0; INIT_MINMAX(min, max); /* first min max raytree space */ - for(v=0;vtotvlak;v++) { - if((v & 255)==0) vlr= re->vlaknodes[v>>8].vlak; - else vlr++; - if(vlr->mat->mode & MA_TRACEBLE) { - if((vlr->mat->mode & MA_WIRE)==0) { - if(!re->excludeob || vlr->ob != re->excludeob) { - DO_MINMAX(vlr->v1->co, min, max); - DO_MINMAX(vlr->v2->co, min, max); - DO_MINMAX(vlr->v3->co, min, max); + for(obi=re->instancetable.first; obi; obi=obi->next) { + obr= obi->obr; + + if(re->excludeob && obr->ob == re->excludeob) + continue; + + for(v=0;vtotvlak;v++) { + if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; + else vlr++; + if(vlr->mat->mode & MA_TRACEBLE) { + if((vlr->mat->mode & MA_WIRE)==0) { + VECCOPY(co1, vlr->v1->co); + VECCOPY(co2, vlr->v2->co); + VECCOPY(co3, vlr->v3->co); + + if(obi->flag & R_TRANSFORMED) { + Mat4MulVecfl(obi->mat, co1); + Mat4MulVecfl(obi->mat, co2); + Mat4MulVecfl(obi->mat, co3); + } + + DO_MINMAX(co1, min, max); + DO_MINMAX(co2, min, max); + DO_MINMAX(co3, min, max); + if(vlr->v4) { - DO_MINMAX(vlr->v4->co, min, max); + VECCOPY(co4, vlr->v4->co); + if(obi->flag & R_TRANSFORMED) + Mat4MulVecfl(obi->mat, co4); + DO_MINMAX(co4, min, max); } totface++; @@ -125,35 +153,42 @@ void makeraytree(Render *re) } } - re->raytree= RE_ray_tree_create(re->r.ocres, totface, min, max, vlr_face_coords, vlr_check_intersect); + re->raytree= RE_ray_tree_create(re->r.ocres, totface, min, max, + vlr_face_coords, vlr_check_intersect, vlr_get_transform, re); if(min[0] > max[0]) { /* empty raytree */ RE_ray_tree_done(re->raytree); return; } - for(v=0; vtotvlak; v++) { - if((v & 255)==0) { - double time= PIL_check_seconds_timer(); + for(obi=re->instancetable.first; obi; obi=obi->next) { + obr= obi->obr; - vlr= re->vlaknodes[v>>8].vlak; - if(re->test_break()) - break; - if(time-lasttime>1.0f) { - char str[32]; - sprintf(str, "Filling Octree: %d", v); - re->i.infostr= str; - re->stats_draw(&re->i); - re->i.infostr= NULL; - lasttime= time; + if(re->excludeob && obr->ob == re->excludeob) + continue; + + for(v=0; vtotvlak; v++) { + if((v & 255)==0) { + double time= PIL_check_seconds_timer(); + + vlr= obr->vlaknodes[v>>8].vlak; + if(re->test_break()) + break; + if(time-lasttime>1.0f) { + char str[32]; + sprintf(str, "Filling Octree: %d", v); + re->i.infostr= str; + re->stats_draw(&re->i); + re->i.infostr= NULL; + lasttime= time; + } } + else vlr++; + + if(vlr->mat->mode & MA_TRACEBLE) + if((vlr->mat->mode & MA_WIRE)==0) + RE_ray_tree_add_face(re->raytree, RAY_OBJECT_SET(re, obi), vlr); } - else vlr++; - - if(vlr->mat->mode & MA_TRACEBLE) - if((vlr->mat->mode & MA_WIRE)==0) - if(!re->excludeob || vlr->ob != re->excludeob) - RE_ray_tree_add_face(re->raytree, (RayFace*)vlr); } RE_ray_tree_done(re->raytree); @@ -165,7 +200,8 @@ void makeraytree(Render *re) static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) { VlakRen *vlr= (VlakRen*)is->face; - int osatex= 0, norflip; + ObjectInstanceRen *obi= RAY_OBJECT_GET(&R, is->ob); + int osatex= 0; /* set up view vector */ VECCOPY(shi->view, is->vec); @@ -177,6 +213,8 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) Normalize(shi->view); + shi->obi= obi; + shi->obr= obi->obr; shi->vlr= vlr; shi->mat= vlr->mat; memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h @@ -194,35 +232,26 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) shi->dyno[0]= shi->dyno[1]= shi->dyno[2]= 0.0f; } - /* face normal, check for flip, need to set puno here */ - norflip= (vlr->n[0]*shi->view[0]+vlr->n[1]*shi->view[1]+vlr->n[2]*shi->view[2]) < 0.0f; - - if(norflip) - shi->puno= vlr->puno ^ 15;// only flip lower 4 bits - else - shi->puno= vlr->puno; - if(vlr->v4) { if(is->isect==2) - shade_input_set_triangle_i(shi, vlr, 2, 1, 3); + shade_input_set_triangle_i(shi, obi, vlr, 2, 1, 3); else - shade_input_set_triangle_i(shi, vlr, 0, 1, 3); + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 3); } else { - shade_input_set_triangle_i(shi, vlr, 0, 1, 2); + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); } - - /* shade_input_set_triangle_i() sets facenor, now we flip */ - if(norflip) { - shi->facenor[0]= -vlr->n[0]; - shi->facenor[1]= -vlr->n[1]; - shi->facenor[2]= -vlr->n[2]; - } - + shi->u= is->u; shi->v= is->v; shi->dx_u= shi->dx_v= shi->dy_u= shi->dy_v= 0.0f; + shade_input_set_normals(shi); + + /* point normals to viewing direction */ + if(INPR(shi->facenor, shi->view) < 0.0f) + shade_input_flip_normals(shi); + shade_input_set_shade_texco(shi); if(is->mode==RE_RAY_SHADOW_TRA) @@ -371,7 +400,7 @@ static void ray_fadeout(Isect *is, ShadeInput *shi, float *col, float *blendcol, } /* the main recursive tracer itself */ -static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, float *start, float *vec, float *col, VlakRen *vlr, int traflag) +static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, float *start, float *vec, float *col, ObjectInstanceRen *obi, VlakRen *vlr, int traflag) { ShadeInput shi; ShadeResult shr; @@ -392,6 +421,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo } isec.mode= RE_RAY_MIRROR; isec.faceorig= (RayFace*)vlr; + isec.oborig= RAY_OBJECT_SET(&R, obi); if(RE_ray_tree_intersect(R.raytree, &isec)) { float d= 1.0f; @@ -441,10 +471,10 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo reflection(refract, shi.vn, shi.view, shi.vn); } traflag |= RAY_TRA; - traceray(origshi, origshr, depth-1, shi.co, refract, tracol, shi.vlr, traflag ^ RAY_TRAFLIP); + traceray(origshi, origshr, depth-1, shi.co, refract, tracol, shi.obi, shi.vlr, traflag ^ RAY_TRAFLIP); } else - traceray(origshi, origshr, depth-1, shi.co, shi.view, tracol, shi.vlr, 0); + traceray(origshi, origshr, depth-1, shi.co, shi.view, tracol, shi.obi, shi.vlr, 0); f= shr.alpha; f1= 1.0f-f; nf= d * shi.mat->filter; @@ -474,7 +504,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo float mircol[4]; reflection(ref, shi.vn, shi.view, NULL); - traceray(origshi, origshr, depth-1, shi.co, ref, mircol, shi.vlr, 0); + traceray(origshi, origshr, depth-1, shi.co, ref, mircol, shi.obi, shi.vlr, 0); f1= 1.0f-f; @@ -951,7 +981,7 @@ static void trace_refract(float *col, ShadeInput *shi, ShadeResult *shr) VECCOPY(v_refract_new, v_refract); } - traceray(shi, shr, shi->mat->ray_depth_tra, shi->co, v_refract_new, sampcol, shi->vlr, RAY_TRA|RAY_TRAFLIP); + traceray(shi, shr, shi->mat->ray_depth_tra, shi->co, v_refract_new, sampcol, shi->obi, shi->vlr, RAY_TRA|RAY_TRAFLIP); col[0] += sampcol[0]; col[1] += sampcol[1]; @@ -1047,7 +1077,7 @@ static void trace_reflect(float *col, ShadeInput *shi, ShadeResult *shr, float f else reflection(v_reflect, v_nor_new, shi->view, NULL); - traceray(shi, shr, shi->mat->ray_depth, shi->co, v_reflect, sampcol, shi->vlr, 0); + traceray(shi, shr, shi->mat->ray_depth, shi->co, v_reflect, sampcol, shi->obi, shi->vlr, 0); col[0] += sampcol[0]; @@ -1223,6 +1253,7 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) /* adapt isect struct */ VECCOPY(is->start, shi.co); + is->oborig= RAY_OBJECT_SET(&R, shi.obi); is->faceorig= (RayFace*)shi.vlr; ray_trace_shadow_tra(is, depth-1, traflag | RAY_TRA); @@ -1250,6 +1281,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) accum[0]= accum[1]= accum[2]= 0.0f; isec.mode= RE_RAY_MIRROR; isec.faceorig= (RayFace*)ship->vlr; + isec.oborig= RAY_OBJECT_SET(&R, ship->obi); for(a=0; a<8*8; a++) { @@ -1448,7 +1480,9 @@ void ray_ao_qmc(ShadeInput *shi, float *shadfac) int aocolor; isec.faceorig= (RayFace*)shi->vlr; + isec.oborig= RAY_OBJECT_SET(&R, shi->obi); isec.face_last= NULL; + isec.ob_last= 0; isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; isec.lay= -1; VECCOPY(isec.start, shi->co); @@ -1574,7 +1608,9 @@ void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) int j= -1, tot, actual=0, skyadded=0, aocolor; isec.faceorig= (RayFace*)shi->vlr; + isec.oborig= RAY_OBJECT_SET(&R, shi->obi); isec.face_last= NULL; + isec.ob_last= 0; isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; isec.lay= -1; @@ -1737,6 +1773,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * while (samples < max_samples) { isec->faceorig= (RayFace*)shi->vlr; + isec->oborig= RAY_OBJECT_SET(&R, shi->obi); /* manually jitter the start shading co-ord per sample * based on the pre-generated OSA texture sampling offsets, @@ -1873,6 +1910,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa } isec->faceorig= (RayFace*)shi->vlr; + isec->oborig= RAY_OBJECT_SET(&R, shi->obi); vec[0]= jitlamp[0]; vec[1]= jitlamp[1]; @@ -1929,10 +1967,14 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; /* only when not mir tracing, first hit optimm */ - if(shi->depth==0) + if(shi->depth==0) { isec.face_last= (RayFace*)lar->vlr_last[shi->thread]; - else + isec.ob_last= RAY_OBJECT_SET(&R, lar->obi_last[shi->thread]); + } + else { isec.face_last= NULL; + isec.ob_last= 0; + } if(lar->type==LA_SUN || lar->type==LA_HEMI) { maxsize= RE_ray_tree_max_size(R.raytree); @@ -1952,6 +1994,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) if(lar->ray_totsamp<2) { isec.faceorig= (RayFace*)shi->vlr; + isec.oborig= RAY_OBJECT_SET(&R, shi->obi); shadfac[3]= 1.0f; // 1.0=full light /* set up isec vec */ @@ -1974,8 +2017,10 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) } /* for first hit optim, set last interesected shadow face */ - if(shi->depth==0) + if(shi->depth==0) { lar->vlr_last[shi->thread]= (VlakRen*)isec.face_last; + lar->obi_last[shi->thread]= RAY_OBJECT_GET(&R, isec.ob_last); + } } @@ -2001,6 +2046,7 @@ void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co) } isec.faceorig= (RayFace*)shi->vlr; + isec.oborig= RAY_OBJECT_SET(&R, shi->obi); /* set up isec vec */ VECCOPY(isec.start, shi->co); diff --git a/source/blender/render/intern/source/raytrace.c b/source/blender/render/intern/source/raytrace.c index 002148ed97c..54e8e4cfab5 100644 --- a/source/blender/render/intern/source/raytrace.c +++ b/source/blender/render/intern/source/raytrace.c @@ -61,6 +61,7 @@ typedef struct OcVal typedef struct Node { struct RayFace *v[8]; + int ob[8]; struct OcVal ov[8]; struct Node *next; } Node; @@ -76,6 +77,8 @@ typedef struct Octree { char *ocface; /* during building only */ RayCoordsFunc coordsfunc; RayCheckFunc checkfunc; + RayObjectTransformFunc transformfunc; + void *userdata; } Octree; /* ******** globals ***************** */ @@ -230,7 +233,7 @@ static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3] return 0; } -static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short z, float rtf[][3]) +static void ocwrite(Octree *oc, int ob, RayFace *face, int quad, short x, short y, short z, float rtf[][3]) { Branch *br; Node *no; @@ -281,6 +284,7 @@ static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short } no->v[a]= face; + no->ob[a]= ob; if(quad) calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]); @@ -435,7 +439,7 @@ void RE_ray_tree_free(RayTree *tree) MEM_freeN(oc); } -RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayCoordsFunc coordsfunc, RayCheckFunc checkfunc) +RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayCoordsFunc coordsfunc, RayCheckFunc checkfunc, RayObjectTransformFunc transformfunc, void *userdata) { Octree *oc; float t00, t01, t02; @@ -447,6 +451,8 @@ RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayC oc->coordsfunc= coordsfunc; oc->checkfunc= checkfunc; + oc->transformfunc= transformfunc; + oc->userdata= userdata; /* only for debug info */ raycount=0; @@ -486,10 +492,11 @@ RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayC return (RayTree*)oc; } -void RE_ray_tree_add_face(RayTree *tree, RayFace *face) +void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) { Octree *oc = (Octree*)tree; float *v1, *v2, *v3, *v4, ocfac[3], rtf[4][3]; + float co1[3], co2[3], co3[3], co4[3]; short rts[4][3], ocmin[6], *ocmax; char *ocface= oc->ocface; // front, top, size view of face, to fill in int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2; @@ -503,16 +510,34 @@ void RE_ray_tree_add_face(RayTree *tree, RayFace *face) ocmax= ocmin+3; oc->coordsfunc(face, &v1, &v2, &v3, &v4); + + VECCOPY(co1, v1); + VECCOPY(co2, v2); + VECCOPY(co3, v3); + if(v4) + VECCOPY(co4, v4); + + if(ob >= RE_RAY_TRANSFORM_OFFS) { + float (*mat)[4]= (float(*)[4])oc->transformfunc(oc->userdata, ob); + + if(mat) { + Mat4MulVecfl(mat, co1); + Mat4MulVecfl(mat, co2); + Mat4MulVecfl(mat, co3); + if(v4) + Mat4MulVecfl(mat, co4); + } + } for(c=0;c<3;c++) { - rtf[0][c]= (v1[c]-oc->min[c])*ocfac[c] ; + rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ; rts[0][c]= (short)rtf[0][c]; - rtf[1][c]= (v2[c]-oc->min[c])*ocfac[c] ; + rtf[1][c]= (co2[c]-oc->min[c])*ocfac[c] ; rts[1][c]= (short)rtf[1][c]; - rtf[2][c]= (v3[c]-oc->min[c])*ocfac[c] ; + rtf[2][c]= (co3[c]-oc->min[c])*ocfac[c] ; rts[2][c]= (short)rtf[2][c]; if(v4) { - rtf[3][c]= (v4[c]-oc->min[c])*ocfac[c] ; + rtf[3][c]= (co4[c]-oc->min[c])*ocfac[c] ; rts[3][c]= (short)rtf[3][c]; } } @@ -535,7 +560,7 @@ void RE_ray_tree_add_face(RayTree *tree, RayFace *face) } if(ocmin[0]==ocmax[0] && ocmin[1]==ocmax[1] && ocmin[2]==ocmax[2]) { - ocwrite(oc, face, (v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf); + ocwrite(oc, ob, face, (v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf); } else { @@ -574,7 +599,7 @@ void RE_ray_tree_add_face(RayTree *tree, RayFace *face) for(z=ocmin[2];z<=ocmax[2];z++) { if(ocface[b+z] && ocface[a+z]) { if(face_in_node(NULL, x, y, z, rtf)) - ocwrite(oc, face, (v4 != NULL), x,y,z, rtf); + ocwrite(oc, ob, face, (v4 != NULL), x,y,z, rtf); } } } @@ -611,9 +636,9 @@ void RE_ray_tree_done(RayTree *tree) /* ************ raytracer **************** */ /* only for self-intersecting test with current render face (where ray left) */ -static int intersection2(RayFace *face, RayCoordsFunc coordsfunc, float r0, float r1, float r2, float rx1, float ry1, float rz1) +static int intersection2(RayFace *face, int ob, RayObjectTransformFunc transformfunc, RayCoordsFunc coordsfunc, void *userdata, float r0, float r1, float r2, float rx1, float ry1, float rz1) { - float *v1, *v2, *v3, *v4; + float *v1, *v2, *v3, *v4, co1[3], co2[3], co3[3], co4[3]; float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22; float m0, m1, m2, divdet, det, det1; float u1, v, u2; @@ -623,17 +648,35 @@ static int intersection2(RayFace *face, RayCoordsFunc coordsfunc, float r0, floa /* happens for baking with non existing face */ if(v1==NULL) return 1; - - if (v4) { + + if(v4) { SWAP(float*, v3, v4); } + + VECCOPY(co1, v1); + VECCOPY(co2, v2); + VECCOPY(co3, v3); + if(v4) + VECCOPY(co4, v4); + + if(ob >= RE_RAY_TRANSFORM_OFFS) { + float (*mat)[4]= (float(*)[4])transformfunc(userdata, ob); + + if(mat) { + Mat4MulVecfl(mat, co1); + Mat4MulVecfl(mat, co2); + Mat4MulVecfl(mat, co3); + if(v4) + Mat4MulVecfl(mat, co4); + } + } - t00= v3[0]-v1[0]; - t01= v3[1]-v1[1]; - t02= v3[2]-v1[2]; - t10= v3[0]-v2[0]; - t11= v3[1]-v2[1]; - t12= v3[2]-v2[2]; + t00= co3[0]-co1[0]; + t01= co3[1]-co1[1]; + t02= co3[2]-co1[2]; + t10= co3[0]-co2[0]; + t11= co3[1]-co2[1]; + t12= co3[2]-co2[2]; x0= t11*r2-t12*r1; x1= t12*r0-t10*r2; @@ -641,9 +684,9 @@ static int intersection2(RayFace *face, RayCoordsFunc coordsfunc, float r0, floa divdet= t00*x0+t01*x1+t02*x2; - m0= rx1-v3[0]; - m1= ry1-v3[1]; - m2= rz1-v3[2]; + m0= rx1-co3[0]; + m1= ry1-co3[1]; + m2= rz1-co3[2]; det1= m0*x0+m1*x1+m2*x2; if(divdet!=0.0f) { @@ -663,9 +706,9 @@ static int intersection2(RayFace *face, RayCoordsFunc coordsfunc, float r0, floa if(v4) { - t20= v3[0]-v4[0]; - t21= v3[1]-v4[1]; - t22= v3[2]-v4[2]; + t20= co3[0]-co4[0]; + t21= co3[1]-co4[1]; + t22= co3[2]-co4[2]; divdet= t20*x0+t21*x1+t22*x2; if(divdet!=0.0f) { @@ -752,10 +795,11 @@ static int intersection_strand(Isect *is) #endif /* ray - triangle or quad intersection */ -int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc) +int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc, RayCoordsFunc coordsfunc) { RayFace *face= is->face; - float *v1,*v2,*v3,*v4; + int ob= is->ob; + float *v1,*v2,*v3,*v4,co1[3],co2[3],co3[3],co4[3]; float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2; float m0, m1, m2, divdet, det1; short ok=0; @@ -767,16 +811,34 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc) coordsfunc(face, &v1, &v2, &v3, &v4); - if (v4) { + if(v4) { SWAP(float*, v3, v4); } - t00= v3[0]-v1[0]; - t01= v3[1]-v1[1]; - t02= v3[2]-v1[2]; - t10= v3[0]-v2[0]; - t11= v3[1]-v2[1]; - t12= v3[2]-v2[2]; + VECCOPY(co1, v1); + VECCOPY(co2, v2); + VECCOPY(co3, v3); + if(v4) + VECCOPY(co4, v4); + + if(ob) { + float (*mat)[4]= (float(*)[4])transformfunc(is->userdata, ob); + + if(mat) { + Mat4MulVecfl(mat, co1); + Mat4MulVecfl(mat, co2); + Mat4MulVecfl(mat, co3); + if(v4) + Mat4MulVecfl(mat, co4); + } + } + + t00= co3[0]-co1[0]; + t01= co3[1]-co1[1]; + t02= co3[2]-co1[2]; + t10= co3[0]-co2[0]; + t11= co3[1]-co2[1]; + t12= co3[2]-co2[2]; r0= is->vec[0]; r1= is->vec[1]; @@ -788,9 +850,9 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc) divdet= t00*x0+t01*x1+t02*x2; - m0= is->start[0]-v3[0]; - m1= is->start[1]-v3[1]; - m2= is->start[2]-v3[2]; + m0= is->start[0]-co3[0]; + m1= is->start[1]-co3[1]; + m2= is->start[2]-co3[2]; det1= m0*x0+m1*x1+m2*x2; if(divdet!=0.0f) { @@ -821,9 +883,9 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc) if(ok==0 && v4) { - t20= v3[0]-v4[0]; - t21= v3[1]-v4[1]; - t22= v3[2]-v4[2]; + t20= co3[0]-co4[0]; + t21= co3[1]-co4[1]; + t22= co3[2]-co4[2]; divdet= t20*x0+t21*x1+t22*x2; if(divdet!=0.0f) { @@ -874,11 +936,13 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc) coordsfunc(face, &origv1, &origv2, &origv3, &origv4); - if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++; - if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++; - if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++; - if(origv4) { - if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++; + if(ob == is->oborig) { + if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++; + if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++; + if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++; + if(origv4) { + if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++; + } } if(de) { /* so there's a shared edge or vertex, let's intersect ray with face @@ -886,8 +950,9 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc) the intersection is invalid, 0 */ if(is->facecontr==NULL) { + is->obcontr= is->oborig; is->facecontr= face; - is->faceisect= intersection2(face, coordsfunc, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2]); + is->faceisect= intersection2(face, is->oborig, transformfunc, coordsfunc, is->userdata, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2]); } if(is->faceisect) return 1; @@ -905,6 +970,7 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc) static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc checkfunc) { RayFace *face; + int ob; short nr=0; OcVal *ov; @@ -912,18 +978,21 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc c if(is->mode==RE_RAY_SHADOW) { face= no->v[0]; + ob= no->ob[0]; while(face) { - if(is->faceorig != face) { + if(!(is->faceorig == face && is->oborig == ob)) { if(checkfunc(is, face)) { ov= no->ov+nr; if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { //accepted++; + is->ob= ob; is->face= face; - if(RE_ray_face_intersection(is, oc->coordsfunc)) { + if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) { + is->ob_last= ob; is->face_last= face; return 1; } @@ -939,6 +1008,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc c nr=0; } face= no->v[nr]; + ob= no->ob[nr]; } } else { /* else mirror or glass or shadowtra, return closest face */ @@ -949,16 +1019,18 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc c isect= *is; /* copy for sorting */ face= no->v[0]; + ob= no->ob[0]; while(face) { - if(is->faceorig != face) { + if(!(is->faceorig == face && is->oborig == ob)) { if(checkfunc(is, face)) { ov= no->ov+nr; if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { //accepted++; + isect.ob= ob; isect.face= face; - if(RE_ray_face_intersection(&isect, oc->coordsfunc)) { + if(RE_ray_face_intersection(&isect, oc->transformfunc, oc->coordsfunc)) { if(isect.labdalabda) *is= isect; found= 1; } @@ -974,6 +1046,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc c nr=0; } face= no->v[nr]; + ob= no->ob[nr]; } return found; @@ -1123,17 +1196,20 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc /* do this before intersect calls */ is->facecontr= NULL; /* to check shared edge */ + is->obcontr= 0; is->faceisect= is->isect= 0; /* shared edge, quad half flag */ + is->userdata= oc->userdata; /* only for shadow! */ if(is->mode==RE_RAY_SHADOW) { /* check with last intersected shadow face */ - if(is->face_last!=NULL && is->face_last!=is->faceorig) { + if(is->face_last!=NULL && !(is->face_last==is->faceorig && is->ob_last==is->oborig)) { if(checkfunc(is, is->face_last)) { + is->ob= is->ob_last; is->face= is->face_last; VECSUB(is->vec, is->end, is->start); - if(RE_ray_face_intersection(is, oc->coordsfunc)) return 1; + if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) return 1; } } } @@ -1349,6 +1425,7 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc } /* reached end, no intersections found */ + is->ob_last= 0; is->face_last= NULL; return 0; } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index f5f1f6cec17..0a9078b32f0 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -214,7 +214,7 @@ static void halo_pixelstruct(HaloRen *har, float *rb, float dist, float xn, floa static void halo_tile(RenderPart *pa, float *pass, unsigned int lay) { - HaloRen *har = NULL; + HaloRen *har; rcti disprect= pa->disprect, testrect= pa->disprect; float dist, xsq, ysq, xn, yn, *rb; float col[4]; @@ -231,9 +231,7 @@ static void halo_tile(RenderPart *pa, float *pass, unsigned int lay) } for(a=0; a>8]; - else har++; + har= R.sortedhalos[a]; /* layer test, clip halo with y */ if((har->lay & lay)==0); @@ -388,8 +386,8 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, if(shi->totuv) { float mult= (float)count_mask(curmask)/(float)R.osa; fp= rpass->rect + 3*offset; - fp[0]+= mult*(0.5f + 0.5f*shi->uv[0].uv[0]); - fp[1]+= mult*(0.5f + 0.5f*shi->uv[0].uv[1]); + fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]); + fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]); fp[2]+= mult; } break; @@ -398,7 +396,7 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, if(shi->vlr) { fp= rpass->rect + offset; if(*fp==0.0f) - *fp= (float)shi->vlr->ob->index; + *fp= (float)shi->obr->ob->index; } break; case SCE_PASS_VECTOR: @@ -463,8 +461,8 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult break; case SCE_PASS_UV: if(shi->totuv) { - uvcol[0]= 0.5f + 0.5f*shi->uv[0].uv[0]; - uvcol[1]= 0.5f + 0.5f*shi->uv[0].uv[1]; + uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0]; + uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1]; uvcol[2]= 1.0f; col= uvcol; } @@ -476,7 +474,7 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult case SCE_PASS_INDEXOB: if(shi->vlr) { fp= rpass->rect + offset; - *fp= (float)shi->vlr->ob->index; + *fp= (float)shi->obr->ob->index; } break; } @@ -615,7 +613,7 @@ static void freeps(ListBase *lb) lb->first= lb->last= NULL; } -static void addps(ListBase *lb, long *rd, int facenr, int z, unsigned short mask) +static void addps(ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask) { PixStrMain *psm; PixStr *ps, *last= NULL; @@ -624,7 +622,7 @@ static void addps(ListBase *lb, long *rd, int facenr, int z, unsigned short mask ps= (PixStr *)(*rd); while(ps) { - if( ps->facenr == facenr ) { + if( ps->obi == obi && ps->facenr == facenr ) { ps->mask |= mask; return; } @@ -645,30 +643,13 @@ static void addps(ListBase *lb, long *rd, int facenr, int z, unsigned short mask else *rd= (long)ps; ps->next= NULL; + ps->obi= obi; ps->facenr= facenr; ps->z= z; ps->mask = mask; ps->shadfac= 0; } -static void make_pixelstructs(RenderPart *pa, ListBase *lb) -{ - long *rd= pa->rectdaps; - int *rp= pa->rectp; - int *rz= pa->rectz; - int x, y; - int mask= 1<sample; - - for(y=0; yrecty; y++) { - for(x=0; xrectx; x++, rd++, rp++) { - if(*rp) { - addps(lb, rd, *rp, *(rz+x), mask); - } - } - rz+= pa->rectx; - } -} - static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect) { float addcol[4]; @@ -704,7 +685,7 @@ static void convert_to_key_alpha(RenderPart *pa, float *rectf) } /* adds only alpha values */ -static void edge_enhance_tile(RenderPart *pa, float *rectf) +void edge_enhance_tile(RenderPart *pa, float *rectf) { /* use zbuffer to define edges, add it to the image */ int y, x, col, *rz, *rz1, *rz2, *rz3; @@ -835,6 +816,36 @@ static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dma dest[3]= (mul*dest[3]) + source[3]; } +typedef struct ZbufSolidData { + RenderLayer *rl; + ListBase *psmlist; + float *edgerect; +} ZbufSolidData; + +void make_pixelstructs(RenderPart *pa, ZSpan *zspan, int sample, void *data) +{ + ZbufSolidData *sdata= (ZbufSolidData*)data; + ListBase *lb= sdata->psmlist; + long *rd= pa->rectdaps; + int *ro= zspan->recto; + int *rp= zspan->rectp; + int *rz= zspan->rectz; + int x, y; + int mask= 1<recty; y++) { + for(x=0; xrectx; x++, rd++, rp++, ro++) { + if(*rp) { + addps(lb, rd, *ro, *rp, *(rz+x), mask); + } + } + rz+= pa->rectx; + } + + if(sdata->rl->layflag & SCE_LAY_EDGE) + if(R.r.mode & R_EDGE) + edge_enhance_tile(pa, sdata->edgerect); +} /* main call for shading Delta Accum, for OSA */ /* supposed to be fully threadable! */ @@ -845,10 +856,9 @@ void zbufshadeDA_tile(RenderPart *pa) ListBase psmlist= {NULL, NULL}; float *edgerect= NULL; - set_part_zbuf_clipflag(pa); - /* allocate the necessary buffers */ /* zbuffer inits these rects */ + pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); @@ -863,14 +873,13 @@ void zbufshadeDA_tile(RenderPart *pa) edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge"); /* always fill visibility */ - for(pa->sample=0; pa->samplesample++) { - zbuffer_solid(pa, rl->lay, rl->layflag); - make_pixelstructs(pa, &psmlist); - - if(rl->layflag & SCE_LAY_EDGE) - if(R.r.mode & R_EDGE) - edge_enhance_tile(pa, edgerect); - + for(pa->sample=0; pa->samplesample+=4) { + ZbufSolidData sdata; + + sdata.rl= rl; + sdata.psmlist= &psmlist; + sdata.edgerect= edgerect; + zbuffer_solid(pa, rl->lay, rl->layflag, make_pixelstructs, &sdata); if(R.test_break()) break; } @@ -931,7 +940,7 @@ void zbufshadeDA_tile(RenderPart *pa) } /* strand rendering */ - if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) { + if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) { float *fcol, *scol; unsigned short *strandmask, *solidmask= NULL; /* 16 bits, MAX_OSA */ int x; @@ -998,9 +1007,9 @@ void zbufshadeDA_tile(RenderPart *pa) } /* free all */ + MEM_freeN(pa->recto); pa->recto= NULL; MEM_freeN(pa->rectp); pa->rectp= NULL; MEM_freeN(pa->rectz); pa->rectz= NULL; - MEM_freeN(pa->clipflag); pa->clipflag= NULL; /* display active layer */ rr->renrect.ymin=rr->renrect.ymax= 0; @@ -1025,9 +1034,8 @@ void zbufshade_tile(RenderPart *pa) ps.next= NULL; ps.mask= 0xFFFF; - set_part_zbuf_clipflag(pa); - /* zbuffer code clears/inits rects */ + pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); @@ -1037,7 +1045,7 @@ void zbufshade_tile(RenderPart *pa) shade_sample_initialize(&ssamp, pa, rl); addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); - zbuffer_solid(pa, rl->lay, rl->layflag); + zbuffer_solid(pa, rl->lay, rl->layflag, NULL, NULL); if(!R.test_break()) { /* NOTE: this if() is not consistant */ @@ -1055,7 +1063,8 @@ void zbufshade_tile(RenderPart *pa) if(rl->layflag & SCE_LAY_SOLID) { float *fcol= rl->rectf; - int x, y, *rp= pa->rectp, *rz= pa->rectz, offs=0, seed; + int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz; + int x, y, offs=0, seed; /* we set per pixel a fixed seed, for random AO and shadow samples */ seed= pa->rectx*pa->disprect.ymin; @@ -1065,15 +1074,19 @@ void zbufshade_tile(RenderPart *pa) ISB_create(pa, NULL); for(y=pa->disprect.ymin; ydisprect.ymax; y++, rr->renrect.ymax++) { - for(x=pa->disprect.xmin; xdisprect.xmax; x++, rz++, rp++, fcol+=4, offs++) { + for(x=pa->disprect.xmin; xdisprect.xmax; x++, ro++, rz++, rp++, fcol+=4, offs++) { /* per pixel fixed seed */ BLI_thread_srandom(pa->thread, seed++); if(*rp) { + ps.obi= *ro; ps.facenr= *rp; ps.z= *rz; if(shade_samples(&ssamp, &ps, x, y)) { QUATCOPY(fcol, ssamp.shr[0].combined); + + if(!(fcol[0] == fcol[0])) + printvecf("fudgecol", fcol); /* passes */ if(addpassflag) @@ -1124,7 +1137,7 @@ void zbufshade_tile(RenderPart *pa) } /* strand rendering */ - if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) { + if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) { float *fcol, *scol; int x; @@ -1169,9 +1182,9 @@ void zbufshade_tile(RenderPart *pa) rr->renrect.ymin=rr->renrect.ymax= 0; rr->renlay= render_get_active_layer(&R, rr); + MEM_freeN(pa->recto); pa->recto= NULL; MEM_freeN(pa->rectp); pa->rectp= NULL; MEM_freeN(pa->rectz); pa->rectz= NULL; - MEM_freeN(pa->clipflag); pa->clipflag= NULL; } /* SSS preprocess tile render, fully threadable */ @@ -1181,7 +1194,7 @@ typedef struct ZBufSSSHandle { int totps; } ZBufSSSHandle; -static void addps_sss(void *cb_handle, int facenr, int x, int y, int z) +static void addps_sss(void *cb_handle, int obi, int facenr, int x, int y, int z) { ZBufSSSHandle *handle = cb_handle; RenderPart *pa= handle->pa; @@ -1196,54 +1209,50 @@ static void addps_sss(void *cb_handle, int facenr, int x, int y, int z) if(pa->rectall) { long *rs= pa->rectall + pa->rectx*y + x; - addps(&handle->psmlist, rs, facenr, z, 0); + addps(&handle->psmlist, rs, obi, facenr, z, 0); handle->totps++; } if(pa->rectz) { int *rz= pa->rectz + pa->rectx*y + x; int *rp= pa->rectp + pa->rectx*y + x; + int *ro= pa->recto + pa->rectx*y + x; if(z < *rz) { if(*rp == 0) handle->totps++; *rz= z; *rp= facenr; + *ro= obi; } } if(pa->rectbackz) { int *rz= pa->rectbackz + pa->rectx*y + x; int *rp= pa->rectbackp + pa->rectx*y + x; + int *ro= pa->rectbacko + pa->rectx*y + x; if(z >= *rz) { if(*rp == 0) handle->totps++; *rz= z; *rp= facenr; + *ro= obi; } } } -static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, int quad, float x, float y, float z, float *co, float *color, float *area) +static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRen *obi, VlakRen *vlr, int quad, float x, float y, float z, float *co, float *color, float *area) { ShadeInput *shi= ssamp->shi; ShadeResult shr; float texfac, orthoarea, nor[3]; - /* normal flipping must be disabled to make back scattering work, so that - backside faces actually face any lighting from the back */ - shi->puno= 0; - /* cache for shadow */ shi->samplenr++; if(quad) - shade_input_set_triangle_i(shi, vlr, 0, 2, 3); + shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); else - shade_input_set_triangle_i(shi, vlr, 0, 1, 2); - - /* we don't want flipped normals, they screw up back scattering */ - if(vlr->noflag & R_FLIPPED_NO) - VecMulf(shi->facenor, -1.0f); + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); /* center pixel */ x += 0.5f; @@ -1269,8 +1278,12 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, in shade_input_set_uv(shi); shade_input_set_normals(shi); + /* we don't want flipped normals, they screw up back scattering */ + if(shi->flippednor) + shade_input_flip_normals(shi); + /* not a pretty solution, but fixes common cases */ - if(vlr->ob && vlr->ob->transflag & OB_NEG_SCALE) { + if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { VecMulf(shi->vn, -1.0f); VecMulf(shi->vno, -1.0f); } @@ -1311,15 +1324,16 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, in static void zbufshade_sss_free(RenderPart *pa) { - MEM_freeN(pa->clipflag); pa->clipflag= NULL; #if 0 MEM_freeN(pa->rectall); pa->rectall= NULL; freeps(&handle.psmlist); #else MEM_freeN(pa->rectz); pa->rectz= NULL; MEM_freeN(pa->rectp); pa->rectp= NULL; + MEM_freeN(pa->recto); pa->recto= NULL; MEM_freeN(pa->rectbackz); pa->rectbackz= NULL; MEM_freeN(pa->rectbackp); pa->rectbackp= NULL; + MEM_freeN(pa->rectbacko); pa->rectbacko= NULL; #endif } @@ -1334,15 +1348,13 @@ void zbufshade_sss_tile(RenderPart *pa) Material *mat= re->sss_mat; float (*co)[3], (*color)[3], *area, *fcol= rl->rectf; int x, y, seed, quad, totpoint, display = !(re->r.scemode & R_PREVIEWBUTS); - int *rz, *rp, *rbz, *rbp; + int *ro, *rz, *rp, *rbo, *rbz, *rbp; #if 0 PixStr *ps; long *rs; int z; #endif - set_part_zbuf_clipflag(pa); - /* setup pixelstr list and buffer for zbuffering */ handle.pa= pa; handle.totps= 0; @@ -1353,8 +1365,10 @@ void zbufshade_sss_tile(RenderPart *pa) pa->rectall= MEM_callocN(sizeof(long)*pa->rectx*pa->recty+4, "rectall"); #else + pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); + pa->rectbacko= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbacko"); pa->rectbackp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackp"); pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz"); #endif @@ -1397,8 +1411,10 @@ void zbufshade_sss_tile(RenderPart *pa) #else rz= pa->rectz; rp= pa->rectp; + ro= pa->recto; rbz= pa->rectbackz; rbp= pa->rectbackp; + rbo= pa->rectbacko; #endif totpoint= 0; @@ -1411,11 +1427,13 @@ void zbufshade_sss_tile(RenderPart *pa) if(rs) { /* for each sample in this pixel, shade it */ for(ps=(PixStr*)*rs; ps; ps=ps->next) { - vlr= RE_findOrAddVlak(re, (ps->facenr-1) & RE_QUAD_MASK); + ObjectInstanceRen *obi= &re->objectinstance[ps->obi]; + ObjectRen *obr= obi->obr; + vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK); quad= (ps->facenr & RE_QUAD_OFFS); z= ps->z; - shade_sample_sss(&ssamp, mat, vlr, quad, x, y, z, + shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, z, co[totpoint], color[totpoint], &area[totpoint]); totpoint++; @@ -1429,11 +1447,14 @@ void zbufshade_sss_tile(RenderPart *pa) #else if(rp) { if(*rp != 0) { + ObjectInstanceRen *obi= &re->objectinstance[*ro]; + ObjectRen *obr= obi->obr; + /* shade front */ - vlr= RE_findOrAddVlak(re, (*rp-1) & RE_QUAD_MASK); + vlr= RE_findOrAddVlak(obr, (*rp-1) & RE_QUAD_MASK); quad= ((*rp) & RE_QUAD_OFFS); - shade_sample_sss(&ssamp, mat, vlr, quad, x, y, *rz, + shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rz, co[totpoint], color[totpoint], &area[totpoint]); VECADD(fcol, fcol, color[totpoint]); @@ -1441,16 +1462,19 @@ void zbufshade_sss_tile(RenderPart *pa) totpoint++; } - rp++; rz++; + rp++; rz++; ro++; } if(rbp) { - if(*rbp != 0 && *rbp != *(rp-1)) { + if(*rbp != 0 && !(*rbp == *(rp-1) && *rbo == *(ro-1))) { + ObjectInstanceRen *obi= &re->objectinstance[*rbo]; + ObjectRen *obr= obi->obr; + /* shade back */ - vlr= RE_findOrAddVlak(re, (*rbp-1) & RE_QUAD_MASK); + vlr= RE_findOrAddVlak(obr, (*rbp-1) & RE_QUAD_MASK); quad= ((*rbp) & RE_QUAD_OFFS); - shade_sample_sss(&ssamp, mat, vlr, quad, x, y, *rbz, + shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rbz, co[totpoint], color[totpoint], &area[totpoint]); /* to indicate this is a back sample */ @@ -1461,7 +1485,7 @@ void zbufshade_sss_tile(RenderPart *pa) totpoint++; } - rbz++; rbp++; + rbz++; rbp++; rbo++; } #endif } @@ -1637,7 +1661,7 @@ void add_halo_flare(Render *re) { RenderResult *rr= re->result; RenderLayer *rl; - HaloRen *har = NULL; + HaloRen *har; int a, mode, do_draw=0; /* for now, we get the first renderlayer in list with halos set */ @@ -1654,8 +1678,7 @@ void add_halo_flare(Render *re) project_renderdata(&R, projectverto, 0, 0, 0); for(a=0; a>8]; - else har++; + har= R.sortedhalos[a]; if(har->flarec) { do_draw= 1; @@ -1708,6 +1731,7 @@ void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *shr) typedef struct BakeShade { ShadeSample ssamp; + ObjectInstanceRen *obi; VlakRen *vlr; ZSpan *zspan; @@ -1723,34 +1747,31 @@ typedef struct BakeShade { float *rect_float; } BakeShade; -static void bake_set_shade_input(VlakRen *vlr, ShadeInput *shi, int quad, int isect, int x, int y, float u, float v) +static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int isect, int x, int y, float u, float v) { if(isect) { /* raytrace intersection with different u,v than scanconvert */ if(vlr->v4) { if(quad) - shade_input_set_triangle_i(shi, vlr, 2, 1, 3); + shade_input_set_triangle_i(shi, obi, vlr, 2, 1, 3); else - shade_input_set_triangle_i(shi, vlr, 0, 1, 3); + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 3); } else - shade_input_set_triangle_i(shi, vlr, 0, 1, 2); + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); } else { /* regular scanconvert */ if(quad) - shade_input_set_triangle_i(shi, vlr, 0, 2, 3); + shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); else - shade_input_set_triangle_i(shi, vlr, 0, 1, 2); + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); } /* set up view vector */ VECCOPY(shi->view, shi->co); Normalize(shi->view); - /* no face normal flip */ - shi->puno= 0; - /* cache for shadow */ shi->samplenr++; @@ -1760,13 +1781,18 @@ static void bake_set_shade_input(VlakRen *vlr, ShadeInput *shi, int quad, int is shi->ys= y; shade_input_set_normals(shi); + + /* no normal flip */ + if(shi->flippednor) + shade_input_flip_normals(shi); } -static void bake_shade(void *handle, Object *ob, VlakRen *vlr, ShadeInput *shi, int quad, int x, int y, float u, float v, float *tvn, float *ttang) +static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int x, int y, float u, float v, float *tvn, float *ttang) { BakeShade *bs= handle; ShadeSample *ssamp= &bs->ssamp; ShadeResult shr; + VlakRen *vlr= shi->vlr; /* init material vars */ memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h @@ -1850,9 +1876,9 @@ static int bake_check_intersect(Isect *is, RayFace *face) BakeShade *bs = (BakeShade*)is->userdata; /* no direction checking for now, doesn't always improve the result - * (INPR(vlr->n, bs->dir) > 0.0f); */ + * (INPR(shi->facenor, bs->dir) > 0.0f); */ - return (vlr->ob != bs->actob); + return (vlr->obr->ob != bs->actob); } static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *dir, float sign, float *hitco) @@ -1884,7 +1910,8 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) { BakeShade *bs= handle; VlakRen *vlr= bs->vlr; - Object *ob= vlr->ob; + ObjectInstanceRen *obi= bs->obi; + Object *ob= obi->obr->ob; float l, *v1, *v2, *v3, tvn[3], ttang[3]; int quad; ShadeSample *ssamp= &bs->ssamp; @@ -1913,8 +1940,11 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1]; shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2]; + if(obi->flag & R_TRANSFORMED) + Mat4MulVecfl(obi->mat, shi->co); + quad= bs->quad; - bake_set_shade_input(vlr, shi, quad, 0, x, y, u, v); + bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v); if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) { shade_input_set_shade_texco(shi); @@ -1940,6 +1970,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) VECCOPY(isec.start, shi->co); isec.mode= RE_RAY_MIRROR; isec.faceorig= (RayFace*)vlr; + isec.oborig= RAY_OBJECT_SET(&R, obi); isec.userdata= bs; if(bake_intersect_tree(R.raytree, &isec, shi->vn, sign, co)) { @@ -1954,77 +1985,86 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) /* if hit, we shade from the new point, otherwise from point one starting face */ if(hit) { vlr= (VlakRen*)minisec.face; + obi= RAY_OBJECT_GET(&R, minisec.ob); quad= (minisec.isect == 2); VECCOPY(shi->co, minco); u= -minisec.u; v= -minisec.v; - bake_set_shade_input(vlr, shi, quad, 1, x, y, u, v); + bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v); } } if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) - bake_shade(handle, ob, vlr, shi, quad, x, y, u, v, tvn, ttang); + bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang); else - bake_shade(handle, ob, vlr, shi, quad, x, y, u, v, 0, 0); + bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0); } static int get_next_bake_face(BakeShade *bs) { + ObjectRen *obr; VlakRen *vlr; MTFace *tface; static int v= 0, vdone= 0; + static ObjectInstanceRen *obi= NULL; if(bs==NULL) { vlr= NULL; v= vdone= 0; + obi= R.instancetable.first; return 0; } BLI_lock_thread(LOCK_CUSTOM1); - - for(; vactob && bs->actob == vlr->ob) || (!bs->actob && (vlr->ob->flag & SELECT))) { - tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0); - if(tface && tface->tpage) { - Image *ima= tface->tpage; - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; - - if(ibuf==NULL) - continue; - - if(ibuf->rect==NULL && ibuf->rect_float==NULL) - continue; - - if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) - continue; - - /* find the image for the first time? */ - if(ima->id.flag & LIB_DOIT) { - ima->id.flag &= ~LIB_DOIT; + for(; obi; obi=obi->next, v=0) { + obr= obi->obr; + + for(; vtotvlak; v++) { + vlr= RE_findOrAddVlak(obr, v); + + if((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) { + tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); + + if(tface && tface->tpage) { + Image *ima= tface->tpage; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; - /* we either fill in float or char, this ensures things go fine */ - if(ibuf->rect_float) - imb_freerectImBuf(ibuf); - /* clear image */ - if(R.r.bake_flag & R_BAKE_CLEAR) - IMB_rectfill(ibuf, vec); - - /* might be read by UI to set active image for display */ - R.bakebuf= ima; - } - - bs->vlr= vlr; - - bs->vdone++; /* only for error message if nothing was rendered */ - v++; - - BLI_unlock_thread(LOCK_CUSTOM1); - return 1; + if(ibuf==NULL) + continue; + + if(ibuf->rect==NULL && ibuf->rect_float==NULL) + continue; + + if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) + continue; + + /* find the image for the first time? */ + if(ima->id.flag & LIB_DOIT) { + ima->id.flag &= ~LIB_DOIT; + + /* we either fill in float or char, this ensures things go fine */ + if(ibuf->rect_float) + imb_freerectImBuf(ibuf); + /* clear image */ + if(R.r.bake_flag & R_BAKE_CLEAR) + IMB_rectfill(ibuf, vec); + + /* might be read by UI to set active image for display */ + R.bakebuf= ima; + } + + bs->obi= obi; + bs->vlr= vlr; + + bs->vdone++; /* only for error message if nothing was rendered */ + v++; + + BLI_unlock_thread(LOCK_CUSTOM1); + return 1; + } } } } @@ -2037,7 +2077,9 @@ static int get_next_bake_face(BakeShade *bs) static void shade_tface(BakeShade *bs) { VlakRen *vlr= bs->vlr; - MTFace *tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0); + ObjectInstanceRen *obi= bs->obi; + ObjectRen *obr= obi->obr; + MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); Image *ima= tface->tpage; float vec[4][2]; int a, i1, i2, i3; @@ -2048,7 +2090,7 @@ static void shade_tface(BakeShade *bs) bs->ibuf= BKE_image_get_ibuf(ima, NULL); /* note, these calls only free/fill contents of zspan struct, not zspan itself */ zbuf_free_span(bs->zspan); - zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y); + zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); } bs->rectx= bs->ibuf->x; @@ -2099,6 +2141,10 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob) ListBase threads; Image *ima; int a, vdone=0; + + /* initialize render global */ + R= *re; + R.bakebuf= NULL; /* initialize static vars */ get_next_bake_face(NULL); @@ -2107,10 +2153,6 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob) for(ima= G.main->image.first; ima; ima= ima->id.next) ima->id.flag |= LIB_DOIT; - /* initialize render global */ - R= *re; - R.bakebuf= NULL; - BLI_init_threads(&threads, do_bake_thread, re->r.threads); /* get the threads running */ diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 1d490637222..3906b1fc001 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -62,6 +62,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_memarena.h" #include "DNA_material_types.h" @@ -104,30 +105,30 @@ #define RE_UV_ELEMS 2 #define RE_SURFNOR_ELEMS 3 -float *RE_vertren_get_sticky(Render *re, VertRen *ver, int verify) +float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify) { float *sticky; int nr= ver->index>>8; - sticky= re->vertnodes[nr].sticky; + sticky= obr->vertnodes[nr].sticky; if(sticky==NULL) { if(verify) - sticky= re->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table"); + sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table"); else return NULL; } return sticky + (ver->index & 255)*RE_STICKY_ELEMS; } -float *RE_vertren_get_stress(Render *re, VertRen *ver, int verify) +float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify) { float *stress; int nr= ver->index>>8; - stress= re->vertnodes[nr].stress; + stress= obr->vertnodes[nr].stress; if(stress==NULL) { if(verify) - stress= re->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table"); + stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table"); else return NULL; } @@ -135,30 +136,30 @@ float *RE_vertren_get_stress(Render *re, VertRen *ver, int verify) } /* this one callocs! */ -float *RE_vertren_get_rad(Render *re, VertRen *ver, int verify) +float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify) { float *rad; int nr= ver->index>>8; - rad= re->vertnodes[nr].rad; + rad= obr->vertnodes[nr].rad; if(rad==NULL) { if(verify) - rad= re->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table"); + rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table"); else return NULL; } return rad + (ver->index & 255)*RE_RAD_ELEMS; } -float *RE_vertren_get_strand(Render *re, VertRen *ver, int verify) +float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify) { float *strand; int nr= ver->index>>8; - strand= re->vertnodes[nr].strand; + strand= obr->vertnodes[nr].strand; if(strand==NULL) { if(verify) - strand= re->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table"); + strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table"); else return NULL; } @@ -166,15 +167,15 @@ float *RE_vertren_get_strand(Render *re, VertRen *ver, int verify) } /* needs calloc */ -float *RE_vertren_get_tangent(Render *re, VertRen *ver, int verify) +float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify) { float *tangent; int nr= ver->index>>8; - tangent= re->vertnodes[nr].tangent; + tangent= obr->vertnodes[nr].tangent; if(tangent==NULL) { if(verify) - tangent= re->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table"); + tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table"); else return NULL; } @@ -182,64 +183,62 @@ float *RE_vertren_get_tangent(Render *re, VertRen *ver, int verify) } /* needs calloc! not all renderverts have them */ -float *RE_vertren_get_winspeed(Render *re, VertRen *ver, int verify) +/* also winspeed is exception, it is stored per instance */ +float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify) { float *winspeed; - int nr= ver->index>>8; + int totvector; - winspeed= re->vertnodes[nr].winspeed; + winspeed= obi->vectors; if(winspeed==NULL) { - if(verify) - winspeed= re->vertnodes[nr].winspeed= MEM_callocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table"); + if(verify) { + totvector= obi->obr->totvert + obi->obr->totstrand; + winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table"); + } else return NULL; } - return winspeed + (ver->index & 255)*RE_WINSPEED_ELEMS; + return winspeed + ver->index*RE_WINSPEED_ELEMS; } -VertRen *RE_vertren_copy(Render *re, VertRen *ver) +VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver) { - VertRen *v1= RE_findOrAddVert(re, re->totvert++); + VertRen *v1= RE_findOrAddVert(obr, obr->totvert++); float *fp1, *fp2; int index= v1->index; *v1= *ver; v1->index= index; - fp1= RE_vertren_get_sticky(re, ver, 0); + fp1= RE_vertren_get_sticky(obr, ver, 0); if(fp1) { - fp2= RE_vertren_get_sticky(re, v1, 1); + fp2= RE_vertren_get_sticky(obr, v1, 1); memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float)); } - fp1= RE_vertren_get_stress(re, ver, 0); + fp1= RE_vertren_get_stress(obr, ver, 0); if(fp1) { - fp2= RE_vertren_get_stress(re, v1, 1); + fp2= RE_vertren_get_stress(obr, v1, 1); memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float)); } - fp1= RE_vertren_get_rad(re, ver, 0); + fp1= RE_vertren_get_rad(obr, ver, 0); if(fp1) { - fp2= RE_vertren_get_rad(re, v1, 1); + fp2= RE_vertren_get_rad(obr, v1, 1); memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float)); } - fp1= RE_vertren_get_strand(re, ver, 0); + fp1= RE_vertren_get_strand(obr, ver, 0); if(fp1) { - fp2= RE_vertren_get_strand(re, v1, 1); + fp2= RE_vertren_get_strand(obr, v1, 1); memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float)); } - fp1= RE_vertren_get_tangent(re, ver, 0); + fp1= RE_vertren_get_tangent(obr, ver, 0); if(fp1) { - fp2= RE_vertren_get_tangent(re, v1, 1); + fp2= RE_vertren_get_tangent(obr, v1, 1); memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float)); } - fp1= RE_vertren_get_winspeed(re, ver, 0); - if(fp1) { - fp2= RE_vertren_get_winspeed(re, v1, 1); - memcpy(fp2, fp1, RE_WINSPEED_ELEMS*sizeof(float)); - } return v1; } -VertRen *RE_findOrAddVert(Render *re, int nr) +VertRen *RE_findOrAddVert(ObjectRen *obr, int nr) { VertTableNode *temp; VertRen *v; @@ -251,23 +250,23 @@ VertRen *RE_findOrAddVert(Render *re, int nr) } a= nr>>8; - if (a>=re->vertnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */ - temp= re->vertnodes; + if (a>=obr->vertnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */ + temp= obr->vertnodes; - re->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(re->vertnodeslen+TABLEINITSIZE) , "vertnodes"); - if(temp) memcpy(re->vertnodes, temp, re->vertnodeslen*sizeof(VertTableNode)); - memset(re->vertnodes+re->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode)); + obr->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(obr->vertnodeslen+TABLEINITSIZE) , "vertnodes"); + if(temp) memcpy(obr->vertnodes, temp, obr->vertnodeslen*sizeof(VertTableNode)); + memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode)); - re->vertnodeslen+=TABLEINITSIZE; + obr->vertnodeslen+=TABLEINITSIZE; if(temp) MEM_freeN(temp); } - v= re->vertnodes[a].vert; + v= obr->vertnodes[a].vert; if(v==NULL) { int i; v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert"); - re->vertnodes[a].vert= v; + obr->vertnodes[a].vert= v; for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) { v[a].index= i; @@ -279,120 +278,94 @@ VertRen *RE_findOrAddVert(Render *re, int nr) /* ------------------------------------------------------------------------ */ -MTFace *RE_vlakren_get_tface(Render *re, VlakRen *vlr, int n, char **name, int verify) +MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify) { VlakTableNode *node; int nr= vlr->index>>8, vlakindex= (vlr->index&255); int index= (n<<8) + vlakindex; - node= &re->vlaknodes[nr]; + node= &obr->vlaknodes[nr]; if(verify) { if(n>=node->totmtface) { - MTFace **mtface= node->mtface; + MTFace *mtface= node->mtface; int size= size= (n+1)*256; - node->mtface= MEM_callocN(size*sizeof(MTFace*), "Vlak mtface"); + node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface"); if(mtface) { size= node->totmtface*256; - memcpy(node->mtface, mtface, size*sizeof(MTFace*)); + memcpy(node->mtface, mtface, size*sizeof(MTFace)); MEM_freeN(mtface); } node->totmtface= n+1; - - if (!node->names) { - size= sizeof(*node->names)*256; - node->names= MEM_callocN(size, "Vlak names"); - } - } - - if(node->mtface[index]==NULL) { - node->mtface[index]= BLI_memarena_alloc(re->memArena, - sizeof(MTFace)*RE_MTFACE_ELEMS); - - node->names[vlakindex]= re->customdata_names.last; } } else { - if(n>=node->totmtface || node->mtface[index]==NULL) + if(n>=node->totmtface) return NULL; - if(name) *name= node->names[vlakindex]->mtface[n]; + if(name) *name= obr->mtface[n]; } - return node->mtface[index]; + return node->mtface + index; } -MCol *RE_vlakren_get_mcol(Render *re, VlakRen *vlr, int n, char **name, int verify) +MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify) { VlakTableNode *node; int nr= vlr->index>>8, vlakindex= (vlr->index&255); int index= (n<<8) + vlakindex; - node= &re->vlaknodes[nr]; + node= &obr->vlaknodes[nr]; if(verify) { if(n>=node->totmcol) { - MCol **mcol= node->mcol; + MCol *mcol= node->mcol; int size= (n+1)*256; - node->mcol= MEM_callocN(size*sizeof(MCol*), "Vlak mcol"); + node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol"); if(mcol) { size= node->totmcol*256; - memcpy(node->mcol, mcol, size*sizeof(MCol*)); + memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS); MEM_freeN(mcol); } node->totmcol= n+1; - - if (!node->names) { - size= sizeof(*node->names)*256; - node->names= MEM_callocN(size, "Vlak names"); - } - } - - if(node->mcol[index]==NULL) { - node->mcol[index]= BLI_memarena_alloc(re->memArena, - sizeof(MCol)*RE_MCOL_ELEMS); - - node->names[vlakindex]= re->customdata_names.last; } } else { - if(n>=node->totmcol || node->mcol[index]==NULL) + if(n>=node->totmcol) return NULL; - if(name) *name= node->names[vlakindex]->mcol[n]; + if(name) *name= obr->mcol[n]; } - return node->mcol[index]; + return node->mcol + index*RE_MCOL_ELEMS; } -float *RE_vlakren_get_surfnor(Render *re, VlakRen *vlak, int verify) +float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify) { float *surfnor; int nr= vlak->index>>8; - surfnor= re->vlaknodes[nr].surfnor; + surfnor= obr->vlaknodes[nr].surfnor; if(surfnor==NULL) { if(verify) - surfnor= re->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table"); + surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table"); else return NULL; } return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS; } -VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr) +VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr) { - VlakRen *vlr1 = RE_findOrAddVlak(re, re->totvlak++); + VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++); MTFace *mtface, *mtface1; MCol *mcol, *mcol1; - VlakTableNode *node = &re->vlaknodes[vlr->index>>8]; - VlakTableNode *node1 = &re->vlaknodes[vlr1->index>>8]; float *surfnor, *surfnor1; int i, index = vlr1->index; char *name; @@ -400,72 +373,101 @@ VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr) *vlr1= *vlr; vlr1->index= index; - for (i=0; (mtface=RE_vlakren_get_tface(re, vlr, i, &name, 0)) != NULL; i++) { - mtface1= RE_vlakren_get_tface(re, vlr1, i, &name, 1); + for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) { + mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1); memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS); } - for (i=0; (mcol=RE_vlakren_get_mcol(re, vlr, i, &name, 0)) != NULL; i++) { - mcol1= RE_vlakren_get_mcol(re, vlr1, i, &name, 1); + for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) { + mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1); memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS); } - surfnor= RE_vlakren_get_surfnor(re, vlr, 0); + surfnor= RE_vlakren_get_surfnor(obr, vlr, 0); if(surfnor) { - surfnor1= RE_vlakren_get_surfnor(re, vlr1, 1); + surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1); VECCOPY(surfnor1, surfnor); } - if (node->names && node1->names) - node1->names[vlr1->index&255] = node->names[vlr->index&255]; - return vlr1; } -static int vlakren_remap_layer_num(int n, int active) +int RE_vlakren_get_normal(Render *re, ObjectInstanceRen *obi, VlakRen *vlr, float *nor) { - /* make the active layer the first */ - if (n == active) return 0; - else if (n < active) return n+1; - else return n; + float xn, yn, zn, v1[3]; + float (*imat)[3]= obi->imat; + int flipped= 0; + + if(obi->flag & R_TRANSFORMED) { + xn= vlr->n[0]; + yn= vlr->n[1]; + zn= vlr->n[2]; + + /* transpose! */ + nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + } + else + VECCOPY(nor, vlr->n); + + if((vlr->flag & R_NOPUNOFLIP)==0) { + if(re->r.mode & R_ORTHO) { + if(nor[2] > 0.0f) + flipped= 1; + } + else { + VECCOPY(v1, vlr->v1->co); + if(obi->flag & R_TRANSFORMED) + Mat4MulVecfl(obi->mat, v1); + if(INPR(v1, nor) < 0.0f) { + flipped= 1; + } + } + + if(flipped) { + nor[0]= -nor[0]; + nor[1]= -nor[1]; + nor[2]= -nor[2]; + } + } + + return flipped; } -void RE_vlakren_set_customdata_names(Render *re, CustomData *data) +void RE_set_customdata_names(ObjectRen *obr, CustomData *data) { /* CustomData layer names are stored per object here, because the DerivedMesh which stores the layers is freed */ - CustomDataNames *cdn= MEM_callocN(sizeof(*cdn), "CustomDataNames"); CustomDataLayer *layer; - int numlayers, i, mtfn, mcn, n; - - BLI_addtail(&re->customdata_names, cdn); + int numlayers, i, mtfn, mcn; if (CustomData_has_layer(data, CD_MTFACE)) { numlayers= CustomData_number_of_layers(data, CD_MTFACE); - cdn->mtface= MEM_callocN(sizeof(*cdn->mtface)*numlayers, "mtfacenames"); + obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numlayers, "mtfacenames"); } if (CustomData_has_layer(data, CD_MCOL)) { numlayers= CustomData_number_of_layers(data, CD_MCOL); - cdn->mcol= MEM_callocN(sizeof(*cdn->mcol)*numlayers, "mcolnames"); + obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numlayers, "mcolnames"); } for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) { layer= &data->layers[i]; if (layer->type == CD_MTFACE) { - n= vlakren_remap_layer_num(mtfn++, layer->active_rnd); - strcpy(cdn->mtface[n], layer->name); + strcpy(obr->mtface[mtfn++], layer->name); + obr->actmtface= layer->active_rnd; } else if (layer->type == CD_MCOL) { - n= vlakren_remap_layer_num(mcn++, layer->active_rnd); - strcpy(cdn->mcol[n], layer->name); + strcpy(obr->mcol[mcn++], layer->name); + obr->actmcol= layer->active_rnd; } } } -VlakRen *RE_findOrAddVlak(Render *re, int nr) +VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr) { VlakTableNode *temp; VlakRen *v; @@ -473,28 +475,28 @@ VlakRen *RE_findOrAddVlak(Render *re, int nr) if(nr<0) { printf("error in findOrAddVlak: %d\n",nr); - return re->vlaknodes[0].vlak; + return obr->vlaknodes[0].vlak; } a= nr>>8; - if (a>=re->vlaknodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ - temp= re->vlaknodes; + if (a>=obr->vlaknodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ + temp= obr->vlaknodes; - re->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(re->vlaknodeslen+TABLEINITSIZE) , "vlaknodes"); - if(temp) memcpy(re->vlaknodes, temp, re->vlaknodeslen*sizeof(VlakTableNode)); - memset(re->vlaknodes+re->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode)); + obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE) , "vlaknodes"); + if(temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode)); + memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode)); - re->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ + obr->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ if(temp) MEM_freeN(temp); } - v= re->vlaknodes[a].vlak; + v= obr->vlaknodes[a].vlak; if(v==NULL) { int i; v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak"); - re->vlaknodes[a].vlak= v; + obr->vlaknodes[a].vlak= v; for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) v[a].index= i; @@ -505,129 +507,108 @@ VlakRen *RE_findOrAddVlak(Render *re, int nr) /* ------------------------------------------------------------------------ */ -float *RE_strandren_get_winspeed(Render *re, StrandRen *strand, int verify) -{ - float *winspeed; - int nr= strand->index>>8; - - winspeed= re->strandnodes[nr].winspeed; - if(winspeed==NULL) { - if(verify) - winspeed= re->strandnodes[nr].winspeed= MEM_callocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table"); - else - return NULL; - } - return winspeed + (strand->index & 255)*RE_WINSPEED_ELEMS; -} - -float *RE_strandren_get_surfnor(Render *re, StrandRen *strand, int verify) +float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify) { float *surfnor; int nr= strand->index>>8; - surfnor= re->strandnodes[nr].surfnor; + surfnor= obr->strandnodes[nr].surfnor; if(surfnor==NULL) { if(verify) - surfnor= re->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table"); + surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table"); else return NULL; } return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS; } -float *RE_strandren_get_uv(Render *re, StrandRen *strand, int n, char **name, int verify) +float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify) { StrandTableNode *node; int nr= strand->index>>8, strandindex= (strand->index&255); int index= (n<<8) + strandindex; - node= &re->strandnodes[nr]; + node= &obr->strandnodes[nr]; if(verify) { if(n>=node->totuv) { - float **uv= node->uv; + float *uv= node->uv; int size= (n+1)*256; - node->uv= MEM_callocN(size*sizeof(float*), "Strand uv"); + node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "Strand uv"); if(uv) { size= node->totuv*256; - memcpy(node->uv, uv, size*sizeof(float*)); + memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS); MEM_freeN(uv); } node->totuv= n+1; - - if (!node->names) { - size= sizeof(*node->names)*256; - node->names= MEM_callocN(size, "Strand names"); - } - } - - if(node->uv[index]==NULL) { - node->uv[index]= BLI_memarena_alloc(re->memArena, - sizeof(float)*RE_UV_ELEMS); - - node->names[strandindex]= re->customdata_names.last; } } else { - if(n>=node->totuv || node->uv[index]==NULL) + if(n>=node->totuv) return NULL; - if(name) *name= node->names[strandindex]->mtface[n]; + if(name) *name= obr->mtface[n]; } - return node->uv[index]; + return node->uv + index*RE_UV_ELEMS; } -MCol *RE_strandren_get_mcol(Render *re, StrandRen *strand, int n, char **name, int verify) +MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify) { StrandTableNode *node; int nr= strand->index>>8, strandindex= (strand->index&255); int index= (n<<8) + strandindex; - node= &re->strandnodes[nr]; + node= &obr->strandnodes[nr]; if(verify) { if(n>=node->totmcol) { - MCol **mcol= node->mcol; + MCol *mcol= node->mcol; int size= (n+1)*256; - node->mcol= MEM_callocN(size*sizeof(MCol*), "Strand mcol"); + node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Strand mcol"); if(mcol) { size= node->totmcol*256; - memcpy(node->mcol, mcol, size*sizeof(MCol*)); + memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS); MEM_freeN(mcol); } node->totmcol= n+1; - - if (!node->names) { - size= sizeof(*node->names)*256; - node->names= MEM_callocN(size, "Strand names"); - } - } - - if(node->mcol[index]==NULL) { - node->mcol[index]= BLI_memarena_alloc(re->memArena, - sizeof(MCol)*RE_MCOL_ELEMS); - - node->names[strandindex]= re->customdata_names.last; } } else { - if(n>=node->totmcol || node->mcol[index]==NULL) + if(n>=node->totmcol) return NULL; - if(name) *name= node->names[strandindex]->mcol[n]; + if(name) *name= obr->mcol[n]; } - return node->mcol[index]; + return node->mcol + index*RE_MCOL_ELEMS; } -StrandRen *RE_findOrAddStrand(Render *re, int nr) +/* winspeed is exception, it is stored per instance */ +float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify) +{ + float *winspeed; + int totvector; + + winspeed= obi->vectors; + if(winspeed==NULL) { + if(verify) { + totvector= obi->obr->totvert + obi->obr->totstrand; + winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table"); + } + else + return NULL; + } + return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS; +} + +StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr) { StrandTableNode *temp; StrandRen *v; @@ -635,28 +616,28 @@ StrandRen *RE_findOrAddStrand(Render *re, int nr) if(nr<0) { printf("error in findOrAddStrand: %d\n",nr); - return re->strandnodes[0].strand; + return obr->strandnodes[0].strand; } a= nr>>8; - if (a>=re->strandnodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ - temp= re->strandnodes; + if (a>=obr->strandnodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ + temp= obr->strandnodes; - re->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(re->strandnodeslen+TABLEINITSIZE) , "strandnodes"); - if(temp) memcpy(re->strandnodes, temp, re->strandnodeslen*sizeof(StrandTableNode)); - memset(re->strandnodes+re->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode)); + obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE) , "strandnodes"); + if(temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode)); + memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode)); - re->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ + obr->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ if(temp) MEM_freeN(temp); } - v= re->strandnodes[a].strand; + v= obr->strandnodes[a].strand; if(v==NULL) { int i; v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand"); - re->strandnodes[a].strand= v; + obr->strandnodes[a].strand= v; for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) v[a].index= i; @@ -665,36 +646,38 @@ StrandRen *RE_findOrAddStrand(Render *re, int nr) return v; } -StrandBuffer *RE_addStrandBuffer(Render *re, Object *ob, int totvert) +StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert) { StrandBuffer *strandbuf; strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer"); strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert"); strandbuf->totvert= totvert; - strandbuf->ob= ob; + strandbuf->obr= obr; - BLI_addtail(&re->strandbufs, strandbuf); + BLI_addtail(&obr->strandbufs, strandbuf); return strandbuf; } /* ------------------------------------------------------------------------ */ -void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est) +ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex) { - ObjectRen *obr= MEM_mallocN(sizeof(ObjectRen), "object render struct"); + ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct"); BLI_addtail(&re->objecttable, obr); obr->ob= ob; obr->par= par; obr->index= index; - obr->startvert= sve; - obr->endvert= eve; - obr->startface= sfa; - obr->endface= efa; - obr->startstrand= sst; - obr->endstrand= est; + obr->psysindex= psysindex; + + if(!re->objecthash) + re->objecthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + if(!BLI_ghash_lookup(re->objecthash, ob)) + BLI_ghash_insert(re->objecthash, ob, obr); + + return obr; } void free_renderdata_vertnodes(VertTableNode *vertnodes) @@ -738,8 +721,6 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes) MEM_freeN(vlaknodes[a].mcol); if(vlaknodes[a].surfnor) MEM_freeN(vlaknodes[a].surfnor); - if(vlaknodes[a].names) - MEM_freeN(vlaknodes[a].names); } MEM_freeN(vlaknodes); @@ -762,8 +743,6 @@ void free_renderdata_strandnodes(StrandTableNode *strandnodes) MEM_freeN(strandnodes[a].winspeed); if(strandnodes[a].surfnor) MEM_freeN(strandnodes[a].surfnor); - if(strandnodes[a].names) - MEM_freeN(strandnodes[a].names); } MEM_freeN(strandnodes); @@ -771,35 +750,72 @@ void free_renderdata_strandnodes(StrandTableNode *strandnodes) void free_renderdata_tables(Render *re) { + ObjectInstanceRen *obi; + ObjectRen *obr; StrandBuffer *strandbuf; - CustomDataNames *cdn; int a=0; - if(re->bloha) { - for(a=0; re->bloha[a]; a++) - MEM_freeN(re->bloha[a]); + for(obr=re->objecttable.first; obr; obr=obr->next) { + if(obr->vertnodes) { + free_renderdata_vertnodes(obr->vertnodes); + obr->vertnodes= NULL; + obr->vertnodeslen= 0; + } - MEM_freeN(re->bloha); - re->bloha= NULL; - re->blohalen= 0; + if(obr->vlaknodes) { + free_renderdata_vlaknodes(obr->vlaknodes); + obr->vlaknodes= NULL; + obr->vlaknodeslen= 0; + obr->totvlak= 0; + } + + if(obr->bloha) { + for(a=0; obr->bloha[a]; a++) + MEM_freeN(obr->bloha[a]); + + MEM_freeN(obr->bloha); + obr->bloha= NULL; + obr->blohalen= 0; + } + + if(obr->strandnodes) { + free_renderdata_strandnodes(obr->strandnodes); + obr->strandnodes= NULL; + obr->strandnodeslen= 0; + } + + for(strandbuf=obr->strandbufs.first; strandbuf; strandbuf=strandbuf->next) + if(strandbuf->vert) MEM_freeN(strandbuf->vert); + BLI_freelistN(&obr->strandbufs); + + if(obr->mtface) + MEM_freeN(obr->mtface); + if(obr->mcol) + MEM_freeN(obr->mcol); } - if(re->vertnodes) { - free_renderdata_vertnodes(re->vertnodes); - re->vertnodes= NULL; - re->vertnodeslen= 0; + if(re->objectinstance) { + for(obi=re->instancetable.first; obi; obi=obi->next) + if(obi->vectors) + MEM_freeN(obi->vectors); + + MEM_freeN(re->objectinstance); + re->objectinstance= NULL; + re->totinstance= 0; + re->instancetable.first= re->instancetable.last= NULL; + } + else { + BLI_freelistN(&re->instancetable); + + if(re->objecthash) { + BLI_ghash_free(re->objecthash, NULL, NULL); + re->objecthash= NULL; + } } - if(re->vlaknodes) { - free_renderdata_vlaknodes(re->vlaknodes); - re->vlaknodes= NULL; - re->vlaknodeslen= 0; - } - - if(re->strandnodes) { - free_renderdata_strandnodes(re->strandnodes); - re->strandnodes= NULL; - re->strandnodeslen= 0; + if(re->sortedhalos) { + MEM_freeN(re->sortedhalos); + re->sortedhalos= NULL; } if(re->strandbuckets) { @@ -807,25 +823,13 @@ void free_renderdata_tables(Render *re) re->strandbuckets= NULL; } - for(cdn=re->customdata_names.first; cdn; cdn=cdn->next) { - if(cdn->mtface) - MEM_freeN(cdn->mtface); - if(cdn->mcol) - MEM_freeN(cdn->mcol); - } - - for(strandbuf=re->strandbufs.first; strandbuf; strandbuf=strandbuf->next) - if(strandbuf->vert) MEM_freeN(strandbuf->vert); - BLI_freelistN(&re->strandbufs); - BLI_freelistN(&re->customdata_names); BLI_freelistN(&re->objecttable); } - /* ------------------------------------------------------------------------ */ -HaloRen *RE_findOrAddHalo(Render *re, int nr) +HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr) { HaloRen *h, **temp; int a; @@ -836,22 +840,22 @@ HaloRen *RE_findOrAddHalo(Render *re, int nr) } a= nr>>8; - if (a>=re->blohalen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ + if (a>=obr->blohalen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ //printf("Allocating %i more halo groups. %i total.\n", - // TABLEINITSIZE, re->blohalen+TABLEINITSIZE ); - temp=re->bloha; + // TABLEINITSIZE, obr->blohalen+TABLEINITSIZE ); + temp=obr->bloha; - re->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(re->blohalen+TABLEINITSIZE) , "Bloha"); - if(temp) memcpy(re->bloha, temp, re->blohalen*sizeof(void*)); - memset(&(re->bloha[re->blohalen]), 0, TABLEINITSIZE*sizeof(void*)); - re->blohalen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ + obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha"); + if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*)); + memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*)); + obr->blohalen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ if(temp) MEM_freeN(temp); } - h= re->bloha[a]; + h= obr->bloha[a]; if(h==NULL) { h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo"); - re->bloha[a]= h; + obr->bloha[a]= h; } h+= (nr & 255); return h; @@ -859,7 +863,7 @@ HaloRen *RE_findOrAddHalo(Render *re, int nr) /* ------------------------------------------------------------------------- */ -HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1, +HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, float *vec, float *vec1, float *orco, float hasize, float vectsize, int seed) { HaloRen *har; @@ -876,7 +880,7 @@ HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1, if(hoco1[3]==0.0) return NULL; } - har= RE_findOrAddHalo(re, re->tothalo++); + har= RE_findOrAddHalo(obr, obr->tothalo++); VECCOPY(har->co, vec); har->hasize= hasize; @@ -969,7 +973,7 @@ HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1, return har; } -HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma, float *vec, float *vec1, +HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, float *vec, float *vec1, float *orco, float *uvco, float hasize, float vectsize, int seed) { HaloRen *har; @@ -987,7 +991,7 @@ HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma, float if(hoco1[3]==0.0) return NULL; } - har= RE_findOrAddHalo(re, re->tothalo++); + har= RE_findOrAddHalo(obr, obr->tothalo++); VECCOPY(har->co, vec); har->hasize= hasize; @@ -1153,8 +1157,7 @@ static int panotestclip(Render *re, int do_pano, float *v) void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets) { - VlakRen *vlr = NULL; - VertRen *ver = NULL; + ObjectRen *obr; HaloRen *har = NULL; float zn, vec[3], hoco[4]; int a; @@ -1165,113 +1168,76 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], re->panosi= sin(panophi); re->panoco= cos(panophi); } - - /* calculate view coordinates (and zbuffer value) */ - for(a=0; a< re->totvert;a++) { - if((a & 255)==0) ver= RE_findOrAddVert(re, a); - else ver++; - if(do_pano) { - vec[0]= re->panoco*ver->co[0] + re->panosi*ver->co[2]; - vec[1]= ver->co[1]; - vec[2]= -re->panosi*ver->co[0] + re->panoco*ver->co[2]; - } - else { - VECCOPY(vec, ver->co); - } - /* Go from wcs to hcs ... */ - projectfunc(vec, re->winmat, ver->ho); - /* ... and clip in that system. */ - ver->clip = testclip(ver->ho); - /* - Because all other ops are performed in other systems, this is - the only thing that has to be done. - */ - } + for(obr=re->objecttable.first; obr; obr=obr->next) { + /* calculate view coordinates (and zbuffer value) */ + for(a=0; atothalo; a++) { + if((a & 255)==0) har= obr->bloha[a>>8]; + else har++; - /* calculate view coordinates (and zbuffer value) */ - for(a=0; atothalo; a++) { - if((a & 255)==0) har= re->bloha[a>>8]; - else har++; - - if(do_pano) { - vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2]; - vec[1]= har->co[1]; - vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2]; - } - else { - VECCOPY(vec, har->co); - } - - projectfunc(vec, re->winmat, hoco); - - /* we clip halos less critical, but not for the Z */ - hoco[0]*= 0.5; - hoco[1]*= 0.5; - - if( panotestclip(re, do_pano, hoco) ) { - har->miny= har->maxy= -10000; /* that way render clips it */ - } - else if(hoco[3]<0.0) { - har->miny= har->maxy= -10000; /* render clips it */ - } - else /* do the projection...*/ - { - /* bring back hocos */ - hoco[0]*= 2.0; - hoco[1]*= 2.0; - - zn= hoco[3]; - har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/ - har->ys= 0.5*re->winy*(1.0+hoco[1]/zn); - - /* this should be the zbuffer coordinate */ - har->zs= 0x7FFFFF*(hoco[2]/zn); - /* taking this from the face clip functions? seems ok... */ - har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); - - vec[0]+= har->hasize; - projectfunc(vec, re->winmat, hoco); - vec[0]-= har->hasize; - zn= hoco[3]; - har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn)); - - /* this clip is not really OK, to prevent stars to become too large */ - if(har->type & HA_ONLYSKY) { - if(har->rad>3.0) har->rad= 3.0; + if(do_pano) { + vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2]; + vec[1]= har->co[1]; + vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2]; } - - har->radsq= har->rad*har->rad; - - har->miny= har->ys - har->rad/re->ycor; - har->maxy= har->ys + har->rad/re->ycor; - - /* the Zd value is still not really correct for pano */ - - vec[2]-= har->hasize; /* z negative, otherwise it's clipped */ - projectfunc(vec, re->winmat, hoco); - zn= hoco[3]; - zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn)); - har->zd= CLAMPIS(zn, 0, INT_MAX); - - } - - } - - /* set flags at 0 if clipped away */ - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; - else vlr++; - - if(!re->excludeob || vlr->ob != re->excludeob) { - vlr->flag |= R_VISIBLE; - if(vlr->v4) { - if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE; + else { + VECCOPY(vec, har->co); } - else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE; + + projectfunc(vec, re->winmat, hoco); + + /* we clip halos less critical, but not for the Z */ + hoco[0]*= 0.5; + hoco[1]*= 0.5; + + if( panotestclip(re, do_pano, hoco) ) { + har->miny= har->maxy= -10000; /* that way render clips it */ + } + else if(hoco[3]<0.0) { + har->miny= har->maxy= -10000; /* render clips it */ + } + else /* do the projection...*/ + { + /* bring back hocos */ + hoco[0]*= 2.0; + hoco[1]*= 2.0; + + zn= hoco[3]; + har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/ + har->ys= 0.5*re->winy*(1.0+hoco[1]/zn); + + /* this should be the zbuffer coordinate */ + har->zs= 0x7FFFFF*(hoco[2]/zn); + /* taking this from the face clip functions? seems ok... */ + har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); + + vec[0]+= har->hasize; + projectfunc(vec, re->winmat, hoco); + vec[0]-= har->hasize; + zn= hoco[3]; + har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn)); + + /* this clip is not really OK, to prevent stars to become too large */ + if(har->type & HA_ONLYSKY) { + if(har->rad>3.0) har->rad= 3.0; + } + + har->radsq= har->rad*har->rad; + + har->miny= har->ys - har->rad/re->ycor; + har->maxy= har->ys + har->rad/re->ycor; + + /* the Zd value is still not really correct for pano */ + + vec[2]-= har->hasize; /* z negative, otherwise it's clipped */ + projectfunc(vec, re->winmat, hoco); + zn= hoco[3]; + zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn)); + har->zd= CLAMPIS(zn, 0, INT_MAX); + + } + } - else - vlr->flag &= ~R_VISIBLE; } project_strands(re, projectfunc, do_pano, do_buckets); @@ -1279,56 +1245,67 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], /* ------------------------------------------------------------------------- */ -void set_normalflags(Render *re) +void RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4]) { - VlakRen *vlr = NULL; - float *v1, xn, yn, zn; - int a1, doflip; - - /* switch normal 'snproj' values (define which axis is the optimal one for calculations) */ - for(a1=0; a1totvlak; a1++) { - if((a1 & 255)==0) vlr= re->vlaknodes[a1>>8].vlak; - else vlr++; - - vlr->noflag= 0; + ObjectInstanceRen *obi; + float mat3[3][3]; - /* abuse of this flag... this is code that just sets face normal in direction of camera */ - /* that convention we should get rid of */ - if((vlr->flag & R_NOPUNOFLIP)==0) { - - doflip= 0; - if(re->r.mode & R_ORTHO) { - if(vlr->n[2]>0.0) doflip= 1; - } - else { - v1= vlr->v1->co; - if( (v1[0]*vlr->n[0] +v1[1]*vlr->n[1] +v1[2]*vlr->n[2])<0.0 ) doflip= 1; - } - if(doflip) { - vlr->n[0]= -vlr->n[0]; - vlr->n[1]= -vlr->n[1]; - vlr->n[2]= -vlr->n[2]; - vlr->noflag |= R_FLIPPED_NO; - } - } - - /* recalculate puno. Displace & flipped matrices can screw up */ - vlr->puno= 0; - if(!(vlr->flag & R_TANGENT)) { - if( Inpf(vlr->n, vlr->v1->n) < 0.0 ) vlr->puno |= ME_FLIPV1; - if( Inpf(vlr->n, vlr->v2->n) < 0.0 ) vlr->puno |= ME_FLIPV2; - if( Inpf(vlr->n, vlr->v3->n) < 0.0 ) vlr->puno |= ME_FLIPV3; - if(vlr->v4 && Inpf(vlr->n, vlr->v4->n) < 0.0 ) vlr->puno |= ME_FLIPV4; - } - xn= fabs(vlr->n[0]); - yn= fabs(vlr->n[1]); - zn= fabs(vlr->n[2]); - if(zn>=xn && zn>=yn) vlr->noflag |= R_SNPROJ_X; - else if(yn>=xn && yn>=zn) vlr->noflag |= R_SNPROJ_Y; - else vlr->noflag |= R_SNPROJ_Z; + obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen"); + obi->obr= obr; + obi->ob= ob; + obi->par= par; + obi->index= index; + obi->psysindex= psysindex; + if(mat) { + Mat4CpyMat4(obi->mat, mat); + Mat3CpyMat4(mat3, mat); + Mat3Inv(obi->imat, mat3); + obi->flag |= R_DUPLI_TRANSFORMED; } + + BLI_addtail(&re->instancetable, obi); } +void RE_makeRenderInstances(Render *re) +{ + ObjectInstanceRen *obi, *oldobi; + ListBase newlist; + int tot; + /* convert list of object instances to an array for index based lookup */ + tot= BLI_countlist(&re->instancetable); + re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance"); + re->totinstance= tot; + newlist.first= newlist.last= NULL; + + obi= re->objectinstance; + for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) { + *obi= *oldobi; + + if(!obi->obr) { + /* dupli objects are created after object instances, so they were + * stored in a object -> objectren hash, we do lookup of the actual + * pointer here */ + if(re->objecthash && (obi->obr=BLI_ghash_lookup(re->objecthash, obi->ob))) + while(obi->obr && obi->obr->psysindex != obi->psysindex) + obi->obr= obi->obr->next; + } + + if(obi->obr) { + obi->prev= obi->next= NULL; + BLI_addtail(&newlist, obi); + obi++; + } + else + re->totinstance--; + } + + if(re->objecthash) { + BLI_ghash_free(re->objecthash, NULL, NULL); + re->objecthash= NULL; + } + BLI_freelistN(&re->instancetable); + re->instancetable= newlist; +} diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index 006a26dc82e..8e37606cdf9 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -42,6 +42,8 @@ #include "BLI_memarena.h" #include "BLI_rand.h" +#include "PIL_time.h" + #include "renderpipeline.h" #include "render_types.h" #include "renderdatabase.h" @@ -279,72 +281,82 @@ static void compress_shadowbuf(ShadBuf *shb, int *rectz, int square) /* sets start/end clipping. lar->shb should be initialized */ static void shadowbuf_autoclip(Render *re, LampRen *lar) { + ObjectInstanceRen *obi; + ObjectRen *obr; VlakRen *vlr= NULL; VertRen *ver= NULL; Material *ma= NULL; - float minz, maxz, vec[3], viewmat[4][4]; + float minz, maxz, vec[3], viewmat[4][4], obviewmat[4][4]; unsigned int lay = -1; - int a, ok= 1; + int i, a, ok= 1; + char *clipflag; minz= 1.0e30f; maxz= -1.0e30f; Mat4CpyMat4(viewmat, lar->shb->viewmat); if(lar->mode & LA_LAYER) lay= lar->lay; - - /* clear clip, is being set if face is visible (clip is calculated for real later) */ - for(a=0; atotvert; a++) { - if((a & 255)==0) ver= RE_findOrAddVert(re, a); - else ver++; - - ver->clip= 0; - } - - /* set clip in vertices when face visible */ - for(a=0; atotvlak; a++) { - - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; - else vlr++; - - /* note; these conditions are copied from zbuffer_shadow() */ - if(vlr->mat!= ma) { - ma= vlr->mat; - ok= 1; - if((ma->mode & MA_SHADBUF)==0) ok= 0; - } - - if(ok && (vlr->lay & lay)) { - vlr->v1->clip= 1; - vlr->v2->clip= 1; - vlr->v3->clip= 1; - if(vlr->v4) vlr->v4->clip= 1; - } - } - - /* calculate min and max */ - for(a=0; a< re->totvert;a++) { - if((a & 255)==0) ver= RE_findOrAddVert(re, a); - else ver++; - - if(ver->clip) { - VECCOPY(vec, ver->co); - Mat4MulVecfl(viewmat, vec); - /* Z on visible side of lamp space */ - if(vec[2] < 0.0f) { - float inpr, z= -vec[2]; - - /* since vec is rotated in lampspace, this is how to get the cosine of angle */ - /* precision is set 20% larger */ - vec[2]*= 1.2f; - Normalize(vec); - inpr= - vec[2]; - if(inpr>=lar->spotsi) { - if(zmaxz) maxz= z; + clipflag= MEM_callocN(sizeof(char)*re->totvert, "autoclipflag"); + + /* set clip in vertices when face visible */ + for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { + obr= obi->obr; + + if(obi->flag & R_TRANSFORMED) + Mat4MulMat4(obviewmat, obi->mat, viewmat); + else + Mat4CpyMat4(obviewmat, viewmat); + + memset(clipflag, 0, sizeof(char)*obr->totvert); + + /* clear clip, is being set if face is visible (clip is calculated for real later) */ + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + /* note; these conditions are copied from zbuffer_shadow() */ + if(vlr->mat!= ma) { + ma= vlr->mat; + ok= 1; + if((ma->mode & MA_SHADBUF)==0) ok= 0; + } + + if(ok && (vlr->lay & lay)) { + clipflag[vlr->v1->index]= 1; + clipflag[vlr->v2->index]= 1; + clipflag[vlr->v3->index]= 1; + if(vlr->v4) clipflag[vlr->v4->index]= 1; + } + } + + /* calculate min and max */ + for(a=0; a< obr->totvert;a++) { + if((a & 255)==0) ver= RE_findOrAddVert(obr, a); + else ver++; + + if(clipflag[a]) { + VECCOPY(vec, ver->co); + Mat4MulVecfl(obviewmat, vec); + /* Z on visible side of lamp space */ + if(vec[2] < 0.0f) { + float inpr, z= -vec[2]; + + /* since vec is rotated in lampspace, this is how to get the cosine of angle */ + /* precision is set 20% larger */ + vec[2]*= 1.2f; + Normalize(vec); + inpr= - vec[2]; + + if(inpr>=lar->spotsi) { + if(zmaxz) maxz= z; + } } } } } + + MEM_freeN(clipflag); /* set clipping min and max */ if(minz < maxz) { @@ -369,9 +381,6 @@ void makeshadowbuf(Render *re, LampRen *lar) float wsize, *jitbuf, twozero[2]= {0.0f, 0.0f}, angle, temp; int *rectz, samples; - /* XXXX EVIL! this global is used in clippyra(), zbuf.c */ - R.clipcrop= 1.0f; - if(lar->bufflag & (LA_SHADBUF_AUTO_START|LA_SHADBUF_AUTO_END)) shadowbuf_autoclip(re, lar); @@ -391,38 +400,132 @@ void makeshadowbuf(Render *re, LampRen *lar) MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat); if(ELEM(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY)) { - /* jitter, weights */ + /* jitter, weights - not threadsafe! */ + BLI_lock_thread(LOCK_CUSTOM1); shb->jit= give_jitter_tab(shb->samp); make_jitter_weight_tab(shb, lar->filtertype); + BLI_unlock_thread(LOCK_CUSTOM1); shb->totbuf= lar->buffers; if(shb->totbuf==4) jitbuf= give_jitter_tab(2); else if(shb->totbuf==9) jitbuf= give_jitter_tab(3); else jitbuf= twozero; - /* temp, will be restored */ - MTC_Mat4SwapMat4(shb->persmat, re->winmat); - - project_renderdata(re, projectvert, 0, 0, 0); - /* zbuffering */ rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf"); for(samples=0; samplestotbuf; samples++) { - zbuffer_shadow(re, lar, rectz, shb->size, jitbuf[2*samples], jitbuf[2*samples+1]); + zbuffer_shadow(re, shb->persmat, lar, rectz, shb->size, jitbuf[2*samples], jitbuf[2*samples+1]); /* create Z tiles (for compression): this system is 24 bits!!! */ compress_shadowbuf(shb, rectz, lar->mode & LA_SQUARE); + + if(re->test_break()) + break; } MEM_freeN(rectz); - - /* old matrix back */ - MTC_Mat4SwapMat4(shb->persmat, re->winmat); /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */ } } +static void *do_shadow_thread(void *re_v) +{ + Render *re= (Render*)re_v; + LampRen *lar; + + do { + BLI_lock_thread(LOCK_CUSTOM1); + for(lar=re->lampren.first; lar; lar=lar->next) { + if(lar->shb && !lar->thread_assigned) { + lar->thread_assigned= 1; + break; + } + } + BLI_unlock_thread(LOCK_CUSTOM1); + + /* if type is irregular, this only sets the perspective matrix and autoclips */ + if(lar) { + makeshadowbuf(re, lar); + BLI_lock_thread(LOCK_CUSTOM1); + lar->thread_ready= 1; + BLI_unlock_thread(LOCK_CUSTOM1); + } + } while(lar && !re->test_break()); + + return NULL; +} + +static volatile int g_break= 0; +static int thread_break(void) +{ + return g_break; +} + +void threaded_makeshadowbufs(Render *re) +{ + ListBase threads; + LampRen *lar; + int a, totthread= 0; + int (*test_break)(void); + + /* count number of threads to use */ + if(G.rendering) { + for(lar=re->lampren.first; lar; lar= lar->next) + if(lar->shb) + totthread++; + + totthread= MIN2(totthread, re->r.threads); + } + else + totthread= 1; /* preview render */ + + if(totthread <= 1) { + for(lar=re->lampren.first; lar; lar= lar->next) { + if(re->test_break()) break; + if(lar->shb) { + /* if type is irregular, this only sets the perspective matrix and autoclips */ + makeshadowbuf(re, lar); + } + } + } + else { + /* swap test break function */ + test_break= re->test_break; + re->test_break= thread_break; + + for(lar=re->lampren.first; lar; lar= lar->next) { + lar->thread_assigned= 0; + lar->thread_ready= 0; + } + + BLI_init_threads(&threads, do_shadow_thread, totthread); + + for(a=0; alampren.first; lar; lar= lar->next) + if(lar->shb && !lar->thread_ready) + break; + BLI_unlock_thread(LOCK_CUSTOM1); + } while(lar); + + BLI_end_threads(&threads); + + /* unset threadsafety */ + re->test_break= test_break; + g_break= 0; + } +} + void freeshadowbuf(LampRen *lar) { if(lar->shb) { @@ -884,6 +987,7 @@ typedef struct ISBBranch { typedef struct BSPFace { Boxf box; float *v1, *v2, *v3, *v4; + int obi; /* object for face lookup */ int facenr; /* index to retrieve VlakRen */ int type; /* only for strand now */ short shad_alpha, is_full; @@ -1063,7 +1167,7 @@ static int isb_bsp_insert(ISBBranch *root, MemArena *memarena, ISBSample *sample /* insert */ bspn->samples[bspn->totsamp]= sample; bspn->totsamp++; - + /* split if allowed and needed */ if(bspn->totsamp==BSPMAX_SAMPLE) { if(i==BSPMAX_DEPTH) { @@ -1262,7 +1366,7 @@ static void isb_bsp_face_inside(ISBBranch *bspn, BSPFace *face) for(a=bspn->totsamp-1; a>=0; a--) { ISBSample *samp= bspn->samples[a]; - if(samp->facenr!=face->facenr && samp->shadfac) { + if((samp->facenr!=face->facenr || samp->obi!=face->obi) && samp->shadfac) { if(face->box.zmin < samp->zco[2]) { if(BLI_in_rctf((rctf *)&face->box, samp->zco[0], samp->zco[1])) { int inshadow= 0; @@ -1308,7 +1412,7 @@ static void isb_bsp_recalc_box(ISBBranch *root) } /* callback function for zbuf clip */ -static void isb_bsp_test_strand(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void isb_bsp_test_strand(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) { BSPFace face; @@ -1316,6 +1420,7 @@ static void isb_bsp_test_strand(ZSpan *zspan, int zvlnr, float *v1, float *v2, f face.v2= v2; face.v3= v3; face.v4= v4; + face.obi= obi; face.facenr= zvlnr & ~RE_QUAD_OFFS; face.type= R_STRAND; if(R.osa) @@ -1341,7 +1446,7 @@ static void isb_bsp_test_strand(ZSpan *zspan, int zvlnr, float *v1, float *v2, f } /* callback function for zbuf clip */ -static void isb_bsp_test_face(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void isb_bsp_test_face(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) { BSPFace face; @@ -1349,6 +1454,7 @@ static void isb_bsp_test_face(ZSpan *zspan, int zvlnr, float *v1, float *v2, flo face.v2= v2; face.v3= v3; face.v4= v4; + face.obi= obi; face.facenr= zvlnr & ~RE_QUAD_OFFS; face.type= 0; if(R.osa) @@ -1386,13 +1492,15 @@ static int testclip_minmax(float *ho, float *minmax) /* main loop going over all faces and check in bsp overlaps, fill in shadfac values */ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) { + ObjectInstanceRen *obi; + ObjectRen *obr; ShadBuf *shb= lar->shb; ZSpan zspan, zspanstrand; VlakRen *vlr= NULL; Material *ma= NULL; - float minmaxf[4]; + float minmaxf[4], winmat[4][4]; int size= shb->size; - int a, ok=1, lay= -1; + int i, a, ok=1, lay= -1; /* further optimize, also sets minz maxz */ isb_bsp_recalc_box(root); @@ -1406,7 +1514,7 @@ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) if(lar->mode & LA_LAYER) lay= lar->lay; /* (ab)use zspan, since we use zbuffer clipping code */ - zbuf_alloc_span(&zspan, size, size); + zbuf_alloc_span(&zspan, size, size, re->clipcrop); zspan.zmulx= ((float)size)/2.0f; zspan.zmuly= ((float)size)/2.0f; @@ -1422,74 +1530,90 @@ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) zspan.zbuffunc= isb_bsp_test_face; zspanstrand.zbuffunc= isb_bsp_test_strand; - for(a=0; atotvlak; a++) { - - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; - else vlr++; - - /* note, these conditions are copied in shadowbuf_autoclip() */ - if(vlr->mat!= ma) { - ma= vlr->mat; - ok= 1; - if((ma->mode & MA_SHADBUF)==0) ok= 0; - if(ma->mode & MA_WIRE) ok= 0; - zspanstrand.shad_alpha= zspan.shad_alpha= ma->shad_alpha; - } - - if(ok && (vlr->lay & lay)) { - float hoco[4][4]; - int c1, c2, c3, c4=0; - int d1, d2, d3, d4=0; - int partclip; + for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { + obr= obi->obr; + + if(obi->flag & R_TRANSFORMED) + Mat4MulMat4(winmat, obi->mat, shb->persmat); + else + Mat4CpyMat4(winmat, shb->persmat); + + for(a=0; atotvlak; a++) { - /* create hocos per face, it is while render */ - projectvert(vlr->v1->co, shb->persmat, hoco[0]); d1= testclip_minmax(hoco[0], minmaxf); - projectvert(vlr->v2->co, shb->persmat, hoco[1]); d2= testclip_minmax(hoco[1], minmaxf); - projectvert(vlr->v3->co, shb->persmat, hoco[2]); d3= testclip_minmax(hoco[2], minmaxf); - if(vlr->v4) { - projectvert(vlr->v4->co, shb->persmat, hoco[3]); d4= testclip_minmax(hoco[3], minmaxf); + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + /* note, these conditions are copied in shadowbuf_autoclip() */ + if(vlr->mat!= ma) { + ma= vlr->mat; + ok= 1; + if((ma->mode & MA_SHADBUF)==0) ok= 0; + if(ma->mode & MA_WIRE) ok= 0; + zspanstrand.shad_alpha= zspan.shad_alpha= ma->shad_alpha; } - /* minmax clipping */ - if(vlr->v4) partclip= d1 & d2 & d3 & d4; - else partclip= d1 & d2 & d3; - - if(partclip==0) { + if(ok && (vlr->lay & lay)) { + float hoco[4][4]; + int c1, c2, c3, c4=0; + int d1, d2, d3, d4=0; + int partclip; - /* window clipping */ - c1= testclip(hoco[0]); - c2= testclip(hoco[1]); - c3= testclip(hoco[2]); - if(vlr->v4) - c4= testclip(hoco[3]); - - /* ***** NO WIRE YET */ - if(ma->mode & MA_WIRE) - zbufclipwire(&zspan, a+1, vlr); - else if(vlr->v4) { - if(vlr->flag & R_STRAND) - zbufclip4(&zspanstrand, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); - else - zbufclip4(&zspan, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); + /* create hocos per face, it is while render */ + projectvert(vlr->v1->co, winmat, hoco[0]); d1= testclip_minmax(hoco[0], minmaxf); + projectvert(vlr->v2->co, winmat, hoco[1]); d2= testclip_minmax(hoco[1], minmaxf); + projectvert(vlr->v3->co, winmat, hoco[2]); d3= testclip_minmax(hoco[2], minmaxf); + if(vlr->v4) { + projectvert(vlr->v4->co, winmat, hoco[3]); d4= testclip_minmax(hoco[3], minmaxf); } - else - zbufclip(&zspan, a+1, hoco[0], hoco[1], hoco[2], c1, c2, c3); + + /* minmax clipping */ + if(vlr->v4) partclip= d1 & d2 & d3 & d4; + else partclip= d1 & d2 & d3; + if(partclip==0) { + + /* window clipping */ + c1= testclip(hoco[0]); + c2= testclip(hoco[1]); + c3= testclip(hoco[2]); + if(vlr->v4) + c4= testclip(hoco[3]); + + /* ***** NO WIRE YET */ + if(ma->mode & MA_WIRE) { + if(vlr->v4) + zbufclipwire(&zspan, i, a+1, vlr->ec, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); + else + zbufclipwire(&zspan, i, a+1, vlr->ec, hoco[0], hoco[1], hoco[2], 0, c1, c2, c3, 0); + } + else if(vlr->v4) { + if(vlr->flag & R_STRAND) + zbufclip4(&zspanstrand, i, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); + else + zbufclip4(&zspan, i, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); + } + else + zbufclip(&zspan, i, a+1, hoco[0], hoco[1], hoco[2], c1, c2, c3); + + } } } } zbuf_free_span(&zspan); - } - /* returns 1 when the viewpixel is visible in lampbuffer */ -static int viewpixel_to_lampbuf(ShadBuf *shb, VlakRen *vlr, float x, float y, float *co) +static int viewpixel_to_lampbuf(ShadBuf *shb, ObjectInstanceRen *obi, VlakRen *vlr, float x, float y, float *co) { - float hoco[4], *v1= vlr->v1->co, *nor= vlr->n; + float hoco[4], v1[3], nor[3]; float dface, fac, siz; + RE_vlakren_get_normal(&R, obi, vlr, nor); + VECCOPY(v1, vlr->v1->co); + if(obi->flag & R_TRANSFORMED) + Mat4MulVecfl(obi->mat, v1); + /* from shadepixel() */ dface= v1[0]*nor[0] + v1[1]*nor[1] + v1[2]*nor[2]; hoco[3]= 1.0f; @@ -1550,7 +1674,7 @@ static int viewpixel_to_lampbuf(ShadBuf *shb, VlakRen *vlr, float x, float y, fl } /* storage of shadow results, solid osa and transp case */ -static void isb_add_shadfac(ISBShadfacA **isbsapp, MemArena *mem, int facenr, short shadfac, short samples) +static void isb_add_shadfac(ISBShadfacA **isbsapp, MemArena *mem, int obi, int facenr, short shadfac, short samples) { ISBShadfacA *new; float shadfacf; @@ -1562,6 +1686,7 @@ static void isb_add_shadfac(ISBShadfacA **isbsapp, MemArena *mem, int facenr, sh shadfacf= ((float)shadfac)/(4096.0); new= BLI_memarena_alloc(mem, sizeof(ISBShadfacA)); + new->obi= obi; new->facenr= facenr & ~RE_QUAD_OFFS; new->shadfac= shadfacf; if(*isbsapp) @@ -1619,7 +1744,7 @@ static void isb_make_buffer(RenderPart *pa, LampRen *lar) ISBBranch root; MemArena *memarena; long *rd; - int *rectp, x, y, sindex, sample, bsp_err=0; + int *recto, *rectp, x, y, sindex, sample, bsp_err=0; /* storage for shadow, per thread */ isbdata= shb->isb_result[pa->thread]; @@ -1669,11 +1794,14 @@ static void isb_make_buffer(RenderPart *pa, LampRen *lar) ps= ps->next; } if(ps && ps->facenr>0) { - VlakRen *vlr= RE_findOrAddVlak(&R, (ps->facenr-1) & RE_QUAD_MASK); + ObjectInstanceRen *obi= &R.objectinstance[ps->obi]; + ObjectRen *obr= obi->obr; + VlakRen *vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK); samp= samplebuf[sample] + sindex; /* convert image plane pixel location to lamp buffer space */ - if(viewpixel_to_lampbuf(shb, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], samp->zco)) { + if(viewpixel_to_lampbuf(shb, obi, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], samp->zco)) { + samp->obi= ps->obi; samp->facenr= ps->facenr & ~RE_QUAD_OFFS; ps->shadfac= 0; samp->shadfac= &ps->shadfac; @@ -1685,14 +1813,18 @@ static void isb_make_buffer(RenderPart *pa, LampRen *lar) } else { rectp= pa->rectp + sindex; + recto= pa->recto + sindex; if(*rectp>0) { - VlakRen *vlr= RE_findOrAddVlak(&R, (*rectp-1) & RE_QUAD_MASK); + ObjectInstanceRen *obi= &R.objectinstance[*recto]; + ObjectRen *obr= obi->obr; + VlakRen *vlr= RE_findOrAddVlak(obr, (*rectp-1) & RE_QUAD_MASK); float xs= (float)(x + pa->disprect.xmin); float ys= (float)(y + pa->disprect.ymin); samp= samplebuf[0] + sindex; /* convert image plane pixel location to lamp buffer space */ - if(viewpixel_to_lampbuf(shb, vlr, xs, ys, samp->zco)) { + if(viewpixel_to_lampbuf(shb, obi, vlr, xs, ys, samp->zco)) { + samp->obi= *recto; samp->facenr= *rectp & ~RE_QUAD_OFFS; samp->shadfac= isbdata->shadfacs + sindex; bound_rectf((rctf *)&root.box, samp->zco); @@ -1729,7 +1861,7 @@ static void isb_make_buffer(RenderPart *pa, LampRen *lar) PixStr *ps= (PixStr *)(*rd); while(ps) { if(ps->shadfac) - isb_add_shadfac(isbsa, isbdata->memarena, ps->facenr, ps->shadfac, count_mask(ps->mask)); + isb_add_shadfac(isbsa, isbdata->memarena, ps->obi, ps->facenr, ps->shadfac, count_mask(ps->mask)); ps= ps->next; } } @@ -1857,7 +1989,9 @@ static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *la int a; for(a=0; a<4; a++) { if(apn->p[a]) { - VlakRen *vlr= RE_findOrAddVlak(&R, (apn->p[a]-1) & RE_QUAD_MASK); + ObjectInstanceRen *obi= &R.objectinstance[apn->obi[a]]; + ObjectRen *obr= obi->obr; + VlakRen *vlr= RE_findOrAddVlak(obr, (apn->p[a]-1) & RE_QUAD_MASK); float zco[3]; /* here we store shadfac, easier to create the end storage buffer. needs zero'ed, multiple shadowbufs use it */ @@ -1870,8 +2004,9 @@ static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *la if(apn->mask[a] & mask) { /* convert image plane pixel location to lamp buffer space */ - if(viewpixel_to_lampbuf(shb, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], zco)) { + if(viewpixel_to_lampbuf(shb, obi, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], zco)) { samp= isb_alloc_sample_transp(samplebuf[sample] + sindex, memarena); + samp->obi= apn->obi[a]; samp->facenr= apn->p[a] & ~RE_QUAD_OFFS; samp->shadfac= &apn->shadfac[a]; @@ -1884,9 +2019,10 @@ static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *la else { /* convert image plane pixel location to lamp buffer space */ - if(viewpixel_to_lampbuf(shb, vlr, xs, ys, zco)) { + if(viewpixel_to_lampbuf(shb, obi, vlr, xs, ys, zco)) { samp= isb_alloc_sample_transp(samplebuf[0] + sindex, memarena); + samp->obi= apn->obi[a]; samp->facenr= apn->p[a] & ~RE_QUAD_OFFS; samp->shadfac= &apn->shadfac[a]; @@ -1930,9 +2066,9 @@ static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *la for(a=0; a<4; a++) { if(apn->p[a] && apn->shadfac[a]) { if(R.osa) - isb_add_shadfac(isbsa, isbdata->memarena, apn->p[a], apn->shadfac[a], count_mask(apn->mask[a])); + isb_add_shadfac(isbsa, isbdata->memarena, apn->obi[a], apn->p[a], apn->shadfac[a], count_mask(apn->mask[a])); else - isb_add_shadfac(isbsa, isbdata->memarena, apn->p[a], apn->shadfac[a], 0); + isb_add_shadfac(isbsa, isbdata->memarena, apn->obi[a], apn->p[a], apn->shadfac[a], 0); } } } @@ -1977,10 +2113,11 @@ float ISB_getshadow(ShadeInput *shi, ShadBuf *shb) } else { int sindex= y*isbdata->rectx + x; + int obi= shi->obi - R.objectinstance; ISBShadfacA *isbsa= *(isbdata->shadfaca + sindex); while(isbsa) { - if(isbsa->facenr==shi->facenr+1) + if(isbsa->facenr==shi->facenr+1 && isbsa->obi==obi) return isbsa->shadfac>=1.0f?0.0f:1.0f - isbsa->shadfac; isbsa= isbsa->next; } @@ -2044,7 +2181,3 @@ void ISB_free(RenderPart *pa) } } - - - - diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index acd04910565..f937218cdb6 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -50,6 +50,7 @@ #include "shading.h" #include "strand.h" #include "texture.h" +#include "zbuf.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ @@ -122,7 +123,6 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) if(shi->depth==0) { if(R.r.mode & R_RAYTRACE) { if(shi->ray_mirror!=0.0f || ((shi->mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0f)) { - /* ray trace works on combined, but gives pass info */ ray_trace(shi, shr); } @@ -209,14 +209,28 @@ void vlr_set_uv_indices(VlakRen *vlr, int *i1, int *i2, int *i3) } } +static void normal_transform(float imat[][3], float *nor) +{ + float xn, yn, zn; + + xn= nor[0]; + yn= nor[1]; + zn= nor[2]; + + nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; +} /* copy data from face to ShadeInput, general case */ -/* indices 0 1 2 3 only. shi->puno should be set! */ -void shade_input_set_triangle_i(ShadeInput *shi, VlakRen *vlr, short i1, short i2, short i3) +/* indices 0 1 2 3 only */ +void shade_input_set_triangle_i(ShadeInput *shi, ObjectInstanceRen *obi, VlakRen *vlr, short i1, short i2, short i3) { VertRen **vpp= &vlr->v1; shi->vlr= vlr; + shi->obi= obi; + shi->obr= obi->obr; shi->v1= vpp[i1]; shi->v2= vpp[i2]; @@ -231,39 +245,44 @@ void shade_input_set_triangle_i(ShadeInput *shi, VlakRen *vlr, short i1, short i shi->osatex= (shi->mat->texco & TEXCO_OSA); shi->mode= shi->mat->mode_l; /* or-ed result for all nodes */ + + /* facenormal copy, can get flipped */ + shi->flippednor= RE_vlakren_get_normal(&R, obi, vlr, shi->facenor); + + /* copy of original pre-flipped normal, for geometry->front/back node output */ + VECCOPY(shi->orignor, shi->facenor); + if(shi->flippednor) + VECMUL(shi->orignor, -1.0f); /* calculate vertexnormals */ if(vlr->flag & R_SMOOTH) { - float *n1= shi->v1->n, *n2= shi->v2->n, *n3= shi->v3->n; - char p1, p2, p3; - - p1= 1<puno & p1) { - shi->n1[0]= -n1[0]; shi->n1[1]= -n1[1]; shi->n1[2]= -n1[2]; - } else { - VECCOPY(shi->n1, n1); + VECCOPY(shi->n1, shi->v1->n); + VECCOPY(shi->n2, shi->v2->n); + VECCOPY(shi->n3, shi->v3->n); + + if(obi->flag & R_TRANSFORMED) { + normal_transform(obi->imat, shi->n1); + normal_transform(obi->imat, shi->n2); + normal_transform(obi->imat, shi->n3); } - if(shi->puno & p2) { - shi->n2[0]= -n2[0]; shi->n2[1]= -n2[1]; shi->n2[2]= -n2[2]; - } else { - VECCOPY(shi->n2, n2); + + if(!(vlr->flag & (R_NOPUNOFLIP|R_TANGENT))) { + if(INPR(shi->facenor, shi->n1) < 0.0f) { + shi->n1[0]= -shi->n1[0]; + shi->n1[1]= -shi->n1[1]; + shi->n1[2]= -shi->n1[2]; + } + if(INPR(shi->facenor, shi->n2) < 0.0f) { + shi->n2[0]= -shi->n2[0]; + shi->n2[1]= -shi->n2[1]; + shi->n2[2]= -shi->n2[2]; + } + if(INPR(shi->facenor, shi->n3) < 0.0f) { + shi->n3[0]= -shi->n3[0]; + shi->n3[1]= -shi->n3[1]; + shi->n3[2]= -shi->n3[2]; + } } - if(shi->puno & p3) { - shi->n3[0]= -n3[0]; shi->n3[1]= -n3[1]; shi->n3[2]= -n3[2]; - } else { - VECCOPY(shi->n3, n3); - } - } - /* facenormal copy, can get flipped */ - VECCOPY(shi->facenor, vlr->n); - - /* copy of original pre-flipped normal, for geometry->front/back node output */ - VECCOPY(shi->orignor, vlr->n); - if (vlr->noflag & R_FLIPPED_NO) { - VECMUL(shi->orignor, -1.0f); } } @@ -272,26 +291,25 @@ void shade_input_set_triangle_i(ShadeInput *shi, VlakRen *vlr, short i1, short i */ /* copy data from face to ShadeInput, scanline case */ -void shade_input_set_triangle(ShadeInput *shi, volatile int facenr, int normal_flip) +void shade_input_set_triangle(ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip) { if(facenr>0) { + shi->obi= &R.objectinstance[obi]; + shi->obr= shi->obi->obr; shi->facenr= (facenr-1) & RE_QUAD_MASK; - if( shi->facenr < R.totvlak ) { - VlakRen *vlr= RE_findOrAddVlak(&R, shi->facenr); - - shi->puno= normal_flip?vlr->puno:0; + if( shi->facenr < shi->obr->totvlak ) { + VlakRen *vlr= RE_findOrAddVlak(shi->obr, shi->facenr); if(facenr & RE_QUAD_OFFS) - shade_input_set_triangle_i(shi, vlr, 0, 2, 3); + shade_input_set_triangle_i(shi, shi->obi, vlr, 0, 2, 3); else - shade_input_set_triangle_i(shi, vlr, 0, 1, 2); + shade_input_set_triangle_i(shi, shi->obi, vlr, 0, 1, 2); } else shi->vlr= NULL; /* general signal we got sky */ } else shi->vlr= NULL; /* general signal we got sky */ - } /* full osa case: copy static info */ @@ -310,8 +328,6 @@ void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spo shi->osatex= (shi->mat->texco & TEXCO_OSA); shi->mode= shi->mat->mode_l; /* or-ed result for all nodes */ - shi->puno= 0; /* always faces camera automatically */ - /* shade_input_set_viewco equivalent */ VECCOPY(shi->co, spoint->co); VECCOPY(shi->view, shi->co); @@ -343,6 +359,7 @@ void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spo void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert *svert, StrandPoint *spoint) { StrandBuffer *strandbuf= strand->buffer; + ObjectRen *obr= strandbuf->obr; StrandVert *sv; int mode= shi->mode; /* or-ed result for all nodes */ short texco= shi->mat->texco; @@ -360,7 +377,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert } if(mode & MA_STR_SURFDIFF) { - float *surfnor= RE_strandren_get_surfnor(&R, strand, 0); + float *surfnor= RE_strandren_get_surfnor(obr, strand, 0); if(surfnor) VECCOPY(shi->surfnor, surfnor) @@ -378,7 +395,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert if(R.r.mode & R_SPEED) { float *speed; - speed= RE_strandren_get_winspeed(&R, strand, 0); + speed= RE_strandren_get_winspeed(shi->obi, strand, 0); if(speed) QUATCOPY(shi->winspeed, speed) else @@ -423,7 +440,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert shi->totcol= 0; if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) { - for (i=0; (mcol=RE_strandren_get_mcol(&R, strand, i, &name, 0)); i++) { + for (i=0; (mcol=RE_strandren_get_mcol(obr, strand, i, &name, 0)); i++) { ShadeInputCol *scol= &shi->col[i]; char *cp= (char*)mcol; @@ -447,7 +464,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert } } - for (i=0; (uv=RE_strandren_get_uv(&R, strand, i, &name, 0)); i++) { + for (i=0; (uv=RE_strandren_get_uv(obr, strand, i, &name, 0)); i++) { ShadeInputUV *suv= &shi->uv[i]; shi->totuv++; @@ -569,7 +586,12 @@ void shade_input_set_viewco(ShadeInput *shi, float x, float y, float z) calc_renderco_zbuf(shi->co, shi->view, z); } else { - float dface, *v1= shi->v1->co; + float dface, v1[3]; + + VECCOPY(v1, shi->v1->co); + + if(shi->obi->flag & R_TRANSFORMED) + Mat4MulVecfl(shi->obi->mat, v1); dface= v1[0]*shi->facenor[0]+v1[1]*shi->facenor[1]+v1[2]*shi->facenor[2]; @@ -652,9 +674,19 @@ void shade_input_set_uv(ShadeInput *shi) { VlakRen *vlr= shi->vlr; - if( (vlr->flag & R_SMOOTH) || (shi->mat->texco & NEED_UV) || (shi->passflag & SCE_PASS_UV)) { - float *v1= shi->v1->co, *v2= shi->v2->co, *v3= shi->v3->co; - + if((vlr->flag & R_SMOOTH) || (shi->mat->texco & NEED_UV) || (shi->passflag & SCE_PASS_UV)) { + float v1[3], v2[3], v3[3]; + + VECCOPY(v1, shi->v1->co); + VECCOPY(v2, shi->v2->co); + VECCOPY(v3, shi->v3->co); + + if(shi->obi->flag & R_TRANSFORMED) { + Mat4MulVecfl(shi->obi->mat, v1); + Mat4MulVecfl(shi->obi->mat, v2); + Mat4MulVecfl(shi->obi->mat, v3); + } + /* exception case for wire render of edge */ if(vlr->v2==vlr->v3) { float lend, lenc; @@ -679,55 +711,35 @@ void shade_input_set_uv(ShadeInput *shi) } else { /* most of this could become re-used for faces */ - float detsh, t00, t10, t01, t11; - - if(vlr->noflag & R_SNPROJ_X) { - t00= v3[0]-v1[0]; t01= v3[1]-v1[1]; - t10= v3[0]-v2[0]; t11= v3[1]-v2[1]; - } - else if(vlr->noflag & R_SNPROJ_Y) { - t00= v3[0]-v1[0]; t01= v3[2]-v1[2]; - t10= v3[0]-v2[0]; t11= v3[2]-v2[2]; - } - else { - t00= v3[1]-v1[1]; t01= v3[2]-v1[2]; - t10= v3[1]-v2[1]; t11= v3[2]-v2[2]; - } - + float detsh, t00, t10, t01, t11, xn, yn, zn; + int axis1, axis2; + + /* find most stable axis to project */ + xn= fabs(shi->facenor[0]); + yn= fabs(shi->facenor[1]); + zn= fabs(shi->facenor[2]); + + if(zn>=xn && zn>=yn) { axis1= 0; axis2= 1; } + else if(yn>=xn && yn>=zn) { axis1= 0; axis2= 2; } + else { axis1= 1; axis2= 2; } + + /* compute u,v and derivatives */ + t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2]; + t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2]; + detsh= 1.0f/(t00*t11-t10*t01); t00*= detsh; t01*=detsh; t10*=detsh; t11*=detsh; - - if(vlr->noflag & R_SNPROJ_X) { - shi->u= (shi->co[0]-v3[0])*t11-(shi->co[1]-v3[1])*t10; - shi->v= (shi->co[1]-v3[1])*t00-(shi->co[0]-v3[0])*t01; - if(shi->osatex) { - shi->dx_u= shi->dxco[0]*t11- shi->dxco[1]*t10; - shi->dx_v= shi->dxco[1]*t00- shi->dxco[0]*t01; - shi->dy_u= shi->dyco[0]*t11- shi->dyco[1]*t10; - shi->dy_v= shi->dyco[1]*t00- shi->dyco[0]*t01; - } - } - else if(vlr->noflag & R_SNPROJ_Y) { - shi->u= (shi->co[0]-v3[0])*t11-(shi->co[2]-v3[2])*t10; - shi->v= (shi->co[2]-v3[2])*t00-(shi->co[0]-v3[0])*t01; - if(shi->osatex) { - shi->dx_u= shi->dxco[0]*t11- shi->dxco[2]*t10; - shi->dx_v= shi->dxco[2]*t00- shi->dxco[0]*t01; - shi->dy_u= shi->dyco[0]*t11- shi->dyco[2]*t10; - shi->dy_v= shi->dyco[2]*t00- shi->dyco[0]*t01; - } - } - else { - shi->u= (shi->co[1]-v3[1])*t11-(shi->co[2]-v3[2])*t10; - shi->v= (shi->co[2]-v3[2])*t00-(shi->co[1]-v3[1])*t01; - if(shi->osatex) { - shi->dx_u= shi->dxco[1]*t11- shi->dxco[2]*t10; - shi->dx_v= shi->dxco[2]*t00- shi->dxco[1]*t01; - shi->dy_u= shi->dyco[1]*t11- shi->dyco[2]*t10; - shi->dy_v= shi->dyco[2]*t00- shi->dyco[1]*t01; - } + + shi->u= (shi->co[axis1]-v3[axis1])*t11-(shi->co[axis2]-v3[axis2])*t10; + shi->v= (shi->co[axis2]-v3[axis2])*t00-(shi->co[axis1]-v3[axis1])*t01; + if(shi->osatex) { + shi->dx_u= shi->dxco[axis1]*t11- shi->dxco[axis2]*t10; + shi->dx_v= shi->dxco[axis2]*t00- shi->dxco[axis1]*t01; + shi->dy_u= shi->dyco[axis1]*t11- shi->dyco[axis2]*t10; + shi->dy_v= shi->dyco[axis2]*t00- shi->dyco[axis1]*t01; } + /* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */ CLAMP(shi->u, -2.0f, 1.0f); CLAMP(shi->v, -2.0f, 1.0f); @@ -750,17 +762,36 @@ void shade_input_set_normals(ShadeInput *shi) Normalize(shi->vn); } - else { + else VECCOPY(shi->vn, shi->facenor); - } /* used in nodes */ VECCOPY(shi->vno, shi->vn); } +/* use by raytrace, sss, bake to flip into the right direction */ +void shade_input_flip_normals(ShadeInput *shi) +{ + shi->facenor[0]= -shi->facenor[0]; + shi->facenor[1]= -shi->facenor[1]; + shi->facenor[2]= -shi->facenor[2]; + + shi->vn[0]= -shi->vn[0]; + shi->vn[1]= -shi->vn[1]; + shi->vn[2]= -shi->vn[2]; + + shi->vno[0]= -shi->vno[0]; + shi->vno[1]= -shi->vno[1]; + shi->vno[2]= -shi->vno[2]; + + shi->flippednor= !shi->flippednor; +} + void shade_input_set_shade_texco(ShadeInput *shi) { + ObjectInstanceRen *obi= shi->obi; + ObjectRen *obr= shi->obr; VertRen *v1= shi->v1, *v2= shi->v2, *v3= shi->v3; float u= shi->u, v= shi->v; float l= 1.0f+u+v, dl; @@ -788,13 +819,17 @@ void shade_input_set_shade_texco(ShadeInput *shi) if (mode & (MA_TANGENT_V|MA_NORMAP_TANG) || R.flag & R_NEED_TANGENT) { float *s1, *s2, *s3; - s1= RE_vertren_get_tangent(&R, v1, 0); - s2= RE_vertren_get_tangent(&R, v2, 0); - s3= RE_vertren_get_tangent(&R, v3, 0); + s1= RE_vertren_get_tangent(obr, v1, 0); + s2= RE_vertren_get_tangent(obr, v2, 0); + s3= RE_vertren_get_tangent(obr, v3, 0); if(s1 && s2 && s3) { shi->tang[0]= (l*s3[0] - u*s1[0] - v*s2[0]); shi->tang[1]= (l*s3[1] - u*s1[1] - v*s2[1]); shi->tang[2]= (l*s3[2] - u*s1[2] - v*s2[2]); + + if(obi->flag & R_TRANSFORMED) + normal_transform(obi->imat, shi->tang); + /* qdn: normalize just in case */ Normalize(shi->tang); } @@ -806,13 +841,17 @@ void shade_input_set_shade_texco(ShadeInput *shi) if (mode & (MA_TANGENT_V|MA_NORMAP_TANG) || R.flag & R_NEED_TANGENT) { /* qdn: flat faces have tangents too, could pick either one, using average here */ - float *s1 = RE_vertren_get_tangent(&R, v1, 0); - float *s2 = RE_vertren_get_tangent(&R, v2, 0); - float *s3 = RE_vertren_get_tangent(&R, v3, 0); + float *s1 = RE_vertren_get_tangent(obr, v1, 0); + float *s2 = RE_vertren_get_tangent(obr, v2, 0); + float *s3 = RE_vertren_get_tangent(obr, v3, 0); if (s1 && s2 && s3) { shi->tang[0] = (s1[0] + s2[0] + s3[0]); shi->tang[1] = (s1[1] + s2[1] + s3[1]); shi->tang[2] = (s1[2] + s2[2] + s3[2]); + + if(obi->flag & R_TRANSFORMED) + normal_transform(obi->imat, shi->tang); + Normalize(shi->tang); } else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f; @@ -820,10 +859,13 @@ void shade_input_set_shade_texco(ShadeInput *shi) } if(mode & MA_STR_SURFDIFF) { - float *surfnor= RE_vlakren_get_surfnor(&R, shi->vlr, 0); + float *surfnor= RE_vlakren_get_surfnor(obr, shi->vlr, 0); - if(surfnor) + if(surfnor) { VECCOPY(shi->surfnor, surfnor) + if(obi->flag & R_TRANSFORMED) + normal_transform(obi->imat, shi->surfnor); + } else VECCOPY(shi->surfnor, shi->vn) @@ -833,9 +875,9 @@ void shade_input_set_shade_texco(ShadeInput *shi) if(R.r.mode & R_SPEED) { float *s1, *s2, *s3; - s1= RE_vertren_get_winspeed(&R, v1, 0); - s2= RE_vertren_get_winspeed(&R, v2, 0); - s3= RE_vertren_get_winspeed(&R, v3, 0); + s1= RE_vertren_get_winspeed(obi, v1, 0); + s2= RE_vertren_get_winspeed(obi, v2, 0); + s3= RE_vertren_get_winspeed(obi, v3, 0); if(s1 && s2 && s3) { shi->winspeed[0]= (l*s3[0] - u*s1[0] - v*s2[0]); shi->winspeed[1]= (l*s3[1] - u*s1[1] - v*s2[1]); @@ -912,9 +954,11 @@ void shade_input_set_shade_texco(ShadeInput *shi) shi->totuv= 0; shi->totcol= 0; + shi->actuv= obr->actmtface; + shi->actcol= obr->actmcol; if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) { - for (i=0; (mcol=RE_vlakren_get_mcol(&R, vlr, i, &name, 0)); i++) { + for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) { ShadeInputCol *scol= &shi->col[i]; char *cp1, *cp2, *cp3; @@ -944,7 +988,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) } } - for (i=0; (tface=RE_vlakren_get_tface(&R, vlr, i, &name, 0)); i++) { + for (i=0; (tface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)); i++) { ShadeInputUV *suv= &shi->uv[i]; float *uv1, *uv2, *uv3; @@ -977,7 +1021,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) suv->dyuv[1]= 2.0f*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); } - if((mode & MA_FACETEXTURE) && i==0) { + if((mode & MA_FACETEXTURE) && i==obr->actmtface) { if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) { shi->vcol[0]= 1.0f; shi->vcol[1]= 1.0f; @@ -1015,22 +1059,20 @@ void shade_input_set_shade_texco(ShadeInput *shi) if(mode & MA_RADIO) { float *r1, *r2, *r3; - r1= RE_vertren_get_rad(&R, v1, 0); - r2= RE_vertren_get_rad(&R, v2, 0); - r3= RE_vertren_get_rad(&R, v3, 0); + r1= RE_vertren_get_rad(obr, v1, 0); + r2= RE_vertren_get_rad(obr, v2, 0); + r3= RE_vertren_get_rad(obr, v3, 0); if(r1 && r2 && r3) { shi->rad[0]= (l*r3[0] - u*r1[0] - v*r2[0]); shi->rad[1]= (l*r3[1] - u*r1[1] - v*r2[1]); shi->rad[2]= (l*r3[2] - u*r1[2] - v*r2[2]); } - else { + else shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f; - } } - else { + else shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f; - } if(texco & TEXCO_REFL) { /* mirror reflection color textures (and envmap) */ @@ -1040,9 +1082,9 @@ void shade_input_set_shade_texco(ShadeInput *shi) if(texco & TEXCO_STRESS) { float *s1, *s2, *s3; - s1= RE_vertren_get_stress(&R, v1, 0); - s2= RE_vertren_get_stress(&R, v2, 0); - s3= RE_vertren_get_stress(&R, v3, 0); + s1= RE_vertren_get_stress(obr, v1, 0); + s2= RE_vertren_get_stress(obr, v2, 0); + s3= RE_vertren_get_stress(obr, v3, 0); if(s1 && s2 && s3) { shi->stress= l*s3[0] - u*s1[0] - v*s2[0]; if(shi->stress<1.0f) shi->stress-= 1.0f; @@ -1058,9 +1100,8 @@ void shade_input_set_shade_texco(ShadeInput *shi) } } } - else { + else shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f; - } /* this only avalailable for scanline renders */ if(shi->depth==0) { @@ -1082,22 +1123,32 @@ void shade_input_set_shade_texco(ShadeInput *shi) if(texco & TEXCO_STICKY) { float *s1, *s2, *s3; - s1= RE_vertren_get_sticky(&R, v1, 0); - s2= RE_vertren_get_sticky(&R, v2, 0); - s3= RE_vertren_get_sticky(&R, v3, 0); + s1= RE_vertren_get_sticky(obr, v1, 0); + s2= RE_vertren_get_sticky(obr, v2, 0); + s3= RE_vertren_get_sticky(obr, v3, 0); if(s1 && s2 && s3) { + float winmat[4][4], ho1[4], ho2[4], ho3[4]; float Zmulx, Zmuly; float hox, hoy, l, dl, u, v; float s00, s01, s10, s11, detsh; /* old globals, localized now */ Zmulx= ((float)R.winx)/2.0f; Zmuly= ((float)R.winy)/2.0f; + + if(shi->obi->flag & R_TRANSFORMED) + zbuf_make_winmat(&R, shi->obi->mat, winmat); + else + zbuf_make_winmat(&R, NULL, winmat); + + zbuf_render_project(winmat, v1->co, ho1); + zbuf_render_project(winmat, v2->co, ho2); + zbuf_render_project(winmat, v3->co, ho3); - s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3]; - s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3]; - s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3]; - s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3]; + s00= ho3[0]/ho3[3] - ho1[0]/ho1[3]; + s01= ho3[1]/ho3[3] - ho1[1]/ho1[3]; + s10= ho3[0]/ho3[3] - ho2[0]/ho2[3]; + s11= ho3[1]/ho3[3] - ho2[1]/ho2[3]; detsh= s00*s11-s10*s01; s00/= detsh; s01/=detsh; @@ -1106,8 +1157,8 @@ void shade_input_set_shade_texco(ShadeInput *shi) /* recalc u and v again */ hox= x/Zmulx -1.0f; hoy= y/Zmuly -1.0f; - u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10; - v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01; + u= (hox - ho3[0]/ho3[3])*s11 - (hoy - ho3[1]/ho3[3])*s10; + v= (hoy - ho3[1]/ho3[3])*s00 - (hox - ho3[0]/ho3[3])*s01; l= 1.0f+u+v; shi->sticky[0]= l*s3[0]-u*s1[0]-v*s2[0]; @@ -1197,7 +1248,7 @@ static void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, in ssamp->tot= 0; for(shi= ssamp->shi; ps; ps= ps->next) { - shade_input_set_triangle(shi, ps->facenr, 1); + shade_input_set_triangle(shi, ps->obi, ps->facenr, 1); if(shi->vlr) { /* NULL happens for env material or for 'all z' */ unsigned short curmask= ps->mask; diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 037a3aa8409..a08046da0da 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1262,7 +1262,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int if(ma->mode & MA_SHADOW) { if(lar->type==LA_HEMI || lar->type==LA_AREA); else if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) { - float thresh= vlr->ob->smoothresh; + float thresh= shi->obr->ob->smoothresh; if(inp>thresh) phongcorr= (inp-thresh)/(inp*(1.0f-thresh)); else diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 0c1590c216b..42c6d559f65 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -59,7 +59,7 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr); void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha); void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco); void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ); -void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2); +void zbufsinglewire(ZSpan *zspan, ObjectRen *obr, int zvlnr, float *ho1, float *ho2); int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag); void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect); void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf); @@ -210,6 +210,7 @@ typedef struct RenderPrimitiveIterator { BucketPrims *bpr; int bprindex; + ObjectInstanceRen *obi; StrandRen *strand; int index, tot; } RenderPrimitiveIterator; @@ -239,7 +240,9 @@ RenderPrimitiveIterator *init_primitive_iterator(Render *re, RenderBuckets *buck } else { iter->index= 0; - iter->tot= re->totstrand; + iter->obi= re->instancetable.first; + if(iter->obi) + iter->tot= iter->obi->obr->totstrand; } return iter; @@ -264,9 +267,22 @@ void *next_primitive_iterator(RenderPrimitiveIterator *iter) return iter->bpr->prim[iter->bprindex++]; } else { + if(!iter->obi) + return NULL; + + if(iter->index >= iter->tot) { + while((iter->obi=iter->obi->next) && !iter->obi->obr->totstrand) + iter->obi= iter->obi->next; + + if(iter->obi) + iter->tot= iter->obi->obr->totstrand; + else + return NULL; + } + if(iter->index < iter->tot) { if((iter->index & 255)==0) - iter->strand= iter->re->strandnodes[iter->index>>8].strand; + iter->strand= iter->obi->obr->strandnodes[iter->index>>8].strand; else iter->strand++; @@ -318,8 +334,15 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint) VECCOPY(p[2], sseg->v[2]->co); VECCOPY(p[3], sseg->v[3]->co); + if(sseg->obi->flag & R_TRANSFORMED) { + Mat4MulVecfl(sseg->obi->mat, p[0]); + Mat4MulVecfl(sseg->obi->mat, p[1]); + Mat4MulVecfl(sseg->obi->mat, p[2]); + Mat4MulVecfl(sseg->obi->mat, p[3]); + } + if(t == 0.0f) { - VECCOPY(spoint->co, sseg->v[1]->co); + VECCOPY(spoint->co, p[1]); spoint->strandco= sseg->v[1]->strandco; spoint->dtstrandco= (sseg->v[2]->strandco - sseg->v[0]->strandco); @@ -327,7 +350,7 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint) spoint->dtstrandco *= 0.5f; } else if(t == 1.0f) { - VECCOPY(spoint->co, sseg->v[2]->co); + VECCOPY(spoint->co, p[2]); spoint->strandco= sseg->v[2]->strandco; spoint->dtstrandco= (sseg->v[3]->strandco - sseg->v[1]->strandco); @@ -408,7 +431,7 @@ typedef struct StrandPart { typedef struct StrandSortSegment { struct StrandSortSegment *next; - int strand, segment; + int obi, strand, segment; float z; } StrandSortSegment; @@ -474,22 +497,22 @@ static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float } } -static void add_strand_obindex(RenderLayer *rl, int offset, Object *ob) +static void add_strand_obindex(RenderLayer *rl, int offset, ObjectRen *obr) { RenderPass *rpass; for(rpass= rl->passes.first; rpass; rpass= rpass->next) { if(rpass->passtype == SCE_PASS_INDEXOB) { float *fp= rpass->rect + offset; - *fp= (float)ob->index; + *fp= (float)obr->ob->index; break; } } } -static void do_strand_point_project(Render *re, ZSpan *zspan, float *co, float *hoco, float *zco) +static void do_strand_point_project(float winmat[][4], ZSpan *zspan, float *co, float *hoco, float *zco) { - projectvert(co, re->winmat, hoco); + projectvert(co, winmat, hoco); hoco_to_zco(zspan, zco, hoco); } @@ -606,16 +629,16 @@ static void do_strand_blend(void *handle, int x, int y, float u, float v, float #endif if(spart->addpassflag & SCE_PASS_INDEXOB) - add_strand_obindex(spart->rl, offset, buffer->ob); + add_strand_obindex(spart->rl, offset, buffer->obr); } } -static int strand_test_clip(Render *re, ZSpan *zspan, float *bounds, float *co, float *zcomp) +static int strand_test_clip(float winmat[][4], ZSpan *zspan, float *bounds, float *co, float *zcomp) { float hoco[4]; int clipflag= 0; - projectvert(co, re->winmat, hoco); + projectvert(co, winmat, hoco); /* we compare z without perspective division for segment sorting */ *zcomp= hoco[2]; @@ -625,6 +648,8 @@ static int strand_test_clip(Render *re, ZSpan *zspan, float *bounds, float *co, else if(hoco[1] > bounds[3]*hoco[3]) clipflag |= 4; else if(hoco[1]< bounds[2]*hoco[3]) clipflag |= 8; + clipflag |= testclip(hoco); + return clipflag; } @@ -635,12 +660,15 @@ void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, Str VlakRen vlr; memset(&vlr, 0, sizeof(vlr)); - vlr.flag= R_SMOOTH|R_VISIBLE; + vlr.flag= R_SMOOTH; vlr.lay= sseg->strand->buffer->lay; - vlr.ob= sseg->strand->buffer->ob; + vlr.obr= sseg->strand->buffer->obr; if(sseg->buffer->ma->mode & MA_TANGENT_STR) vlr.flag |= R_TANGENT; + shi->vlr= &vlr; + shi->obi= sseg->obi; + shi->obr= sseg->obi->obr; /* cache for shadow */ shi->samplenr++; @@ -660,7 +688,7 @@ void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, Str /* include lamphalos for strand, since halo layer was added already */ if(re->flag & R_LAMPHALO) if(shi->layflag & SCE_LAY_HALO) - renderspothalo(shi, shr->combined, shr->combined[3]); + renderspothalo(shi, shr->combined, shr->combined[3]); } static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, float t, float dt, float *co1, float *co2, float *co3, float *co4, int sample) @@ -703,7 +731,7 @@ static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, f zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_blend); } -static void strand_render(Render *re, StrandPart *spart, ZSpan *zspan, StrandPoint *p1, StrandPoint *p2) +static void strand_render(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandPoint *p1, StrandPoint *p2) { if(spart) { float t= p2->t; @@ -720,16 +748,16 @@ static void strand_render(Render *re, StrandPart *spart, ZSpan *zspan, StrandPoi else { float hoco1[4], hoco2[3]; - projectvert(p1->co, re->winmat, hoco1); - projectvert(p2->co, re->winmat, hoco2); + projectvert(p1->co, winmat, hoco1); + projectvert(p2->co, winmat, hoco2); /* render both strand and single pixel wire to counter aliasing */ - zbufclip4(zspan, 0, p1->hoco2, p1->hoco1, p2->hoco1, p2->hoco2, 0, 0, 0, 0); - zbufsinglewire(zspan, 0, hoco1, hoco2); + zbufclip4(zspan, 0, 0, p1->hoco2, p1->hoco1, p2->hoco1, p2->hoco2, 0, 0, 0, 0); + zbufsinglewire(zspan, 0, 0, hoco1, hoco2); } } -static int strand_segment_recursive(Render *re, StrandPart *spart, ZSpan *zspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth) +static int strand_segment_recursive(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth) { StrandPoint p; StrandBuffer *buffer= sseg->buffer; @@ -758,23 +786,23 @@ static int strand_segment_recursive(Render *re, StrandPart *spart, ZSpan *zspan, return 0; if(spart) { - do_strand_point_project(re, zspan, p.co1, p.hoco1, p.zco1); - do_strand_point_project(re, zspan, p.co2, p.hoco2, p.zco2); + do_strand_point_project(winmat, zspan, p.co1, p.hoco1, p.zco1); + do_strand_point_project(winmat, zspan, p.co2, p.hoco2, p.zco2); } else { - projectvert(p.co1, re->winmat, p.hoco1); - projectvert(p.co2, re->winmat, p.hoco2); + projectvert(p.co1, winmat, p.hoco1); + projectvert(p.co2, winmat, p.hoco2); } - if(!strand_segment_recursive(re, spart, zspan, sseg, p1, &p, depth+1)) - strand_render(re, spart, zspan, p1, &p); - if(!strand_segment_recursive(re, spart, zspan, sseg, &p, p2, depth+1)) - strand_render(re, spart, zspan, &p, p2); + if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, p1, &p, depth+1)) + strand_render(re, winmat, spart, zspan, p1, &p); + if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, &p, p2, depth+1)) + strand_render(re, winmat, spart, zspan, &p, p2); return 1; } -void render_strand_segment(Render *re, StrandPart *spart, ZSpan *zspan, StrandSegment *sseg) +void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandSegment *sseg) { StrandBuffer *buffer= sseg->buffer; StrandPoint *p1= &sseg->point1; @@ -789,20 +817,20 @@ void render_strand_segment(Render *re, StrandPart *spart, ZSpan *zspan, StrandSe strand_project_point(buffer->winmat, buffer->winx, buffer->winy, p2); if(spart) { - do_strand_point_project(re, zspan, p1->co1, p1->hoco1, p1->zco1); - do_strand_point_project(re, zspan, p1->co2, p1->hoco2, p1->zco2); - do_strand_point_project(re, zspan, p2->co1, p2->hoco1, p2->zco1); - do_strand_point_project(re, zspan, p2->co2, p2->hoco2, p2->zco2); + do_strand_point_project(winmat, zspan, p1->co1, p1->hoco1, p1->zco1); + do_strand_point_project(winmat, zspan, p1->co2, p1->hoco2, p1->zco2); + do_strand_point_project(winmat, zspan, p2->co1, p2->hoco1, p2->zco1); + do_strand_point_project(winmat, zspan, p2->co2, p2->hoco2, p2->zco2); } else { - projectvert(p1->co1, re->winmat, p1->hoco1); - projectvert(p1->co2, re->winmat, p1->hoco2); - projectvert(p2->co1, re->winmat, p2->hoco1); - projectvert(p2->co2, re->winmat, p2->hoco2); + projectvert(p1->co1, winmat, p1->hoco1); + projectvert(p1->co2, winmat, p1->hoco2); + projectvert(p2->co1, winmat, p2->hoco1); + projectvert(p2->co2, winmat, p2->hoco2); } - if(!strand_segment_recursive(re, spart, zspan, sseg, p1, p2, 0)) - strand_render(re, spart, zspan, p1, p2); + if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, p1, p2, 0)) + strand_render(re, winmat, spart, zspan, p1, p2); } static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, StrandPart *spart, float *pass) @@ -878,7 +906,9 @@ static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, /* render call to fill in strands */ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *rl, float *pass) { - struct RenderPrimitiveIterator *iter; + //struct RenderPrimitiveIterator *iter; + ObjectRen *obr; + ObjectInstanceRen *obi; ZSpan zspan; StrandRen *strand=0; StrandVert *svert; @@ -886,12 +916,12 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r StrandSegment sseg; StrandSortSegment *sortsegments = NULL, *sortseg, *firstseg; MemArena *memarena; - float z[4], bounds[4]; - int a, b, resultsize, totsegment, clip[4]; + float z[4], bounds[4], winmat[4][4]; + int a, b, i, resultsize, totsegment, clip[4]; if(re->test_break()) return NULL; - if(re->strandbufs.first == NULL) + if(re->totstrand == 0) return NULL; /* setup StrandPart */ @@ -937,7 +967,7 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r spart.ssamp2.tot= 1; spart.ssamp.tot= 1; - zbuf_alloc_span(&zspan, pa->rectx, pa->recty); + zbuf_alloc_span(&zspan, pa->rectx, pa->recty, re->clipcrop); /* needed for transform from hoco to zbuffer co */ zspan.zmulx= ((float)re->winx)/2.0; @@ -957,57 +987,75 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r bounds[3]= (2*pa->disprect.ymax - re->winy+1)/(float)re->winy; /* sort segments */ - iter= init_primitive_iterator(re, re->strandbuckets, pa); + //iter= init_primitive_iterator(re, re->strandbuckets, pa); memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); firstseg= NULL; sortseg= sortsegments; totsegment= 0; - while((strand = next_primitive_iterator(iter))) { - if(re->test_break()) - break; + //while((strand = next_primitive_iterator(iter))) { + for(obi=re->instancetable.first, i=0; obi; obi=obi->next, i++) { + obr= obi->obr; - if(strand->clip) - continue; + if(obi->flag & R_TRANSFORMED) + zbuf_make_winmat(re, obi->mat, winmat); + else + zbuf_make_winmat(re, NULL, winmat); - svert= strand->vert; + for(a=0; atotstrand; a++) { + if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; + else strand++; - /* keep clipping and z depth for 4 control points */ - clip[1]= strand_test_clip(re, &zspan, bounds, svert->co, &z[1]); - clip[2]= strand_test_clip(re, &zspan, bounds, (svert+1)->co, &z[2]); - clip[0]= clip[1]; z[0]= z[1]; + if(re->test_break()) + break; - for(b=0; btotvert-1; b++, svert++) { - /* compute 4th point clipping and z depth */ - if(b < strand->totvert-2) { - clip[3]= strand_test_clip(re, &zspan, bounds, (svert+2)->co, &z[3]); - } - else { - clip[3]= clip[2]; z[3]= z[2]; - } +#if 0 + if(strand->clip) + continue; +#endif - /* check clipping and add to sortsegments buffer */ - if(!(clip[0] & clip[1] & clip[2] & clip[3])) { - sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment)); - sortseg->strand= strand->index; - sortseg->segment= b; + svert= strand->vert; - sortseg->z= 0.5f*(z[1] + z[2]); - - sortseg->next= firstseg; - firstseg= sortseg; - totsegment++; - } - - /* shift clipping and z depth */ + /* keep clipping and z depth for 4 control points */ + clip[1]= strand_test_clip(winmat, &zspan, bounds, svert->co, &z[1]); + clip[2]= strand_test_clip(winmat, &zspan, bounds, (svert+1)->co, &z[2]); clip[0]= clip[1]; z[0]= z[1]; - clip[1]= clip[2]; z[1]= z[2]; - clip[2]= clip[3]; z[2]= z[3]; + + for(b=0; btotvert-1; b++, svert++) { + /* compute 4th point clipping and z depth */ + if(b < strand->totvert-2) { + clip[3]= strand_test_clip(winmat, &zspan, bounds, (svert+2)->co, &z[3]); + } + else { + clip[3]= clip[2]; z[3]= z[2]; + } + + /* check clipping and add to sortsegments buffer */ + if(!(clip[0] & clip[1] & clip[2] & clip[3])) { + sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment)); + sortseg->obi= i; + sortseg->strand= strand->index; + sortseg->segment= b; + + sortseg->z= 0.5f*(z[1] + z[2]); + + sortseg->next= firstseg; + firstseg= sortseg; + totsegment++; + } + + /* shift clipping and z depth */ + clip[0]= clip[1]; z[0]= z[1]; + clip[1]= clip[2]; z[1]= z[2]; + clip[2]= clip[3]; z[2]= z[3]; + } } } +#if 0 free_primitive_iterator(iter); +#endif if(!re->test_break()) { /* convert list to array and sort */ @@ -1028,7 +1076,12 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r if(re->test_break()) break; - sseg.strand= RE_findOrAddStrand(re, sortseg->strand); + obi= &re->objectinstance[sortseg->obi]; + obr= obi->obr; + zbuf_make_winmat(re, NULL, winmat); + + sseg.obi= obi; + sseg.strand= RE_findOrAddStrand(obr, sortseg->strand); sseg.buffer= sseg.strand->buffer; sseg.sqadaptcos= sseg.buffer->adaptcos; sseg.sqadaptcos *= sseg.sqadaptcos; @@ -1042,7 +1095,7 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r spart.segment= &sseg; - render_strand_segment(re, &spart, &zspan, &sseg); + render_strand_segment(re, winmat, &spart, &zspan, &sseg); } } @@ -1072,6 +1125,8 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets) { +#if 0 + ObjectRen *obr; StrandRen *strand = NULL; StrandVert *svert; float hoco[4], min[2], max[2], bucketco[2], vec[3]; @@ -1083,84 +1138,92 @@ void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], fl re->strandbuckets= NULL; } + if(re->totstrand == 0) + return; + if(do_buckets) re->strandbuckets= init_buckets(re); /* calculate view coordinates (and zbuffer value) */ - for(a=0; atotstrand; a++) { - if((a & 255)==0) strand= re->strandnodes[a>>8].strand; - else strand++; + for(obr=re->objecttable.first; obr; obr=obr->next) { + for(a=0; atotstrand; a++) { + if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; + else strand++; - strand->clip= ~0; + strand->clip= ~0; #if 0 - if(!(strand->buffer->flag & R_STRAND_BSPLINE)) { - INIT_MINMAX(bmin, bmax); - svert= strand->vert; - for(b=0; btotvert; b++, svert++) - DO_MINMAX(svert->co, bmin, bmax) + if(!(strand->buffer->flag & R_STRAND_BSPLINE)) { + INIT_MINMAX(bmin, bmax); + svert= strand->vert; + for(b=0; btotvert; b++, svert++) + DO_MINMAX(svert->co, bmin, bmax) - bpad[0]= (bmax[0]-bmin[0])*0.2f; - bpad[1]= (bmax[1]-bmin[1])*0.2f; - bpad[2]= (bmax[2]-bmin[2])*0.2f; - } - else - bpad[0]= bpad[1]= bpad[2]= 0.0f; - - ma= strand->buffer->ma; - width= MAX2(ma->strand_sta, ma->strand_end); - if(strand->buffer->flag & R_STRAND_B_UNITS) { - bpad[0] += 0.5f*width; - bpad[1] += 0.5f*width; - bpad[2] += 0.5f*width; - } -#endif - - INIT_MINMAX2(min, max); - svert= strand->vert; - for(b=0; btotvert; b++, svert++) { - //VECADD(vec, svert->co, bpad); - - /* same as VertRen */ - if(do_pano) { - vec[0]= re->panoco*svert->co[0] + re->panosi*svert->co[2]; - vec[1]= svert->co[1]; - vec[2]= -re->panosi*svert->co[0] + re->panoco*svert->co[2]; + bpad[0]= (bmax[0]-bmin[0])*0.2f; + bpad[1]= (bmax[1]-bmin[1])*0.2f; + bpad[2]= (bmax[2]-bmin[2])*0.2f; } else - VECCOPY(vec, svert->co) + bpad[0]= bpad[1]= bpad[2]= 0.0f; - /* Go from wcs to hcs ... */ - projectfunc(vec, re->winmat, hoco); - /* ... and clip in that system. */ - strand->clip &= testclip(hoco); - - if(do_buckets) { - project_hoco_to_bucket(re->strandbuckets, hoco, bucketco); - DO_MINMAX2(bucketco, min, max); - } - } - - if(do_buckets) { -#if 0 - if(strand->buffer->flag & R_STRAND_BSPLINE) { - min[0] -= width; - min[1] -= width; - max[0] += width; - max[1] += width; - } - else { - /* catmull-rom stays within 1.2f bounds in object space, - * is this still true after projection? */ - min[0] -= width + (max[0]-min[0])*0.2f; - min[1] -= width + (max[1]-min[1])*0.2f; - max[0] += width + (max[0]-min[0])*0.2f; - max[1] += width + (max[1]-min[1])*0.2f; + ma= strand->buffer->ma; + width= MAX2(ma->strand_sta, ma->strand_end); + if(strand->buffer->flag & R_STRAND_B_UNITS) { + bpad[0] += 0.5f*width; + bpad[1] += 0.5f*width; + bpad[2] += 0.5f*width; } #endif - add_buckets_primitive(re->strandbuckets, min, max, strand); + INIT_MINMAX2(min, max); + svert= strand->vert; + for(b=0; btotvert; b++, svert++) { + //VECADD(vec, svert->co, bpad); + + /* same as VertRen */ + if(do_pano) { + vec[0]= re->panoco*svert->co[0] + re->panosi*svert->co[2]; + vec[1]= svert->co[1]; + vec[2]= -re->panosi*svert->co[0] + re->panoco*svert->co[2]; + } + else + VECCOPY(vec, svert->co) + + /* Go from wcs to hcs ... */ + projectfunc(vec, re->winmat, hoco); + /* ... and clip in that system. */ + strand->clip &= testclip(hoco); + +#if 0 + if(do_buckets) { + project_hoco_to_bucket(re->strandbuckets, hoco, bucketco); + DO_MINMAX2(bucketco, min, max); + } +#endif + } + +#if 0 + if(do_buckets) { + if(strand->buffer->flag & R_STRAND_BSPLINE) { + min[0] -= width; + min[1] -= width; + max[0] += width; + max[1] += width; + } + else { + /* catmull-rom stays within 1.2f bounds in object space, + * is this still true after projection? */ + min[0] -= width + (max[0]-min[0])*0.2f; + min[1] -= width + (max[1]-min[1])*0.2f; + max[0] += width + (max[0]-min[0])*0.2f; + max[1] += width + (max[1]-min[1])*0.2f; + } + + add_buckets_primitive(re->strandbuckets, min, max, strand); + } +#endif } } +#endif } diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 41a46679e95..b502fb2b421 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -755,16 +755,16 @@ static int plugintex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex } -static int cubemap_glob(VlakRen *vlr, float x, float y, float z, float *adr1, float *adr2) +static int cubemap_glob(float *n, float x, float y, float z, float *adr1, float *adr2) { float x1, y1, z1, nor[3]; int ret; - if(vlr==NULL) { + if(n==NULL) { nor[0]= x; nor[1]= y; nor[2]= z; // use local render coord } else { - VECCOPY(nor, vlr->n); + VECCOPY(nor, n); } MTC_Mat4Mul3Vecfl(R.viewinv, nor); @@ -793,7 +793,7 @@ static int cubemap_glob(VlakRen *vlr, float x, float y, float z, float *adr1, fl /* ------------------------------------------------------------------------- */ /* mtex argument only for projection switches */ -static int cubemap(MTex *mtex, VlakRen *vlr, float x, float y, float z, float *adr1, float *adr2) +static int cubemap(MTex *mtex, VlakRen *vlr, float *n, float x, float y, float z, float *adr1, float *adr2) { int proj[4]={0, ME_PROJXY, ME_PROJXZ, ME_PROJYZ}, ret= 0; @@ -811,7 +811,7 @@ static int cubemap(MTex *mtex, VlakRen *vlr, float x, float y, float z, float *a else if( fabs(nor[0])puno |= ME_PROJXZ; else vlr->puno |= ME_PROJYZ; } - else return cubemap_glob(vlr, x, y, z, adr1, adr2); + else return cubemap_glob(n, x, y, z, adr1, adr2); } if(mtex) { @@ -843,7 +843,7 @@ static int cubemap(MTex *mtex, VlakRen *vlr, float x, float y, float z, float *a } } else { - return cubemap_glob(vlr, x, y, z, adr1, adr2); + return cubemap_glob(n, x, y, z, adr1, adr2); } return ret; @@ -851,14 +851,14 @@ static int cubemap(MTex *mtex, VlakRen *vlr, float x, float y, float z, float *a /* ------------------------------------------------------------------------- */ -static int cubemap_ob(Object *ob, VlakRen *vlr, float x, float y, float z, float *adr1, float *adr2) +static int cubemap_ob(Object *ob, float *n, float x, float y, float z, float *adr1, float *adr2) { float x1, y1, z1, nor[3]; int ret; - if(vlr==NULL) return 0; + if(n==NULL) return 0; - VECCOPY(nor, vlr->n); + VECCOPY(nor, n); if(ob) MTC_Mat4Mul3Vecfl(ob->imat, nor); x1= fabs(nor[0]); @@ -885,7 +885,7 @@ static int cubemap_ob(Object *ob, VlakRen *vlr, float x, float y, float z, float /* ------------------------------------------------------------------------- */ -static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float *dyt) +static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *n, float *dxt, float *dyt) { Tex *tex; Object *ob= NULL; @@ -907,9 +907,9 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float else if(wrap==MTEX_TUBE) tubemap(t[0], t[1], t[2], &fx, &fy); else if(wrap==MTEX_SPHERE) spheremap(t[0], t[1], t[2], &fx, &fy); else { - if(texco==TEXCO_OBJECT) cubemap_ob(ob, vlr, t[0], t[1], t[2], &fx, &fy); - else if(texco==TEXCO_GLOB) cubemap_glob(vlr, t[0], t[1], t[2], &fx, &fy); - else cubemap(mtex, vlr, t[0], t[1], t[2], &fx, &fy); + if(texco==TEXCO_OBJECT) cubemap_ob(ob, n, t[0], t[1], t[2], &fx, &fy); + else if(texco==TEXCO_GLOB) cubemap_glob(n, t[0], t[1], t[2], &fx, &fy); + else cubemap(mtex, vlr, n, t[0], t[1], t[2], &fx, &fy); } /* repeat */ @@ -998,9 +998,9 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float } else { - if(texco==TEXCO_OBJECT) proj = cubemap_ob(ob, vlr, t[0], t[1], t[2], &fx, &fy); - else if (texco==TEXCO_GLOB) proj = cubemap_glob(vlr, t[0], t[1], t[2], &fx, &fy); - else proj = cubemap(mtex, vlr, t[0], t[1], t[2], &fx, &fy); + if(texco==TEXCO_OBJECT) proj = cubemap_ob(ob, n, t[0], t[1], t[2], &fx, &fy); + else if (texco==TEXCO_GLOB) proj = cubemap_glob(n, t[0], t[1], t[2], &fx, &fy); + else proj = cubemap(mtex, vlr, n, t[0], t[1], t[2], &fx, &fy); if(proj==1) { SWAP(float, dxt[1], dxt[2]); @@ -1230,7 +1230,7 @@ int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, Te dyt_l[0]= dyt_l[1]= dyt_l[2]= 0.0f; } - do_2d_mapping(&mtex, texvec_l, NULL, dxt_l, dyt_l); + do_2d_mapping(&mtex, texvec_l, NULL, NULL, dxt_l, dyt_l); return multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres); } @@ -1466,7 +1466,7 @@ void do_material_tex(ShadeInput *shi) co= shi->gl; dx= shi->dxco; dy= shi->dyco; } else if(mtex->texco==TEXCO_UV) { - ShadeInputUV *suv= &shi->uv[0]; + ShadeInputUV *suv= &shi->uv[shi->actuv]; int i; if(mtex->uvname[0] != 0) { @@ -1549,7 +1549,7 @@ void do_material_tex(ShadeInput *shi) else dxt[2]= dyt[2]= 0.0; } - do_2d_mapping(mtex, texvec, shi->vlr, dxt, dyt); + do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); /* translate and scale */ texvec[0]= mtex->size[0]*(texvec[0]-0.5) +mtex->ofs[0]+0.5; @@ -1669,10 +1669,10 @@ void do_material_tex(ShadeInput *shi) if(mtex->texflag & MTEX_VIEWSPACE) { // rotate to global coords if(mtex->texco==TEXCO_ORCO || mtex->texco==TEXCO_UV) { - if(shi->vlr && shi->vlr->ob) { + if(shi->vlr && shi->obr->ob) { float len= Normalize(texres.nor); // can be optimized... (ton) - Mat4Mul3Vecfl(shi->vlr->ob->obmat, texres.nor); + Mat4Mul3Vecfl(shi->obr->ob->obmat, texres.nor); Mat4Mul3Vecfl(R.viewmat, texres.nor); Normalize(texres.nor); VecMulf(texres.nor, len); @@ -1762,8 +1762,8 @@ void do_material_tex(ShadeInput *shi) Mat4Mul3Vecfl(R.viewmat, nor); } else if(mtex->normapspace == MTEX_NSPACE_OBJECT) { - if(shi->vlr && shi->vlr->ob) - Mat4Mul3Vecfl(shi->vlr->ob->obmat, nor); + if(shi->vlr && shi->vlr->obr->ob) + Mat4Mul3Vecfl(shi->vlr->obr->ob->obmat, nor); Mat4Mul3Vecfl(R.viewmat, nor); } @@ -1985,7 +1985,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf) } - if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, dxt, dyt); + if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres); @@ -2156,7 +2156,7 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f else texvec[2]= mtex->size[2]*(mtex->ofs[2]); /* texture */ - if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, dxt, dyt); + if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres); @@ -2336,7 +2336,7 @@ void do_lamp_tex(LampRen *la, float *lavec, ShadeInput *shi, float *colf) /* texture */ if(tex->type==TEX_IMAGE) { - do_2d_mapping(mtex, texvec, NULL, dxt, dyt); + do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); } rgb= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres); @@ -2421,7 +2421,7 @@ int externtex(MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *t /* texture */ if(tex->type==TEX_IMAGE) { - do_2d_mapping(mtex, texvec, NULL, dxt, dyt); + do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); } rgb= multitex(tex, texvec, dxt, dyt, 0, &texr); @@ -2454,6 +2454,7 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) static int firsttime= 1; Tex *tex; float texvec[3], dx[2], dy[2]; + ShadeInputUV *suv= &shi->uv[shi->actuv]; if(firsttime) { firsttime= 0; @@ -2465,14 +2466,14 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) if(shi->ys & 1) tex= &tex1; else tex= &tex2; // threadsafe - texvec[0]= 0.5+0.5*shi->uv[0].uv[0]; - texvec[1]= 0.5+0.5*shi->uv[0].uv[1]; + texvec[0]= 0.5+0.5*suv->uv[0]; + texvec[1]= 0.5+0.5*suv->uv[1]; texvec[2] = 0; // initalize it because imagewrap looks at it. if(shi->osatex) { - dx[0]= 0.5*shi->uv[0].dxuv[0]; - dx[1]= 0.5*shi->uv[0].dxuv[1]; - dy[0]= 0.5*shi->uv[0].dyuv[0]; - dy[1]= 0.5*shi->uv[0].dyuv[1]; + dx[0]= 0.5*suv->dxuv[0]; + dx[1]= 0.5*suv->dxuv[1]; + dy[0]= 0.5*suv->dyuv[0]; + dy[1]= 0.5*suv->dyuv[1]; } texr.nor= NULL; diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index cb92f8cefb3..57d2bbb3489 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -84,7 +84,7 @@ extern struct Render R; /* ****************** Spans ******************************* */ /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */ -void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty) +void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop) { memset(zspan, 0, sizeof(ZSpan)); @@ -93,6 +93,8 @@ void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty) zspan->span1= MEM_mallocN(recty*sizeof(float), "zspan"); zspan->span2= MEM_mallocN(recty*sizeof(float), "zspan"); + + zspan->clipcrop= clipcrop; } void zbuf_free_span(ZSpan *zspan) @@ -298,7 +300,7 @@ static APixstr *addpsA(ZSpan *zspan) return zspan->curpstr; } -static void zbuffillAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) { APixstr *ap, *apofs, *apn; double zxd, zyd, zy0, zverg; @@ -388,16 +390,16 @@ static void zbuffillAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3 apn= ap; while(apn) { - if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; } - if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; } - if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; } - if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; } - if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; } - if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; } - if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; } - if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; } -// if(apn->p[i]==0) {apn->p[i]= zvlnr; apn->z[i]= zverg; apn->mask[i]= mask; break; } -// if(apn->p[i]==zvlnr) {apn->mask[i]|= mask; break; } + if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; } + if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; } + if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; } + if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; } + if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; } + if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; } + if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; } + if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } +// if(apn->p[i]==0) {apn->obi[i]= obi; apn->p[i]= zvlnr; apn->z[i]= zverg; apn->mask[i]= mask; break; } +// if(apn->p[i]==zvlnr && apn->obi[i]==obi) {apn->mask[i]|= mask; break; } if(apn->next==NULL) apn->next= addpsA(zspan); apn= apn->next; } @@ -417,7 +419,7 @@ static void zbuffillAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3 -static void zbuflineAc(ZSpan *zspan, int zvlnr, float *vec1, float *vec2) +static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2) { APixstr *ap, *apn; int *rectz; @@ -476,14 +478,14 @@ static void zbuflineAc(ZSpan *zspan, int zvlnr, float *vec1, float *vec2) apn= ap; while(apn) { /* loop unrolled */ - if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } - if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; } - if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } - if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; } - if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } - if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; } - if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } - if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; } + if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } + if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; } + if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } + if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; } + if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } + if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; } + if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } + if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } if(apn->next==0) apn->next= addpsA(zspan); apn= apn->next; } @@ -568,9 +570,9 @@ static void zbuflineAc(ZSpan *zspan, int zvlnr, float *vec1, float *vec2) /* ************* NORMAL ZBUFFER ************ */ -static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2) +static void zbufline(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2) { - int *rectz, *rectp; + int *rectz, *rectp, *recto; int start, end, x, y, oldx, oldy, ofs; int dz, vergz, maxtest= 0; float dx, dy; @@ -605,21 +607,24 @@ static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2) rectz= zspan->rectz + oldy*zspan->rectx+ start; rectp= zspan->rectp + oldy*zspan->rectx+ start; + recto= zspan->recto + oldy*zspan->rectx+ start; if(dy<0) ofs= -zspan->rectx; else ofs= zspan->rectx; - for(x= start; x<=end; x++, rectz++, rectp++) { + for(x= start; x<=end; x++, rectz++, rectp++, recto++) { y= floor(v1[1]); if(y!=oldy) { oldy= y; rectz+= ofs; rectp+= ofs; + recto+= ofs; } if(x>=0 && y>=0 && yrecty) { if(vergz<*rectz) { + *recto= obi; *rectz= vergz; *rectp= zvlnr; } @@ -657,23 +662,26 @@ static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2) rectz= zspan->rectz + start*zspan->rectx+ oldx; rectp= zspan->rectp + start*zspan->rectx+ oldx; + recto= zspan->recto + start*zspan->rectx+ oldx; if(dx<0) ofs= -1; else ofs= 1; - for(y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx) { + for(y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx, recto+=zspan->rectx) { x= floor(v1[0]); if(x!=oldx) { oldx= x; rectz+= ofs; rectp+= ofs; + recto+= ofs; } if(x>=0 && y>=0 && xrectx) { if(vergz<*rectz) { *rectz= vergz; *rectp= zvlnr; + *recto= obi; } } @@ -684,7 +692,7 @@ static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2) } } -static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2) +static void zbufline_onlyZ(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2) { int *rectz, *rectz1= NULL; int start, end, x, y, oldx, oldy, ofs; @@ -872,26 +880,15 @@ void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco) zco[2]= 0x7FFFFFFF *(hoco[2]*div); } -void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr) +void zbufclipwire(ZSpan *zspan, int obi, int zvlnr, int ec, float *ho1, float *ho2, float *ho3, float *ho4, int c1, int c2, int c3, int c4) { - float vez[20], *f1, *f2, *f3, *f4= 0; - int c1, c2, c3, c4, ec, and, or; + float vez[20]; + int and, or; /* edgecode: 1= draw */ - ec = vlr->ec; if(ec==0) return; - c1= vlr->v1->clip; - c2= vlr->v2->clip; - c3= vlr->v3->clip; - f1= vlr->v1->ho; - f2= vlr->v2->ho; - f3= vlr->v3->ho; - - if(vlr->v4) { - f4= vlr->v4->ho; - c4= vlr->v4->clip; - + if(ho4) { and= (c1 & c2 & c3 & c4); or= (c1 | c2 | c3 | c4); } @@ -907,51 +904,51 @@ void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr) else { /* clipping */ if(ec & ME_V1V2) { - QUATCOPY(vez, f1); - QUATCOPY(vez+4, f2); + QUATCOPY(vez, ho1); + QUATCOPY(vez+4, ho2); if( clipline(vez, vez+4)) { hoco_to_zco(zspan, vez, vez); hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4); + zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); } } if(ec & ME_V2V3) { - QUATCOPY(vez, f2); - QUATCOPY(vez+4, f3); + QUATCOPY(vez, ho2); + QUATCOPY(vez+4, ho3); if( clipline(vez, vez+4)) { hoco_to_zco(zspan, vez, vez); hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4); + zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); } } - if(vlr->v4) { + if(ho4) { if(ec & ME_V3V4) { - QUATCOPY(vez, f3); - QUATCOPY(vez+4, f4); + QUATCOPY(vez, ho3); + QUATCOPY(vez+4, ho4); if( clipline(vez, vez+4)) { hoco_to_zco(zspan, vez, vez); hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4); + zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); } } if(ec & ME_V4V1) { - QUATCOPY(vez, f4); - QUATCOPY(vez+4, f1); + QUATCOPY(vez, ho4); + QUATCOPY(vez+4, ho1); if( clipline(vez, vez+4)) { hoco_to_zco(zspan, vez, vez); hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4); + zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); } } } else { if(ec & ME_V3V1) { - QUATCOPY(vez, f3); - QUATCOPY(vez+4, f1); + QUATCOPY(vez, ho3); + QUATCOPY(vez+4, ho1); if( clipline(vez, vez+4)) { hoco_to_zco(zspan, vez, vez); hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4); + zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); } } } @@ -960,25 +957,25 @@ void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr) } } - hoco_to_zco(zspan, vez, f1); - hoco_to_zco(zspan, vez+4, f2); - hoco_to_zco(zspan, vez+8, f3); - if(vlr->v4) { - hoco_to_zco(zspan, vez+12, f4); + hoco_to_zco(zspan, vez, ho1); + hoco_to_zco(zspan, vez+4, ho2); + hoco_to_zco(zspan, vez+8, ho3); + if(ho4) { + hoco_to_zco(zspan, vez+12, ho4); - if(ec & ME_V3V4) zspan->zbuflinefunc(zspan, zvlnr, vez+8, vez+12); - if(ec & ME_V4V1) zspan->zbuflinefunc(zspan, zvlnr, vez+12, vez); + if(ec & ME_V3V4) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez+12); + if(ec & ME_V4V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+12, vez); } else { - if(ec & ME_V3V1) zspan->zbuflinefunc(zspan, zvlnr, vez+8, vez); + if(ec & ME_V3V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez); } - if(ec & ME_V1V2) zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4); - if(ec & ME_V2V3) zspan->zbuflinefunc(zspan, zvlnr, vez+4, vez+8); + if(ec & ME_V1V2) zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); + if(ec & ME_V2V3) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+4, vez+8); } -void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2) +void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, float *ho1, float *ho2) { float f1[4], f2[4]; int c1, c2; @@ -994,7 +991,7 @@ void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2) if(clipline(f1, f2)) { hoco_to_zco(zspan, f1, f1); hoco_to_zco(zspan, f2, f2); - zspan->zbuflinefunc(zspan, zvlnr, f1, f2); + zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2); } } } @@ -1002,7 +999,7 @@ void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2) hoco_to_zco(zspan, f1, ho1); hoco_to_zco(zspan, f2, ho2); - zspan->zbuflinefunc(zspan, zvlnr, f1, f2); + zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2); } } @@ -1017,12 +1014,13 @@ void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2) * @param v2 [4 floats, world coordinates] second vertex * @param v3 [4 floats, world coordinates] third vertex */ -static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) { double zxd, zyd, zy0, zverg; float x0,y0,z0; float x1,y1,z1,x2,y2,z2,xx1; float *span1, *span2; + int *rectoofs, *ro; int *rectpofs, *rp; int *rz, x, y; int sn1, sn2, rectx, *rectzofs, my0, my2; @@ -1073,6 +1071,7 @@ static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float rectx= zspan->rectx; rectzofs= (zspan->rectz+rectx*my2); rectpofs= (zspan->rectp+rectx*my2); + rectoofs= (zspan->recto+rectx*my2); /* correct span */ sn1= (my0 + my2)/2; @@ -1098,16 +1097,19 @@ static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float zverg= (double)sn1*zxd + zy0; rz= rectzofs+sn1; rp= rectpofs+sn1; + ro= rectoofs+sn1; x= sn2-sn1; while(x>=0) { if( (int)zverg > *rz || *rz==0x7FFFFFFF) { + *ro= obi; *rz= (int)zverg; *rp= zvlnr; } zverg+= zxd; rz++; rp++; + ro++; x--; } } @@ -1115,17 +1117,19 @@ static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float zy0-=zyd; rectzofs-= rectx; rectpofs-= rectx; + rectoofs-= rectx; } } /* uses spanbuffers */ -static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) { double zxd, zyd, zy0, zverg; float x0,y0,z0; float x1,y1,z1,x2,y2,z2,xx1; float *span1, *span2; + int *rectoofs, *ro; int *rectpofs, *rp; int *rz, x, y; int sn1, sn2, rectx, *rectzofs, my0, my2; @@ -1176,6 +1180,7 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3 rectx= zspan->rectx; rectzofs= (zspan->rectz+rectx*my2); rectpofs= (zspan->rectp+rectx*my2); + rectoofs= (zspan->recto+rectx*my2); /* correct span */ sn1= (my0 + my2)/2; @@ -1201,16 +1206,19 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3 zverg= (double)sn1*zxd + zy0; rz= rectzofs+sn1; rp= rectpofs+sn1; + ro= rectoofs+sn1; x= sn2-sn1; while(x>=0) { if( (int)zverg < *rz) { *rz= (int)zverg; *rp= zvlnr; + *ro= obi; } zverg+= zxd; rz++; rp++; + ro++; x--; } } @@ -1218,6 +1226,7 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3 zy0-=zyd; rectzofs-= rectx; rectpofs-= rectx; + rectoofs-= rectx; } } @@ -1233,7 +1242,7 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3 */ /* now: filling two Z values, the closest and 2nd closest */ -static void zbuffillGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void zbuffillGL_onlyZ(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) { double zxd, zyd, zy0, zverg; float x0,y0,z0; @@ -1543,7 +1552,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float * * @param a index for coordinate (x, y, or z) */ -static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a) +static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a, float clipcrop) { float da,dw,u1=0.0,u2=1.0; float v13; @@ -1559,9 +1568,8 @@ static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a v13= v1[3]; } else { - /* XXXXX EVIL! this is a R global, whilst this function can be called for shadow, before R was set */ - dw= R.clipcrop*(v2[3]-v1[3]); - v13= R.clipcrop*v1[3]; + dw= clipcrop*(v2[3]-v1[3]); + v13= clipcrop*v1[3]; } /* according the original article by Liang&Barsky, for clipping of * homogenous coordinates with viewplane, the value of "0" is used instead of "-w" . @@ -1670,9 +1678,115 @@ void projectvert(float *v1, float winmat[][4], float *adr) adr[3]= x*winmat[0][3]+ y*winmat[1][3]+ z*winmat[2][3]+ winmat[3][3]; } +/* ------------------------------------------------------------------------- */ + +#define ZBUF_PROJECT_CACHE_SIZE 256 + +typedef struct ZbufProjectCache { + int index, clip; + float ho[4]; +} ZbufProjectCache; + +static void zbuf_project_cache_clear(ZbufProjectCache *cache, int size) +{ + int i; + + if(size > ZBUF_PROJECT_CACHE_SIZE) + size= ZBUF_PROJECT_CACHE_SIZE; + + memset(cache, 0, sizeof(ZbufProjectCache)*size); + for(i=0; idisprect.xmin - re->winx-1)/(float)re->winx; + bounds[1]= (2*pa->disprect.xmax - re->winx+1)/(float)re->winx; + bounds[2]= (2*pa->disprect.ymin - re->winy-1)/(float)re->winy; + bounds[3]= (2*pa->disprect.ymax - re->winy+1)/(float)re->winy; +} + +static int zbuf_part_project(ZbufProjectCache *cache, int index, float winmat[][4], float *bounds, float *co, float *ho) +{ + float vec[3], wco; + int clipflag= 0, cindex= index & 255; + + if(cache[cindex].index == index) { + QUATCOPY(ho, cache[cindex].ho); + return cache[cindex].clip; + } + else { + VECCOPY(vec, co) + projectvert(co, winmat, ho); + + wco= ho[3]; + if(ho[0] > bounds[1]*wco) clipflag |= 1; + else if(ho[0]< bounds[0]*wco) clipflag |= 2; + if(ho[1] > bounds[3]*wco) clipflag |= 4; + else if(ho[1]< bounds[2]*wco) clipflag |= 8; + + QUATCOPY(cache[cindex].ho, ho); + cache[cindex].clip= clipflag; + cache[cindex].index= index; + + return clipflag; + } +} + +void zbuf_render_project(float winmat[][4], float *co, float *ho) +{ + float vec[3]; + + VECCOPY(vec, co) + projectvert(vec, winmat, ho); +} + +void zbuf_make_winmat(Render *re, float duplimat[][4], float winmat[][4]) +{ + float panomat[4][4]; + + if(re->r.mode & R_PANORAMA) { + Mat4One(panomat); + panomat[0][0]= re->panoco; + panomat[0][2]= re->panosi; + panomat[2][0]= -re->panosi; + panomat[2][2]= re->panoco; + + if(duplimat) + Mat4MulSerie(winmat, re->winmat, panomat, duplimat, 0, 0, 0, 0, 0); + else + Mat4MulMat4(winmat, panomat, re->winmat); + } + else if(duplimat) + Mat4MulMat4(winmat, duplimat, re->winmat); + else + Mat4CpyMat4(winmat, re->winmat); +} + /* do zbuffering and clip, f1 f2 f3 are hocos, c1 c2 c3 are clipping flags */ -void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3) +void zbufclip(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3) { float *vlzp[32][3], labda[3][2]; float vez[400], *trias[40]; @@ -1713,9 +1827,9 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, else if (b==1) arg= 0; else arg= 1; - clippyra(labda[0], vlzp[v][0],vlzp[v][1], &b2,&b3, arg); - clippyra(labda[1], vlzp[v][1],vlzp[v][2], &b2,&b3, arg); - clippyra(labda[2], vlzp[v][2],vlzp[v][0], &b2,&b3, arg); + clippyra(labda[0], vlzp[v][0],vlzp[v][1], &b2,&b3, arg, zspan->clipcrop); + clippyra(labda[1], vlzp[v][1],vlzp[v][2], &b2,&b3, arg, zspan->clipcrop); + clippyra(labda[2], vlzp[v][2],vlzp[v][0], &b2,&b3, arg, zspan->clipcrop); if(b2==0 && b3==1) { /* completely 'in', but we copy because of last for() loop in this section */; @@ -1771,7 +1885,7 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, } for(b=1;bzbuffunc(zspan, zvlnr, vlzp[b][0],vlzp[b][1],vlzp[b][2], NULL); + zspan->zbuffunc(zspan, obi, zvlnr, vlzp[b][0],vlzp[b][1],vlzp[b][2], NULL); } } return; @@ -1782,10 +1896,10 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, hoco_to_zco(zspan, vez, f1); hoco_to_zco(zspan, vez+4, f2); hoco_to_zco(zspan, vez+8, f3); - zspan->zbuffunc(zspan, zvlnr, vez,vez+4,vez+8, NULL); + zspan->zbuffunc(zspan, obi, zvlnr, vez,vez+4,vez+8, NULL); } -void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4) +void zbufclip4(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4) { float vez[16]; @@ -1793,8 +1907,8 @@ void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float * if(c1 & c2 & c3 & c4) { /* completely out */ return; } else { /* clipping */ - zbufclip(zspan, zvlnr, f1, f2, f3, c1, c2, c3); - zbufclip(zspan, zvlnr, f1, f3, f4, c1, c3, c4); + zbufclip(zspan, obi, zvlnr, f1, f2, f3, c1, c2, c3); + zbufclip(zspan, obi, zvlnr, f1, f3, f4, c1, c3, c4); } return; } @@ -1805,90 +1919,89 @@ void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float * hoco_to_zco(zspan, vez+8, f3); hoco_to_zco(zspan, vez+12, f4); - zspan->zbuffunc(zspan, zvlnr, vez, vez+4, vez+8, vez+12); + zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, vez+12); } /* ***************** ZBUFFER MAIN ROUTINES **************** */ -void set_part_zbuf_clipflag(RenderPart *pa) +void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag, void(*fillfunc)(RenderPart*, ZSpan*, int, void*), void *data) { - VertRen *ver=NULL; - float minx, miny, maxx, maxy, wco; - int v; - char *clipflag; - - /* flags stored in part now */ - clipflag= pa->clipflag= MEM_mallocN(R.totvert+1, "part clipflags"); - - minx= (2*pa->disprect.xmin - R.winx-1)/(float)R.winx; - maxx= (2*pa->disprect.xmax - R.winx+1)/(float)R.winx; - miny= (2*pa->disprect.ymin - R.winy-1)/(float)R.winy; - maxy= (2*pa->disprect.ymax - R.winy+1)/(float)R.winy; - - for(v=0; vho[3]; - - *clipflag= 0; - if( ver->ho[0] > maxx*wco) *clipflag |= 1; - else if( ver->ho[0]< minx*wco) *clipflag |= 2; - if( ver->ho[1] > maxy*wco) *clipflag |= 4; - else if( ver->ho[1]< miny*wco) *clipflag |= 8; - } -} - -void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag) -{ - ZSpan zspan; + ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; + ZSpan zspans[16], *zspan; /* 16 = RE_MAX_OSA */ VlakRen *vlr= NULL; VertRen *v1, *v2, *v3, *v4; Material *ma=0; - int v, zvlnr; + ObjectInstanceRen *obi; + ObjectRen *obr; + float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0}; + int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0; short nofill=0, env=0, wire=0, all_z= layflag & SCE_LAY_ALL_Z; - char *clipflag= pa->clipflag; - - zbuf_alloc_span(&zspan, pa->rectx, pa->recty); - - /* needed for transform from hoco to zbuffer co */ - zspan.zmulx= ((float)R.winx)/2.0; - zspan.zmuly= ((float)R.winy)/2.0; - - if(R.osa) { - zspan.zofsx= -pa->disprect.xmin - R.jit[pa->sample][0]; - zspan.zofsy= -pa->disprect.ymin - R.jit[pa->sample][1]; - } - else if(R.i.curblur) { - zspan.zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0]; - zspan.zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1]; - } - else { - zspan.zofsx= -pa->disprect.xmin; - zspan.zofsy= -pa->disprect.ymin; - } - /* to center the sample position */ - zspan.zofsx -= 0.5f; - zspan.zofsy -= 0.5f; - - /* the buffers */ - zspan.rectz= pa->rectz; - zspan.rectp= pa->rectp; - fillrect(pa->rectp, pa->rectx, pa->recty, 0); - fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); - - /* filling methods */ - zspan.zbuffunc= zbuffillGL4; - zspan.zbuflinefunc= zbufline; - for(v=0; vsample); - if((v & 255)==0) vlr= R.vlaknodes[v>>8].vlak; - else vlr++; + for(zsample=0; zsamplerectx, pa->recty, R.clipcrop); - if((vlr->flag & R_VISIBLE)) { + /* needed for transform from hoco to zbuffer co */ + zspan->zmulx= ((float)R.winx)/2.0; + zspan->zmuly= ((float)R.winy)/2.0; + + if(R.osa) { + zspan->zofsx= -pa->disprect.xmin - R.jit[pa->sample+zsample][0]; + zspan->zofsy= -pa->disprect.ymin - R.jit[pa->sample+zsample][1]; + } + else if(R.i.curblur) { + zspan->zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0]; + zspan->zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1]; + } + else { + zspan->zofsx= -pa->disprect.xmin; + zspan->zofsy= -pa->disprect.ymin; + } + /* to center the sample position */ + zspan->zofsx -= 0.5f; + zspan->zofsy -= 0.5f; + + /* the buffers */ + if(zsample == samples-1) { + zspan->rectz= pa->rectz; + zspan->rectp= pa->rectp; + zspan->recto= pa->recto; + } + else { + zspan->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); + zspan->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); + zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); + } + + fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); + fillrect(zspan->rectp, pa->rectx, pa->recty, 0); + fillrect(zspan->recto, pa->rectx, pa->recty, 0); + + /* filling methods */ + zspan->zbuffunc= zbuffillGL4; + zspan->zbuflinefunc= zbufline; + } + + for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { + obr= obi->obr; + + if(obi->flag & R_TRANSFORMED) + zbuf_make_winmat(&R, obi->mat, winmat); + else + zbuf_make_winmat(&R, NULL, winmat); + + zbuf_project_cache_clear(cache, obr->totvert); + + for(v=0; vtotvlak; v++) { + if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; + else vlr++; + /* three cases, visible for render, only z values and nothing */ if(vlr->lay & lay) { if(vlr->mat!=ma) { @@ -1897,8 +2010,10 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag) env= (ma->mode & MA_ENV); wire= (ma->mode & MA_WIRE); - if(ma->mode & MA_ZINV) zspan.zbuffunc= zbuffillGLinv4; - else zspan.zbuffunc= zbuffillGL4; + for(zsample=0; zsamplemode & MA_ZINV) zspans[zsample].zbuffunc= zbuffillGLinv4; + else zspans[zsample].zbuffunc= zbuffillGL4; + } } } else if(all_z) { @@ -1910,36 +2025,55 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag) nofill= 1; ma= NULL; /* otherwise nofill can hang */ } - - if(nofill==0) { + + if(!(vlr->flag & R_HIDDEN) && nofill==0) { unsigned short partclip; v1= vlr->v1; v2= vlr->v2; v3= vlr->v3; v4= vlr->v4; - + + c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1); + c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2); + c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3); + /* partclipping doesn't need viewplane clipping */ - partclip= clipflag[v1->index] & clipflag[v2->index] & clipflag[v3->index]; - if(v4) - partclip &= clipflag[v4->index]; - + partclip= c1 & c2 & c3; + if(v4) { + c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4); + partclip &= c4; + } + if(partclip==0) { if(env) zvlnr= -1; else zvlnr= v+1; - - if(wire) zbufclipwire(&zspan, zvlnr, vlr); - else { - /* strands allow to be filled in as quad */ - if(v4 && (vlr->flag & R_STRAND)) { - zbufclip4(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v4->ho, v1->clip, v2->clip, v3->clip, v4->clip); + + c1= testclip(ho1); + c2= testclip(ho2); + c3= testclip(ho3); + if(v4) + c4= testclip(ho4); + + for(zsample=0; zsampleec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + else + zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0); } else { - zbufclip(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v1->clip, v2->clip, v3->clip); - if(v4) { - if(zvlnr>0) zvlnr+= RE_QUAD_OFFS; - zbufclip(&zspan, zvlnr, v1->ho, v3->ho, v4->ho, v1->clip, v3->clip, v4->clip); + /* strands allow to be filled in as quad */ + if(v4 && (vlr->flag & R_STRAND)) { + zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + } + else { + zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); + if(v4) + zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); } } } @@ -1947,8 +2081,21 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag) } } } - - zbuf_free_span(&zspan); + + for(zsample=0; zsamplesample+zsample, data); + + if(zsample != samples-1) { + MEM_freeN(zspan->rectz); + MEM_freeN(zspan->rectp); + MEM_freeN(zspan->recto); + } + + zbuf_free_span(zspan); + } } typedef struct { @@ -1996,10 +2143,8 @@ void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Re /* needed for projectvert */ MTC_Mat4MulMat4(winmat, vw->viewmat, vw->winmat); - /* for clipping... bad stuff actually */ - R.clipcrop= 1.0f; - - zbuf_alloc_span(&zspan, vw->rectx, vw->recty); + /* 1.0f for clipping in clippyra()... bad stuff actually */ + zbuf_alloc_span(&zspan, vw->rectx, vw->recty, 1.0f); zspan.zmulx= ((float)vw->rectx)/2.0; zspan.zmuly= ((float)vw->recty)/2.0; zspan.zofsx= -0.5f; @@ -2008,6 +2153,7 @@ void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Re /* the buffers */ zspan.rectz= (int *)vw->rectz; zspan.rectp= (int *)vw->rect; + zspan.recto= MEM_callocN(sizeof(int)*vw->rectx*vw->recty, "radiorecto"); fillrect(zspan.rectz, vw->rectx, vw->recty, 0x7FFFFFFF); fillrect(zspan.rectp, vw->rectx, vw->recty, 0xFFFFFF); @@ -2036,62 +2182,74 @@ void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Re } if(rn->v4) - zbufclip4(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); + zbufclip4(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); else - zbufclip(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3); + zbufclip(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3); } } } else { /* radio render */ + ObjectRen *obr; VlakRen *vlr=NULL; RadFace *rf; int totface=0; - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->radface) { - rf= vlr->radface; - if( (rf->flag & RAD_SHOOT)==0 ) { /* no shootelement */ - - if( rf->flag & RAD_TWOSIDED) zvlnr= totface; - else if( rf->flag & RAD_BACKFACE) zvlnr= 0xFFFFFF; /* receives no energy, but is zbuffered */ - else zvlnr= totface; - - c1= hashlist_projectvert(vlr->v1->co, winmat, hoco[0]); - c2= hashlist_projectvert(vlr->v2->co, winmat, hoco[1]); - c3= hashlist_projectvert(vlr->v3->co, winmat, hoco[2]); - - if(vlr->v4) { - c4= hashlist_projectvert(vlr->v4->co, winmat, hoco[3]); + /* note: radio render doesn't support duplis */ + for(obr=re->objecttable.first; obr; obr=obr->next) { + hashlist_projectvert(NULL, NULL, NULL); /* clear hashlist */ + + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; + + if(vlr->radface) { + rf= vlr->radface; + if( (rf->flag & RAD_SHOOT)==0 ) { /* no shootelement */ + + if( rf->flag & RAD_TWOSIDED) zvlnr= totface; + else if( rf->flag & RAD_BACKFACE) zvlnr= 0xFFFFFF; /* receives no energy, but is zbuffered */ + else zvlnr= totface; + + c1= hashlist_projectvert(vlr->v1->co, winmat, hoco[0]); + c2= hashlist_projectvert(vlr->v2->co, winmat, hoco[1]); + c3= hashlist_projectvert(vlr->v3->co, winmat, hoco[2]); + + if(vlr->v4) { + c4= hashlist_projectvert(vlr->v4->co, winmat, hoco[3]); + } + + if(vlr->v4) + zbufclip4(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); + else + zbufclip(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3); } - - if(vlr->v4) - zbufclip4(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); - else - zbufclip(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3); + totface++; } - totface++; } } } + MEM_freeN(zspan.recto); zbuf_free_span(&zspan); } -void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, float jity) +void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int size, float jitx, float jity) { + ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; ZSpan zspan; + ObjectInstanceRen *obi; + ObjectRen *obr; VlakRen *vlr= NULL; Material *ma= NULL; StrandSegment sseg; StrandRen *strand= NULL; StrandVert *svert; - int a, b, ok=1, lay= -1; + float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4]; + int a, b, i, c1, c2, c3, c4, ok=1, lay= -1; if(lar->mode & LA_LAYER) lay= lar->lay; - zbuf_alloc_span(&zspan, size, size); + /* 1.0f for clipping in clippyra()... bad stuff actually */ + zbuf_alloc_span(&zspan, size, size, 1.0f); zspan.zmulx= ((float)size)/2.0; zspan.zmuly= ((float)size)/2.0; zspan.zofsx= jitx; @@ -2109,61 +2267,103 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, zspan.zbuflinefunc= zbufline_onlyZ; zspan.zbuffunc= zbuffillGL_onlyZ; - for(a=0; atotvlak; a++) { + for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { + obr= obi->obr; - if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; - else vlr++; - - /* note, these conditions are copied in shadowbuf_autoclip() */ - if(vlr->mat!= ma) { - ma= vlr->mat; - ok= 1; - if((ma->mode & MA_SHADBUF)==0) ok= 0; - } - - if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) { - if(ma->mode & MA_WIRE) zbufclipwire(&zspan, a+1, vlr); - else if(vlr->flag & R_STRAND) zbufclipwire(&zspan, a+1, vlr); - else { - if(vlr->v4) - zbufclip4(&zspan, 0, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip, vlr->v4->clip); - else - zbufclip(&zspan, 0, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip); - } - } - } - - /* shadow */ - for(a=0; atotstrand; a++) { - if((a & 255)==0) strand= re->strandnodes[a>>8].strand; - else strand++; - - if(strand->clip) + if(obr->ob==re->excludeob) continue; - sseg.buffer= strand->buffer; - sseg.sqadaptcos= sseg.buffer->adaptcos; - sseg.sqadaptcos *= sseg.sqadaptcos; - sseg.strand= strand; - svert= strand->vert; + if(obi->flag & R_TRANSFORMED) + Mat4MulMat4(obwinmat, obi->mat, winmat); + else + Mat4CpyMat4(obwinmat, winmat); - /* note, these conditions are copied in shadowbuf_autoclip() */ - if(sseg.buffer->ma!= ma) { - ma= sseg.buffer->ma; - ok= 1; - if((ma->mode & MA_SHADBUF)==0) ok= 0; - } + zbuf_project_cache_clear(cache, obr->totvert); - if(ok && (sseg.buffer->lay & lay)) { - for(b=0; btotvert-1; b++, svert++) { - sseg.v[0]= (b > 0)? (svert-1): svert; - sseg.v[1]= svert; - sseg.v[2]= svert+1; - sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1; + /* faces */ + for(a=0; atotvlak; a++) { - render_strand_segment(re, NULL, &zspan, &sseg); + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + /* note, these conditions are copied in shadowbuf_autoclip() */ + if(vlr->mat!= ma) { + ma= vlr->mat; + ok= 1; + if((ma->mode & MA_SHADBUF)==0) ok= 0; } + + if(ok && (vlr->lay & lay) && !(vlr->flag & R_HIDDEN)) { + c1= zbuf_shadow_project(cache, vlr->v1->index, obwinmat, vlr->v1->co, ho1); + c2= zbuf_shadow_project(cache, vlr->v2->index, obwinmat, vlr->v2->co, ho2); + c3= zbuf_shadow_project(cache, vlr->v3->index, obwinmat, vlr->v3->co, ho3); + + if((ma->mode & MA_WIRE) || (vlr->flag & R_STRAND)) { + if(vlr->v4) { + c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4); + zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + } + else + zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0); + } + else { + if(vlr->v4) { + c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4); + zbufclip4(&zspan, 0, 0, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + } + else + zbufclip(&zspan, 0, 0, ho1, ho2, ho3, c1, c2, c3); + } + } + + if((a & 255)==255 && re->test_break()) + break; } + + /* strands */ + for(a=0; atotstrand; a++) { + if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; + else strand++; + + sseg.obi= obi; + sseg.buffer= strand->buffer; + sseg.sqadaptcos= sseg.buffer->adaptcos; + sseg.sqadaptcos *= sseg.sqadaptcos; + sseg.strand= strand; + svert= strand->vert; + + /* note, these conditions are copied in shadowbuf_autoclip() */ + if(sseg.buffer->ma!= ma) { + ma= sseg.buffer->ma; + ok= 1; + if((ma->mode & MA_SHADBUF)==0) ok= 0; + } + + if(ok && (sseg.buffer->lay & lay)) { + zbuf_project_cache_clear(cache, strand->totvert); + + for(b=0; btotvert-1; b++, svert++) { + sseg.v[0]= (b > 0)? (svert-1): svert; + sseg.v[1]= svert; + sseg.v[2]= svert+1; + sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1; + + c1= zbuf_shadow_project(cache, sseg.v[0]-strand->vert, obwinmat, sseg.v[0]->co, ho1); + c2= zbuf_shadow_project(cache, sseg.v[1]-strand->vert, obwinmat, sseg.v[1]->co, ho2); + c3= zbuf_shadow_project(cache, sseg.v[2]-strand->vert, obwinmat, sseg.v[2]->co, ho3); + c4= zbuf_shadow_project(cache, sseg.v[3]-strand->vert, obwinmat, sseg.v[3]->co, ho4); + + if(!(c1 & c2 & c3 & c4)) + render_strand_segment(NULL, winmat, NULL, &zspan, &sseg); + } + } + + if((a & 255)==255 && re->test_break()) + break; + } + + if(re->test_break()) + break; } /* merge buffers */ @@ -2177,7 +2377,7 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, zbuf_free_span(&zspan); } -static void zbuffill_sss(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) { double zxd, zyd, zy0, z; float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2; @@ -2244,23 +2444,27 @@ static void zbuffill_sss(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v z= (double)sn1*zxd + zy0; for(x= sn1; x<=sn2; x++, z+=zxd) - zspan->sss_func(zspan->sss_handle, zvlnr, x, y, z); + zspan->sss_func(zspan->sss_handle, obi, zvlnr, x, y, z); zy0 -= zyd; } } -void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void *, int, int, int, int)) +void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void*, int, int, int, int, int)) { + ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; ZSpan zspan; + ObjectInstanceRen *obi; + ObjectRen *obr; VlakRen *vlr= NULL; VertRen *v1, *v2, *v3, *v4; Material *ma=0, *sss_ma= R.sss_mat; + float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0}; + int i, v, zvlnr, c1, c2, c3, c4=0; short nofill=0, env=0, wire=0; - char *clipflag= pa->clipflag; - int v, zvlnr; - zbuf_alloc_span(&zspan, pa->rectx, pa->recty); + zbuffer_part_bounds(&R, pa, bounds); + zbuf_alloc_span(&zspan, pa->rectx, pa->recty, R.clipcrop); zspan.sss_handle= handle; zspan.sss_func= func; @@ -2278,59 +2482,81 @@ void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(vo /* fill front and back zbuffer */ if(pa->rectz) { + fillrect(pa->recto, pa->rectx, pa->recty, 0); fillrect(pa->rectp, pa->rectx, pa->recty, 0); fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); } if(pa->rectbackz) { + fillrect(pa->rectbacko, pa->rectx, pa->recty, 0); fillrect(pa->rectbackp, pa->rectx, pa->recty, 0); fillrect(pa->rectbackz, pa->rectx, pa->recty, -0x7FFFFFFF); } - for(v=0; v>8].vlak; - else vlr++; - - if((vlr->flag & R_VISIBLE) && material_in_material(vlr->mat, sss_ma)) { - /* three cases, visible for render, only z values and nothing */ - if(vlr->lay & lay) { - if(vlr->mat!=ma) { - ma= vlr->mat; - nofill= ma->mode & MA_ONLYCAST; - env= (ma->mode & MA_ENV); - wire= (ma->mode & MA_WIRE); - } - } - else { - nofill= 1; - ma= NULL; /* otherwise nofill can hang */ - } - - if(nofill==0 && wire==0 && env==0) { - unsigned short partclip; - - v1= vlr->v1; - v2= vlr->v2; - v3= vlr->v3; - v4= vlr->v4; - - /* partclipping doesn't need viewplane clipping */ - partclip= clipflag[v1->index] & clipflag[v2->index] & clipflag[v3->index]; - if(v4) - partclip &= clipflag[v4->index]; - + for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { + obr= obi->obr; - if(partclip==0) { - zvlnr= v+1; - zbufclip(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v1->clip, v2->clip, v3->clip); + if(obi->flag & R_TRANSFORMED) + zbuf_make_winmat(&R, obi->mat, winmat); + else + zbuf_make_winmat(&R, NULL, winmat); + + zbuf_project_cache_clear(cache, obr->totvert); + + for(v=0; vtotvlak; v++) { + if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; + else vlr++; + + if(material_in_material(vlr->mat, sss_ma)) { + /* three cases, visible for render, only z values and nothing */ + if(vlr->lay & lay) { + if(vlr->mat!=ma) { + ma= vlr->mat; + nofill= ma->mode & MA_ONLYCAST; + env= (ma->mode & MA_ENV); + wire= (ma->mode & MA_WIRE); + } + } + else { + nofill= 1; + ma= NULL; /* otherwise nofill can hang */ + } + + if(nofill==0 && wire==0 && env==0) { + unsigned short partclip; + + v1= vlr->v1; + v2= vlr->v2; + v3= vlr->v3; + v4= vlr->v4; + + c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1); + c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2); + c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3); + + /* partclipping doesn't need viewplane clipping */ + partclip= c1 & c2 & c3; if(v4) { - zvlnr+= RE_QUAD_OFFS; - zbufclip(&zspan, zvlnr, v1->ho, v3->ho, v4->ho, v1->clip, v3->clip, v4->clip); + c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4); + partclip &= c4; + } + + if(partclip==0) { + c1= testclip(ho1); + c2= testclip(ho2); + c3= testclip(ho3); + + zvlnr= v+1; + zbufclip(&zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); + if(v4) { + c4= testclip(ho4); + zbufclip(&zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); + } } } } } } - + zbuf_free_span(&zspan); } @@ -2549,7 +2775,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * static int firsttime= 1; char *rectmove, *dm; - zbuf_alloc_span(&zspan, xsize, ysize); + zbuf_alloc_span(&zspan, xsize, ysize, 1.0f); zspan.zmulx= ((float)xsize)/2.0; zspan.zmuly= ((float)ysize)/2.0; zspan.zofsx= 0.0f; @@ -2861,56 +3087,76 @@ static void copyto_abufz(RenderPart *pa, int *arectz, int sample) static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay) { - ZSpan zspan; + ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; + ZSpan zspans[16], *zspan; /* MAX_OSA */ Material *ma=NULL; + ObjectInstanceRen *obi; + ObjectRen *obr; VlakRen *vlr=NULL; VertRen *v1, *v2, *v3, *v4; float vec[3], hoco[4], mul, zval, fval; - int v, zvlnr= 0, zsample, dofill= 0; - char *clipflag= pa->clipflag; - - zbuf_alloc_span(&zspan, pa->rectx, pa->recty); - - /* needed for transform from hoco to zbuffer co */ - zspan.zmulx= ((float)R.winx)/2.0; - zspan.zmuly= ((float)R.winy)/2.0; - - /* the buffers */ - zspan.arectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz"); - zspan.apixbuf= APixbuf; - zspan.apsmbase= apsmbase; - - /* filling methods */ - zspan.zbuffunc= zbuffillAc4; - zspan.zbuflinefunc= zbuflineAc; - - for(zsample=0; zsamplerectx, pa->recty, R.clipcrop); - copyto_abufz(pa, zspan.arectz, zsample); /* init zbuffer */ - zspan.mask= 1<zmulx= ((float)R.winx)/2.0; + zspan->zmuly= ((float)R.winy)/2.0; + /* the buffers */ + zspan->arectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz"); + zspan->apixbuf= APixbuf; + zspan->apsmbase= apsmbase; + + /* filling methods */ + zspan->zbuffunc= zbuffillAc4; + zspan->zbuflinefunc= zbuflineAc; + + copyto_abufz(pa, zspan->arectz, zsample); /* init zbuffer */ + zspan->mask= 1<disprect.xmin - R.jit[zsample][0]; - zspan.zofsy= -pa->disprect.ymin - R.jit[zsample][1]; + zspan->zofsx= -pa->disprect.xmin - R.jit[zsample][0]; + zspan->zofsy= -pa->disprect.ymin - R.jit[zsample][1]; } else if(R.i.curblur) { - zspan.zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0]; - zspan.zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1]; + zspan->zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0]; + zspan->zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1]; } else { - zspan.zofsx= -pa->disprect.xmin; - zspan.zofsy= -pa->disprect.ymin; + zspan->zofsx= -pa->disprect.xmin; + zspan->zofsy= -pa->disprect.ymin; } /* to center the sample position */ - zspan.zofsx -= 0.5f; - zspan.zofsy -= 0.5f; + zspan->zofsx -= 0.5f; + zspan->zofsy -= 0.5f; - /* we use this to test if nothing was filled in */ - zvlnr= 0; + } + + /* we use this to test if nothing was filled in */ + zvlnr= 0; - for(v=0; vnext) { + obr= obi->obr; + + if(obi->flag & R_TRANSFORMED) + zbuf_make_winmat(&R, obi->mat, winmat); + else + zbuf_make_winmat(&R, NULL, winmat); + + zbuf_project_cache_clear(cache, obr->totvert); + + for(v=0; vtotvlak; v++) { if((v & 255)==0) - vlr= R.vlaknodes[v>>8].vlak; + vlr= obr->vlaknodes[v>>8].vlak; else vlr++; if(vlr->mat!=ma) { @@ -2919,24 +3165,30 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un } if(dofill) { - if((vlr->flag & R_VISIBLE) && (vlr->lay & lay)) { + if(!(vlr->flag & R_HIDDEN) && (vlr->lay & lay)) { unsigned short partclip; v1= vlr->v1; v2= vlr->v2; v3= vlr->v3; v4= vlr->v4; - + + c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1); + c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2); + c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3); + /* partclipping doesn't need viewplane clipping */ - partclip= clipflag[v1->index] & clipflag[v2->index] & clipflag[v3->index]; - if(v4) - partclip &= clipflag[v4->index]; - + partclip= c1 & c2 & c3; + if(v4) { + c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4); + partclip &= c4; + } + if(partclip==0) { /* a little advantage for transp rendering (a z offset) */ if( ma->zoffs != 0.0) { mul= 0x7FFFFFFF; - zval= mul*(1.0+v1->ho[2]/v1->ho[3]); + zval= mul*(1.0+ho1[2]/ho1[3]); VECCOPY(vec, v1->co); /* z is negative, otherwise its being clipped */ @@ -2944,40 +3196,55 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un projectverto(vec, R.winmat, hoco); fval= mul*(1.0+hoco[2]/hoco[3]); - zspan.polygon_offset= (int) fabs(zval - fval ); + polygon_offset= (int) fabs(zval - fval ); } - else zspan.polygon_offset= 0; + else polygon_offset= 0; zvlnr= v+1; - - if(ma->mode & (MA_WIRE)) zbufclipwire(&zspan, zvlnr, vlr); - else { - if(v4 && (vlr->flag & R_STRAND)) { - zbufclip4(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v4->ho, v1->clip, v2->clip, v3->clip, v4->clip); + + c1= testclip(ho1); + c2= testclip(ho2); + c3= testclip(ho3); + if(v4) + c4= testclip(ho4); + + for(zsample=0; zsamplepolygon_offset= polygon_offset; + + if(ma->mode & (MA_WIRE)) { + if(v4) + zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + else + zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0); } else { - zbufclip(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v1->clip, v2->clip, v3->clip); - if(v4) { - zvlnr+= RE_QUAD_OFFS; - zbufclip(&zspan, zvlnr, v1->ho, v3->ho, v4->ho, v1->clip, v3->clip, v4->clip); + if(v4 && (vlr->flag & R_STRAND)) { + zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + } + else { + zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); + if(v4) + zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); } } } } + if((v & 255)==255) + if(R.test_break()) + break; } - if( (v & 255)==255) - if(R.test_break()) - break; } } - - if(R.osa==0) break; + if(R.test_break()) break; - if(zvlnr==0) break; } - MEM_freeN(zspan.arectz); - zbuf_free_span(&zspan); + for(zsample=0; zsamplearectz); + zbuf_free_span(zspan); + } return zvlnr; } @@ -3020,16 +3287,18 @@ void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, lo } } -static void add_transp_obindex(RenderLayer *rl, int offset, int facenr) +static void add_transp_obindex(RenderLayer *rl, int offset, int obi, int facenr) { - VlakRen *vlr= RE_findOrAddVlak(&R, (facenr-1) & RE_QUAD_MASK); - if(vlr && vlr->ob) { + ObjectRen *obr= R.objectinstance[obi].obr; + VlakRen *vlr= RE_findOrAddVlak(obr, (facenr-1) & RE_QUAD_MASK); + + if(vlr && obr->ob) { RenderPass *rpass; for(rpass= rl->passes.first; rpass; rpass= rpass->next) { if(rpass->passtype == SCE_PASS_INDEXOB) { float *fp= rpass->rect + offset; - *fp= (float)vlr->ob->index; + *fp= (float)obr->ob->index; break; } } @@ -3170,25 +3439,30 @@ void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alph } +typedef struct ZTranspRow { + int obi; + int z; + int p; + int mask; +} ZTranspRow; static int vergzvlak(const void *a1, const void *a2) { - const int *x1=a1, *x2=a2; + const ZTranspRow *r1 = a1, *r2 = a2; - if( x1[0] < x2[0] ) return 1; - else if( x1[0] > x2[0]) return -1; + if(r1->z < r2->z) return 1; + else if(r1->z > r2->z) return -1; return 0; } - -static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int facenr, int curmask) +static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int obi, int facenr, int curmask) { ShadeInput *shi= ssamp->shi; float xs, ys; ssamp->tot= 0; - shade_input_set_triangle(shi, facenr, 1); + shade_input_set_triangle(shi, obi, facenr, 1); /* officially should always be true... we have no sky info */ if(shi->vlr) { @@ -3238,9 +3512,9 @@ static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int } } -static int shade_tra_samples(ShadeSample *ssamp, int x, int y, int z, int facenr, int mask) +static int shade_tra_samples(ShadeSample *ssamp, int x, int y, ZTranspRow *row) { - shade_tra_samples_fill(ssamp, x, y, z, facenr, mask); + shade_tra_samples_fill(ssamp, x, y, row->z, row->obi, row->p, row->mask); if(ssamp->tot) { ShadeInput *shi= ssamp->shi; @@ -3352,6 +3626,7 @@ void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf) } #define MAX_ZROW 2000 + /* main render call to fill in pass the full transparent layer */ /* returns a mask, only if a) transp rendered and b) solid was rendered */ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass) @@ -3362,9 +3637,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas APixstr *ap, *aprect, *apn; ListBase apsmbase={NULL, NULL}; ShadeResult samp_shr[16]; /* MAX_OSA */ + ZTranspRow zrow[MAX_ZROW]; float sampalpha, *passrect= pass; long *rdrect; - int x, y, crop=0, a, zrow[MAX_ZROW][3], totface; + int x, y, crop=0, a, totface; int addpassflag, offs= 0, od, addzbuf; unsigned short *ztramask= NULL; @@ -3383,7 +3659,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas /* general shader info, passes */ shade_sample_initialize(&ssamp, pa, rl); addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); - if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) + if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) addzbuf= 1; /* strands layer needs the z-buffer */ else addzbuf= rl->passflag & SCE_PASS_Z; @@ -3452,9 +3728,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas while(apn) { for(a=0; a<4; a++) { if(apn->p[a]) { - zrow[totface][0]= apn->z[a]; - zrow[totface][1]= apn->p[a]; - zrow[totface][2]= apn->mask[a]; + zrow[totface].obi= apn->obi[a]; + zrow[totface].z= apn->z[a]; + zrow[totface].p= apn->p[a]; + zrow[totface].mask= apn->mask[a]; totface++; if(totface>=MAX_ZROW) totface= MAX_ZROW-1; } @@ -3464,31 +3741,29 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas } if(totface==2) { - if(zrow[0][0] < zrow[1][0]) { - a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a; - a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a; - a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a; + if(zrow[0].z < zrow[1].z) { + SWAP(ZTranspRow, zrow[0], zrow[1]); } } else if(totface>2) { - qsort(zrow, totface, sizeof(int)*3, vergzvlak); + qsort(zrow, totface, sizeof(ZTranspRow), vergzvlak); } /* zbuffer and index pass for transparent, no AA or filters */ if(addzbuf) - if(pa->rectz[od]>zrow[totface-1][0]) - pa->rectz[od]= zrow[totface-1][0]; + if(pa->rectz[od]>zrow[totface-1].z) + pa->rectz[od]= zrow[totface-1].z; if(addpassflag & SCE_PASS_INDEXOB) - add_transp_obindex(rl, od, zrow[totface-1][1]); + add_transp_obindex(rl, od, zrow[totface-1].obi, zrow[totface-1].p); if(R.osa==0) { while(totface>0) { totface--; - if(shade_tra_samples(&ssamp, x, y, zrow[totface][0], zrow[totface][1], zrow[totface][2])) { + if(shade_tra_samples(&ssamp, x, y, &zrow[totface])) { if(addpassflag) add_transp_passes(rl, od, ssamp.shr, (1.0f-pass[3])*ssamp.shr[0].combined[3]); @@ -3512,11 +3787,11 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas while(totface>0) { totface--; - if(shade_tra_samples(&ssamp, x, y, zrow[totface][0], zrow[totface][1], zrow[totface][2])) { + if(shade_tra_samples(&ssamp, x, y, &zrow[totface])) { filled= addtosamp_shr(samp_shr, &ssamp, addpassflag); if(ztramask) - *sp |= zrow[totface][2]; + *sp |= zrow[totface].mask; if(filled==0) break; } diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index db86f14ad76..43e727f4e96 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1641,19 +1641,6 @@ void modifiers_explodeFacepa(void *arg1, void *arg2) emd->flag |= eExplodeFlag_CalcFaces; } -static void modifiers_psysEnable(void *ob_v, void *md_v) -{ - ParticleSystemModifierData *psmd = (ParticleSystemModifierData*) md_v; - - if(psmd->modifier.mode & eModifierMode_Realtime) { - psmd->psys->flag |= PSYS_ENABLED; - } - else { - psmd->psys->flag &= ~PSYS_ENABLED; - PE_free_particle_edit(psmd->psys); - } -} - static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -1693,8 +1680,6 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) { uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering"); but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display"); - if (md->type==eModifierType_ParticleSystem) - uiButSetFunc(but, modifiers_psysEnable, ob, md); if (mti->flags&eModifierTypeFlag_SupportsEditmode) { uiDefIconButBitI(block, TOG, eModifierMode_Editmode, B_MODIFIER_RECALC, VICON_EDIT, x+10+buttonWidth-20, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)"); } @@ -4956,7 +4941,7 @@ static void editing_panel_links(Object *ob) xco, 154, 130,20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButC(block, MENU, REDRAWVIEW3D, "Empty Drawtype%t|Arrows%x1|Single Arrow%x4|Plain Axes%x2|Circle%x3|Cube%x5", + uiDefButC(block, MENU, REDRAWVIEW3D, "Empty Drawtype%t|Arrows%x1|Single Arrow%x4|Plain Axes%x2|Circle%x3|Cube%x5|Sphere%x6|Cone%x7", xco, 128, 140, 20, &ob->empty_drawtype, 0, 0, 0, 0, "The Empty 3D View display style"); uiDefButF(block, NUM, REDRAWVIEW3D, "Size:", xco, 108, 140, 21, &ob->empty_drawsize, 0.01, 10.0, 1, 0, "The size to display the Empty"); @@ -5220,9 +5205,16 @@ void sculptmode_draw_interface_textures(uiBlock *block, unsigned short cx, unsig if(sd->texrept != SCULPTREPT_3D) { uiBlockBeginAlign(block); uiDefButF(block,NUM,0, "Angle", cx,cy,115,19, &mtex->warpfac, 0,360,100,0, "Rotate texture counterclockwise"); + /*Moved inside, so that following buttons aren't made bigger for no reason*/ + cy-= 20; } - cy-= 20; - + + /* Added Rake button. Needs to be turned off if 3D is on / disappear*/ + if(sd->texrept != SCULPTREPT_3D){ + uiDefButC(block,TOG,B_NOP, "Rake", cx,cy,115,19, &sd->rake, 0,0,0,0,"Rotate the brush in the direction of motion"); + cy-=20; + } + if(sd->texrept != SCULPTREPT_DRAG) { uiBlockBeginAlign(block); but= uiDefIconButC(block, TOG, REDRAWBUTSEDIT, sd->texsep ? ICON_UNLOCKED : ICON_LOCKED, cx,cy,20,19, &sd->texsep,0,0,0,0, "Locks the texture sizes together"); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index fcb05c8f00e..d23b12803c4 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -940,29 +940,29 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s else { strcpy (data->subtarget, ""); } - + uiBlockEndAlign(block); - + /* Settings */ uiBlockBeginAlign(block); uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tail", *xco, *yco-92, 137, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tail als last element in Chain"); - uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco, *yco-112,137,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain"); - + uiDefButS(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco, *yco-112,137,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain"); + uiBlockBeginAlign(block); uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco+147, *yco-92, 137, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target"); uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Rot", *xco+147, *yco-112, 40,19, &data->flag, 0, 0, 0, 0, "Chain follows rotation of target"); uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "W ", *xco+187, *yco-112, 97, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target"); - + uiBlockBeginAlign(block); - + uiDefButBitS(block, TOG, CONSTRAINT_IK_STRETCH, B_CONSTRAINT_TEST, "Stretch", *xco, *yco-137,137,19, &data->flag, 0, 0, 0, 0, "Enable IK stretching"); uiBlockBeginAlign(block); uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+147, *yco-137, 137, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations"); uiBlockEndAlign(block); - + /* Pole Vector */ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Pole Target:", *xco+147, *yco-24, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); - + uiBlockBeginAlign(block); uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+147, *yco-44, 137, 19, &data->poletar, "Pole Target Object"); if (is_armature_target(data->poletar)) { @@ -2858,15 +2858,6 @@ void do_effects_panels(unsigned short event) break; case B_PART_ENABLE: if(psys) { - ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); - if(psys->flag & PSYS_ENABLED) { - psmd->modifier.mode |= eModifierMode_Realtime; - } - else { - psmd->modifier.mode &= ~eModifierMode_Realtime; - PE_free_particle_edit(psys); - } - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSOBJECT, 0); @@ -3488,7 +3479,7 @@ static void sb_clear_cache(void *ob_v, void *actsoft_v) static void object_softbodies(Object *ob) { SoftBody *sb=ob->soft; - ParticleSystem *psys; + ParticleSystem *psys=NULL; uiBlock *block; uiBut *but; static int val; @@ -3521,7 +3512,7 @@ static void object_softbodies(Object *ob) MEM_freeN(menustr); } - if(psys_cur){ + if(psys_cur && psys){ if(*softflag & OB_SB_ENABLE) val=1; else diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 26858f657a6..db2225f4823 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -143,6 +143,8 @@ static void draw_bounding_volume(Object *ob); static void drawcube_size(float size); static void drawcircle_size(float size); +static void draw_empty_sphere(float size); +static void draw_empty_cone(float size); /* ************* Setting OpenGL Material ************ */ @@ -412,6 +414,14 @@ void drawaxes(float size, int flag, char drawtype) drawcircle_size(size); break; + case OB_EMPTY_SPHERE: + draw_empty_sphere(size); + break; + + case OB_EMPTY_CONE: + draw_empty_cone(size); + break; + case OB_ARROWS: default: for (axis=0; axis<3; axis++) { @@ -2995,7 +3005,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys) part=psys->part; pars=psys->particles; - if(part==0 || (psys->flag & PSYS_ENABLED)==0) + if(part==0 || !psys_check_enabled(ob, psys)) return; if(pars==0) return; @@ -3984,6 +3994,45 @@ static void drawnurb(Base *base, Nurb *nurb, int dt) if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); } +/* draw a sphere for use as an empty drawtype */ +static void draw_empty_sphere (float size) +{ + float cent=0; + GLUquadricObj *qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + + glPushMatrix(); + glTranslatef(cent, cent, cent); + glScalef(size, size, size); + gluSphere(qobj, 1.0, 8, 5); + + glPopMatrix(); + + gluDeleteQuadric(qobj); +} + +/* draw a cone for use as an empty drawtype */ +static void draw_empty_cone (float size) +{ + float cent=0; + float radius; + GLUquadricObj *qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + + + glPushMatrix(); + + radius = size; + glTranslatef(cent,cent, cent); + glScalef(radius, 2.0*size, radius); + glRotatef(-90., 1.0, 0.0, 0.0); + gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); + + glPopMatrix(); + + gluDeleteQuadric(qobj); +} + /* draw points on curve speed handles */ static void curve_draw_speed(Object *ob) { @@ -5504,4 +5553,3 @@ void draw_object_instance(Object *ob, int dt, int outline) break; } } - diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index 7addda70932..0b33a4df5fc 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -725,54 +725,97 @@ static void draw_cursor(SpaceText *st) { static void calc_text_rcts(SpaceText *st) { - short barheight, barstart, blank_lines; - int lbarstart, lbarh, ltexth; - int pix_available, pix_top_margin, pix_bottom_margin; + int lhlstart, lhlend, ltexth; + short barheight, barstart, hlstart, hlend, blank_lines; + short pix_available, pix_top_margin, pix_bottom_margin, pix_bardiff; - lbarstart= st->top; - lbarh= st->viewlines; pix_top_margin = 8; pix_bottom_margin = 4; pix_available = curarea->winy - pix_top_margin - pix_bottom_margin; ltexth= txt_get_span(st->text->lines.first, st->text->lines.last); blank_lines = st->viewlines / 2; - if(ltexth + blank_lines < lbarstart + st->viewlines) - blank_lines = lbarstart + st->viewlines - ltexth; + /* when resizing a vieport with the bar at the bottom to a greater height more blank lines will be added */ + if (ltexth + blank_lines < st->top + st->viewlines) { + blank_lines = st->top + st->viewlines - ltexth; + } ltexth += blank_lines; - barstart = (lbarstart*pix_available)/ltexth; - barheight = (lbarh*pix_available)/ltexth; - if (barheight<20){ - barstart = ((pix_available + barheight - 20 )*lbarstart)/ltexth; - barheight=20; + barheight = (st->viewlines*pix_available) / ltexth; + pix_bardiff = 0; + if (barheight < 20) { + pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */ + barheight = 20; } + barstart = ((pix_available - pix_bardiff) * st->top) / ltexth; - st->txtbar.xmin= 5; - st->txtbar.xmax= 17; - st->txtbar.ymax= curarea->winy - pix_top_margin - barstart; - st->txtbar.ymin= st->txtbar.ymax - barheight; + st->txtbar.xmin = 5; + st->txtbar.xmax = 17; + st->txtbar.ymax = curarea->winy - pix_top_margin - barstart; + st->txtbar.ymin = st->txtbar.ymax - barheight; CLAMP(st->txtbar.ymin, pix_bottom_margin, curarea->winy - pix_top_margin); CLAMP(st->txtbar.ymax, pix_bottom_margin, curarea->winy - pix_top_margin); - st->pix_per_line= (float) ltexth/curarea->winy; + st->pix_per_line= (float) ltexth/pix_available; if (st->pix_per_line<.1) st->pix_per_line=.1f; - lbarstart= MIN2(txt_get_span(st->text->lines.first, st->text->curl), + lhlstart = MIN2(txt_get_span(st->text->lines.first, st->text->curl), txt_get_span(st->text->lines.first, st->text->sell)); - lbarh= abs(txt_get_span(st->text->lines.first, st->text->curl)-txt_get_span(st->text->lines.first, st->text->sell)); - - barheight= (lbarh*pix_available)/ltexth; - if (barheight<2) barheight=2; - - barstart= (lbarstart*pix_available)/ltexth; + lhlend = MAX2(txt_get_span(st->text->lines.first, st->text->curl), + txt_get_span(st->text->lines.first, st->text->sell)); + + hlstart = (lhlstart * pix_available) / ltexth; + hlend = (lhlend * pix_available) / ltexth; + + /* the scrollbar is non-linear sized */ + if (pix_bardiff > 0) { + /* the start of the highlight is in the current viewport */ + if (lhlstart >= st->top && lhlstart <= st->top + st->viewlines) { + /* speed the progresion of the start of the highlight through the scrollbar */ + hlstart = ( ( (pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->viewlines); + } + else if (lhlstart > st->top + st->viewlines && hlstart < barstart + barheight && hlstart > barstart) { + /* push hl start down */ + hlstart = barstart + barheight; + } + else if (lhlend > st->top && lhlstart < st->top && hlstart > barstart) { + /*fill out start */ + hlstart = barstart; + } + + if (hlend <= hlstart) { + hlend = hlstart + 2; + } + + /* the end of the highlight is in the current viewport */ + if (lhlend >= st->top && lhlend <= st->top + st->viewlines) { + /* speed the progresion of the end of the highlight through the scrollbar */ + hlend = (((pix_available - pix_bardiff )*lhlend)/ltexth) + (pix_bardiff * (lhlend - st->top)/st->viewlines); + } + else if (lhlend < st->top && hlend >= barstart - 2 && hlend < barstart + barheight) { + /* push hl end up */ + hlend = barstart; + } + else if (lhlend > st->top + st->viewlines && lhlstart < st->top + st->viewlines && hlend < barstart + barheight) { + /* fill out end */ + hlend = barstart + barheight; + } + + if (hlend <= hlstart) { + hlstart = hlend - 2; + } + } + + if (hlend - hlstart < 2) { + hlend = hlstart + 2; + } st->txtscroll.xmin= 5; st->txtscroll.xmax= 17; - st->txtscroll.ymax= curarea->winy-barstart; - st->txtscroll.ymin= st->txtscroll.ymax - barheight; + st->txtscroll.ymax= curarea->winy - pix_top_margin - hlstart; + st->txtscroll.ymin= curarea->winy - pix_top_margin - hlend; CLAMP(st->txtscroll.ymin, pix_bottom_margin, curarea->winy - pix_top_margin); CLAMP(st->txtscroll.ymax, pix_bottom_margin, curarea->winy - pix_top_margin); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 7c25afc94c2..8efa44213ed 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -261,7 +261,7 @@ void editbones_to_armature (ListBase *list, Object *ob) if (fBone->parent==eBone) fBone->parent= eBone->parent; } - printf("Warning; removed zero sized bone: %s\n", eBone->name); + printf("Warning: removed zero sized bone: %s\n", eBone->name); BLI_freelinkN (list, eBone); } } @@ -1488,7 +1488,7 @@ static EditBone *add_editbone(char *name) EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone"); - BLI_strncpy (bone->name, name, 32); + BLI_strncpy(bone->name, name, 32); unique_editbone_name(&G.edbo, bone->name); BLI_addtail(&G.edbo, bone); @@ -1663,6 +1663,19 @@ void addvert_armature(void) while(get_mbut()&R_MOUSE); } +/* adds an EditBone between the nominated locations (should be in the right space) */ +static EditBone *add_points_bone (float head[], float tail[]) +{ + EditBone *ebo; + + ebo= add_editbone("Bone"); + + VECCOPY(ebo->head, head); + VECCOPY(ebo->tail, tail); + + return ebo; +} + static EditBone *get_named_editbone(char *name) { @@ -1858,6 +1871,375 @@ void adduplicate_armature(void) /* *************** END Adding stuff in editmode *************** */ +/* ************** Add/Remove stuff in editmode **************** */ + +/* temporary data-structure for merge/fill bones */ +typedef struct EditBonePoint { + struct EditBonePoint *next, *prev; + + EditBone *head_owner; /* EditBone which uses this point as a 'head' point */ + EditBone *tail_owner; /* EditBone which uses this point as a 'tail' point */ + + float vec[3]; /* the actual location of the point in local/EditMode space */ +} EditBonePoint; + +/* find chain-tips (i.e. bones without children) */ +static void chains_find_tips (ListBase *list) +{ + EditBone *curBone, *ebo; + LinkData *ld; + + /* note: this is potentially very slow ... there's got to be a better way */ + for (curBone= G.edbo.first; curBone; curBone= curBone->next) { + short stop= 0; + + /* is this bone contained within any existing chain? (skip if so) */ + for (ld= list->first; ld; ld= ld->next) { + for (ebo= ld->data; ebo; ebo= ebo->parent) { + if (ebo == curBone) { + stop= 1; + break; + } + } + + if (stop) break; + } + /* skip current bone if it is part of an existing chain */ + if (stop) continue; + + /* is any existing chain part of the chain formed by this bone? */ + stop= 0; + for (ebo= curBone->parent; ebo; ebo= ebo->parent) { + for (ld= list->first; ld; ld= ld->next) { + if (ld->data == ebo) { + ld->data= curBone; + stop= 1; + break; + } + } + + if (stop) break; + } + /* current bone has already been added to a chain? */ + if (stop) continue; + + /* add current bone to a new chain */ + ld= MEM_callocN(sizeof(LinkData), "BoneChain"); + ld->data= curBone; + BLI_addtail(list, ld); + } +} + + +static void fill_add_joint (EditBone *ebo, short eb_tail, ListBase *points) +{ + EditBonePoint *ebp; + float vec[3]; + short found= 0; + + if (eb_tail) { + VECCOPY(vec, ebo->tail); + } + else { + VECCOPY(vec, ebo->head); + } + + // FIXME: this algorithm sucks... it misses things it shouldn't + for (ebp= points->first; ebp; ebp= ebp->next) { + if (VecEqual(ebp->vec, vec)) { + if (eb_tail) { + if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) { + /* so this bone's tail owner is this bone*/ + ebp->tail_owner= ebo; + found= 1; + break; + } + } + else { + if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) { + /* so this bone's head owner is this bone */ + ebp->head_owner= ebo; + found = 1; + break; + } + } + } + } + + /* allocate a new point if no existing point was related */ + if (found == 0) { + ebp= MEM_callocN(sizeof(EditBonePoint), "EditBonePoint"); + + if (eb_tail) { + VECCOPY(ebp->vec, ebo->tail); + ebp->tail_owner= ebo; + } + else { + VECCOPY(ebp->vec, ebo->head); + ebp->head_owner= ebo; + } + + BLI_addtail(points, ebp); + } +} + +/* bone adding between selected joints */ +void fill_bones_armature(void) +{ + bArmature *arm= G.obedit->data; + EditBone *ebo, *newbone=NULL; + ListBase points = {NULL, NULL}; + int count; + + /* loop over all bones, and only consider if visible */ + for (ebo= G.edbo.first; ebo; ebo= ebo->next) { + if ((arm->layer & ebo->layer) && !(ebo->flag & BONE_HIDDEN_A)) { + if (!(ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL)) + fill_add_joint(ebo, 0, &points); + if (ebo->flag & BONE_TIPSEL) + fill_add_joint(ebo, 1, &points); + } + } + + /* the number of joints determines how we fill: + * 1) between joint and cursor (joint=head, cursor=tail) + * 2) between the two joints (order is dependent on active-bone/hierachy) + * 3+) error (a smarter method involving finding chains needs to be worked out + */ + count= BLI_countlist(&points); + + if (count == 0) { + error("No joints selected"); + return; + } + else if (count == 1) { + EditBonePoint *ebp; + float curs[3]; + + /* Get Points - selected joint */ + ebp= (EditBonePoint *)points.first; + + /* Get points - cursor (tail) */ + VECCOPY (curs, give_cursor()); + + Mat4Invert(G.obedit->imat, G.obedit->obmat); + Mat4MulVecfl(G.obedit->imat, curs); + + /* Create a bone */ + newbone= add_points_bone(ebp->vec, curs); + } + else if (count == 2) { + EditBonePoint *ebp, *ebp2; + float head[3], tail[3]; + + /* check that the points don't belong to the same bone */ + ebp= (EditBonePoint *)points.first; + ebp2= ebp->next; + + if ((ebp->head_owner==ebp2->tail_owner) && (ebp->head_owner!=NULL)) { + error("Same bone selected..."); + BLI_freelistN(&points); + return; + } + if ((ebp->tail_owner==ebp2->head_owner) && (ebp->tail_owner!=NULL)) { + error("Same bone selected..."); + BLI_freelistN(&points); + return; + } + + /* find which one should be the 'head' */ + if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) { + /* rule: whichever one is closer to 3d-cursor */ + float curs[3]; + float vecA[3], vecB[3]; + float distA, distB; + + /* get cursor location */ + VECCOPY (curs, give_cursor()); + + Mat4Invert(G.obedit->imat, G.obedit->obmat); + Mat4MulVecfl(G.obedit->imat, curs); + + /* get distances */ + VecSubf(vecA, ebp->vec, curs); + VecSubf(vecB, ebp2->vec, curs); + distA= VecLength(vecA); + distB= VecLength(vecB); + + /* compare distances - closer one therefore acts as direction for bone to go */ + if (distA < distB) { + VECCOPY(head, ebp2->vec); + VECCOPY(tail, ebp->vec); + } + else { + VECCOPY(head, ebp->vec); + VECCOPY(tail, ebp2->vec); + } + } + else if (ebp->head_owner) { + VECCOPY(head, ebp->vec); + VECCOPY(tail, ebp2->vec); + } + else if (ebp2->head_owner) { + VECCOPY(head, ebp2->vec); + VECCOPY(tail, ebp->vec); + } + + /* add new bone */ + newbone= add_points_bone(head, tail); + } + else { + // FIXME.. figure out a method for multiple bones + error("Too many points selected"); + printf("Points selected: %d \n", count); + BLI_freelistN(&points); + return; + } + + /* free points */ + BLI_freelistN(&points); + + /* undo + updates */ + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + BIF_undo_push("Fill Bones"); +} + +/* this function merges between two bones, removes them and those in-between, + * and adjusts the parent relationships for those in-between + */ +static void bones_merge(EditBone *start, EditBone *end, ListBase *chains) +{ + EditBone *ebo, *ebone, *newbone; + LinkData *chain; + float head[3], tail[3]; + + /* check if same bone */ + if (start == end) { + printf("Error: same bone! \n"); + printf("\tstart = %s, end = %s \n", start->name, end->name); + } + + /* step 1: add a new bone + * - head = head/tail of start (default head) + * - tail = head/tail of end (default tail) + * - parent = parent of start + */ + if ((start->flag & BONE_TIPSEL) && !(start->flag & (BONE_SELECTED|BONE_ACTIVE))) { + VECCOPY(head, start->tail); + } + else { + VECCOPY(head, start->head); + } + if ((end->flag & BONE_ROOTSEL) && !(end->flag & (BONE_SELECTED|BONE_ACTIVE))) { + VECCOPY(tail, end->head); + } + else { + VECCOPY(tail, end->tail); + } + newbone= add_points_bone(head, tail); + newbone->parent = start->parent; + + /* step 2: parent children of in-between bones to newbone */ + for (chain= chains->first; chain; chain= chain->next) { + /* ick: we need to check if parent of each bone in chain is */ + for (ebo= chain->data; ebo; ebo= ebo->parent) { + short found= 0; + + /* try to find which bone from the list to be removed, is the parent */ + for (ebone= end; ebone; ebone= ebone->parent) { + if (ebo->parent == ebone) { + found= 1; + break; + } + } + + /* adjust this bone's parent to newbone then */ + if (found) { + ebo->parent= newbone; + break; + } + } + } + + /* step 3: delete all bones between and including start and end */ + for (ebo= end; ebo; ebo= ebone) { + ebone= (ebo == start) ? (NULL) : (ebo->parent); + BLI_freelinkN(&G.edbo, ebo); + } +} + +/* bone merging - has a menu! */ +void merge_armature(void) +{ + bArmature *arm= G.obedit->data; + short val= 0; + + /* process a menu to determine how to merge */ + // TODO: there's room for more modes of merging stuff... + val= pupmenu("Merge Selected Bones%t|Within Chains%x1"); + if (val <= 0) return; + + if (val == 1) { + /* go down chains, merging bones */ + ListBase chains = {NULL, NULL}; + LinkData *chain, *nchain; + EditBone *ebo; + + /* get chains (ends on chains) */ + chains_find_tips(&chains); + if (chains.first == NULL) return; + + /* each 'chain' is the last bone in the chain (with no children) */ + for (chain= chains.first; chain; chain= nchain) { + EditBone *bstart= NULL, *bend= NULL; + + /* temporarily remove chain from list of chains */ + nchain= chain->next; + BLI_remlink(&chains, chain); + + /* only consider bones that are visible and selected */ + for (ebo= chain->data; ebo; ebo= ebo->parent) { + /* check if visible + selected */ + if ( (arm->layer & ebo->layer) && !(ebo->flag & BONE_HIDDEN_A) && + ((ebo->flag & BONE_CONNECTED) || (ebo->parent==NULL)) && + (ebo->flag & (BONE_SELECTED|BONE_ACTIVE)) ) + { + /* set either end or start (end gets priority, unless it is already set) */ + if (bend == NULL) + bend= ebo; + else + bstart= ebo; + } + else { + /* chain is broken... merge any continous segments then clear */ + if (bstart && bend) + bones_merge(bstart, bend, &chains); + + bstart = NULL; + bend = NULL; + } + } + + /* merge from bstart to bend if something not merged */ + if (bstart && bend) + bones_merge(bstart, bend, &chains); + + /* put back link */ + BLI_insertlinkbefore(&chains, nchain, chain); + } + + BLI_freelistN(&chains); + } + + /* undo + updates */ + countall(); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + BIF_undo_push("Merge Bones"); +} + +/* ************** END Add/Remove stuff in editmode ************ */ /* *************** Tools in editmode *********** */ diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 134794b8d30..acf60accfc3 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -2823,54 +2823,87 @@ void convertmenu(void) DAG_scene_sort(G.scene); } - /* Change subdivision properties of mesh object ob, if - * level==-1 then toggle subsurf, else set to level. - * *set allows to toggle multiple selections - */ -static void object_flip_subdivison(Object *ob, int *set, int level, int mode, int ingroup) +/* Change subdivision or particle properties of mesh object ob, if level==-1 + * then toggle subsurf, else set to level set allows to toggle multiple + * selections */ + +static void object_has_subdivision_particles(Object *ob, int *havesubdiv, int *havepart, int depth) +{ + if(ob->type==OB_MESH) { + if(modifiers_findByType(ob, eModifierType_Subsurf)) + *havesubdiv= 1; + if(modifiers_findByType(ob, eModifierType_ParticleSystem)) + *havepart= 1; + } + + if(ob->dup_group && depth <= 4) { + GroupObject *go; + + for(go= ob->dup_group->gobject.first; go; go= go->next) + object_has_subdivision_particles(go->ob, havesubdiv, havepart, depth+1); + } +} + +static void object_flip_subdivison_particles(Object *ob, int *set, int level, int mode, int particles, int depth) { ModifierData *md; if(ob->type==OB_MESH) { - md = modifiers_findByType(ob, eModifierType_Subsurf); - - if (md) { - SubsurfModifierData *smd = (SubsurfModifierData*) md; + if(particles) { + for(md=ob->modifiers.first; md; md=md->next) { + if(md->type == eModifierType_ParticleSystem) { + ParticleSystemModifierData *psmd = (ParticleSystemModifierData*)md; - if (level == -1) { - if(*set == -1) - *set= smd->modifier.mode&(mode); - - if (*set) { - smd->modifier.mode &= ~(mode); - } else { - smd->modifier.mode |= (mode); + if(*set == -1) + *set= psmd->modifier.mode&(mode); + + if (*set) + psmd->modifier.mode &= ~(mode); + else + psmd->modifier.mode |= (mode); } - } else { - smd->levels = level; } - } - else if(!ingroup && *set != 0) { - SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf); + } + else { + md = modifiers_findByType(ob, eModifierType_Subsurf); - BLI_addtail(&ob->modifiers, smd); + if (md) { + SubsurfModifierData *smd = (SubsurfModifierData*) md; - if (level!=-1) { - smd->levels = level; + if (level == -1) { + if(*set == -1) + *set= smd->modifier.mode&(mode); + + if (*set) + smd->modifier.mode &= ~(mode); + else + smd->modifier.mode |= (mode); + } else { + smd->levels = level; + } + } + else if(depth == 0 && *set != 0) { + SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf); + + BLI_addtail(&ob->modifiers, smd); + + if (level!=-1) { + smd->levels = level; + } + + if(*set == -1) + *set= 1; } - - if(*set == -1) - *set= 1; } - ob->recalc |= OB_RECALC_DATA; + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); } - if(ob->dup_group) { + if(ob->dup_group && depth<=4) { GroupObject *go; for(go= ob->dup_group->gobject.first; go; go= go->next) - object_flip_subdivison(go->ob, set, level, mode, 1); + object_flip_subdivison_particles(go->ob, set, level, mode, particles, depth+1); } } @@ -2882,16 +2915,34 @@ void flip_subdivison(int level) { Base *base; int set= -1; - int mode; + int mode, pupmode, particles= 0, havesubdiv= 0, havepart= 0; if(G.qual & LR_ALTKEY) mode= eModifierMode_Realtime; else mode= eModifierMode_Render|eModifierMode_Realtime; + if(level == -1) { + for(base= G.scene->base.first; base; base= base->next) + if(((level==-1) && (TESTBASE(base))) || (TESTBASELIB(base))) + object_has_subdivision_particles(base->object, &havesubdiv, &havepart, 0); + } + else + havesubdiv= 1; + + if(havesubdiv && havepart) { + pupmode= pupmenu("Switch%t|Subsurf %x1|Particle Systems %x2"); + if(pupmode <= 0) + return; + else if(pupmode == 2) + particles= 1; + } + else if(havepart) + particles= 1; + for(base= G.scene->base.first; base; base= base->next) if(((level==-1) && (TESTBASE(base))) || (TESTBASELIB(base))) - object_flip_subdivison(base->object, &set, level, mode, 0); + object_flip_subdivison_particles(base->object, &set, level, mode, particles, 0); countall(); allqueue(REDRAWVIEW3D, 0); @@ -2900,7 +2951,10 @@ void flip_subdivison(int level) allqueue(REDRAWBUTSOBJECT, 0); DAG_scene_flush_update(G.scene, screen_view3d_layers()); - BIF_undo_push("Switch subsurf on/off"); + if(particles) + BIF_undo_push("Switch particles on/off"); + else + BIF_undo_push("Switch subsurf on/off"); } static void copymenu_properties(Object *ob) diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index 411a45d0a53..4a9bd8998c7 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -157,7 +157,7 @@ void PE_change_act(void *ob_v, void *act_v) if((psys=BLI_findlink(&ob->particlesystem,act))) { psys->flag |= PSYS_CURRENT; - if(psys->flag & PSYS_ENABLED) { + if(psys_check_enabled(ob, psys)) { if(G.f & G_PARTICLEEDIT && !psys->edit) PE_create_particle_edit(ob, psys); PE_recalc_world_cos(ob, psys); @@ -186,7 +186,7 @@ ParticleSystem *PE_get_current(Object *ob) psys->flag |= PSYS_CURRENT; } - if(psys && (psys->flag & PSYS_ENABLED) && ob == OBACT && (G.f & G_PARTICLEEDIT)) + if(psys && psys_check_enabled(ob, psys) && ob == OBACT && (G.f & G_PARTICLEEDIT)) if(psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) if(psys->edit == NULL) PE_create_particle_edit(ob, psys); @@ -1102,7 +1102,7 @@ void PE_set_particle_edit(void) if((G.f & G_PARTICLEEDIT)==0){ if(psys && psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) { - if(psys->flag & PSYS_ENABLED) { + if(psys_check_enabled(ob, psys)) { if(psys->edit==0) PE_create_particle_edit(ob, psys); PE_recalc_world_cos(ob, psys); @@ -2121,7 +2121,7 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe int i, k, n = 0, totpart = psys->totpart; short dmx = 0, dmy = 0; short mx = mval[0] - curarea->winx / 2, my = mval[1] - curarea->winy / 2; - float co1[3], co2[3], vec[4], min_d, imat[4][4], dx, dy; + float co1[3], co2[3], vec[4], min_d, imat[4][4]; float framestep, timestep = psys_get_timestep(psys->part); short size = pset->brush[PE_BRUSH_ADD].size; short size2 = size*size; @@ -2151,20 +2151,22 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe /* create intersection coordinates in view Z direction at mouse coordinates */ /* Thanks to who ever wrote the "Mouse Location 3D Space" tutorial in "Blender 3D: Blending Into Python/Cookbook". */ if(G.vd->persp){ - dx = G.vd->persmat[3][3] * (2.0f*(mx+dmx)/curarea->winx) - G.vd->persmat[3][0]; - dy = G.vd->persmat[3][3] * (2.0f*(my+dmy)/curarea->winy) - G.vd->persmat[3][1]; + vec[0]= (2.0f*(mx+dmx)/curarea->winx); + vec[1]= (2.0f*(my+dmy)/curarea->winy); + vec[2]= -1.0f; + vec[3]= 1.0f; - co2[0]=G.vd->persinv[0][0]*dx + G.vd->persinv[1][0]*dy; - co2[1]=G.vd->persinv[0][1]*dx + G.vd->persinv[1][1]*dy; - co2[2]=G.vd->persinv[0][2]*dx + G.vd->persinv[1][2]*dy; + Mat4MulVec4fl(G.vd->persinv, vec); + VecMulf(vec, 1.0f/vec[3]); - VECCOPY(co1,G.vd->viewinv[3]); + VECCOPY(co1, G.vd->viewinv[3]); + VECSUB(vec, vec, co1); + Normalize(vec); - VECSUB(vec,co2,co1) - - VECADDFAC(co2,co1,vec,1000.0f); + VECADDFAC(co1, G.vd->viewinv[3], vec, G.vd->near); + VECADDFAC(co2, G.vd->viewinv[3], vec, G.vd->far); } - else{ + else { vec[0] = 2.0f*(mx+dmx)/curarea->winx; vec[1] = 2.0f*(my+dmy)/curarea->winy; vec[2] = 0.0f; diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 1085b8598a1..3a86a55a0aa 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -3765,8 +3765,8 @@ static void do_view3d_edit_armaturemenu(void *arg, int event) case 17: /* move to layer */ pose_movetolayer(); break; - case 18: - uv_autocalc_tface(); + case 18: /* merge bones */ + merge_armature(); break; } @@ -3838,6 +3838,8 @@ static uiBlock *view3d_edit_armaturemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extrude Forked|Shift E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Merge|Alt M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Fill Between Joints|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -3850,11 +3852,7 @@ static uiBlock *view3d_edit_armaturemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Switch Armature Layers|Shift M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Bone To Layer|M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "UV Unwrap|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); - + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBlockBut(block, view3d_edit_armature_parentmenu, NULL, ICON_RIGHTARROW_THIN, "Parent", 0, yco-=20, 120, 19, ""); diff --git a/source/blender/src/language.c b/source/blender/src/language.c index c289d75f88b..5eb4bf3dc61 100644 --- a/source/blender/src/language.c +++ b/source/blender/src/language.c @@ -173,8 +173,8 @@ float BIF_GetStringWidth(BMF_Font* font, char *str, int translate) } void BIF_GetBoundingBox(struct BMF_Font* font, char* str, int translate, rctf *bbox){ - float dummy; #ifdef INTERNATIONAL + float dummy; if(G.ui_international == TRUE) if(translate && (U.transopts & USER_TR_BUTTONS)) FTF_GetBoundingBox(str, &bbox->xmin, &bbox->ymin, &dummy, &bbox->xmax, &bbox->ymax, &dummy, FTF_USE_GETTEXT | FTF_INPUT_UTF8); diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c index 292fcba055e..5907d3cd7c3 100644 --- a/source/blender/src/meshlaplacian.c +++ b/source/blender/src/meshlaplacian.c @@ -426,14 +426,14 @@ static void heat_ray_tree_create(LaplacianSystem *sys) DO_MINMAX(sys->heat.verts[a], min, max); tree= RE_ray_tree_create(64, me->totface, min, max, - heat_ray_coords_func, heat_ray_check_func); + heat_ray_coords_func, heat_ray_check_func, NULL, NULL); sys->heat.vface= MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces"); HeatSys= sys; for(a=0, mface=me->mface; atotface; a++, mface++) { - RE_ray_tree_add_face(tree, mface); + RE_ray_tree_add_face(tree, 0, mface); sys->heat.vface[mface->v1]= mface; sys->heat.vface[mface->v2]= mface; diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 8add5b3dce9..585ff320b71 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -1154,7 +1154,7 @@ void pose_relax() int do_loc = 0; int do_quat = 0; int flag = 0;*/ - int do_w, do_x, do_y, do_z; + int do_x, do_y, do_z; if (!ob) return; diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index 964c373771e..8afd1dafd6a 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -176,6 +176,7 @@ SculptData *sculpt_data(void) void sculpt_init_session(void); void init_editdata(EditData *e, short *, short *); +void sculpt_undo_push(const short); SculptSession *sculpt_session(void) { @@ -225,6 +226,7 @@ void sculptmode_init(Scene *sce) sd->flags= SCULPT_DRAW_BRUSH; sd->tablet_size=3; sd->tablet_strength=10; + sd->rake=0; } void sculptmode_free_session(Scene *); @@ -267,6 +269,11 @@ void sculptmode_free_all(Scene *sce) sculptmode_free_session(sce); + if(projverts) { + MEM_freeN(projverts); + projverts = NULL; + } + for(a=0; amtex[a]; if(mtex) { @@ -882,7 +889,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin /* Mark area around the brush as damaged. projverts are marked if they are inside the area and the damaged rectangle in 2D screen coordinates is added to damaged_rects. */ -void sculptmode_add_damaged_rect(EditData *e) +void sculpt_add_damaged_rect(EditData *e) { short p[2]; const float radius= brush_size(); @@ -910,6 +917,36 @@ void sculptmode_add_damaged_rect(EditData *e) } } +/* Clears the depth buffer in each modified area. */ +void sculpt_clear_damaged_areas(SculptSession *ss) +{ + RectNode *rn= NULL; + + for(rn = ss->damaged_rects.first; rn; rn = rn->next) { + rcti clp = rn->r; + rcti *win = &curarea->winrct; + + clp.xmin += win->xmin; + clp.xmax += win->xmin; + clp.ymin += win->ymin; + clp.ymax += win->ymin; + + if(clp.xmin < win->xmax && clp.xmax > win->xmin && + clp.ymin < win->ymax && clp.ymax > win->ymin) { + if(clp.xmin < win->xmin) clp.xmin = win->xmin; + if(clp.ymin < win->ymin) clp.ymin = win->ymin; + if(clp.xmax > win->xmax) clp.xmax = win->xmax; + if(clp.ymax > win->ymax) clp.ymax = win->ymax; + + glScissor(clp.xmin + 1, clp.ymin + 1, + clp.xmax - clp.xmin - 2, + clp.ymax - clp.ymin - 2); + } + + glClear(GL_DEPTH_BUFFER_BIT); + } +} + void do_brush_action(EditData e) { int i; @@ -922,7 +959,7 @@ void do_brush_action(EditData e) KeyBlock *keyblock= ob_get_keyblock(OBACT); SculptSession *ss = sculpt_session(); - sculptmode_add_damaged_rect(&e); + sculpt_add_damaged_rect(&e); /* Build a list of all vertices that are potentially within the brush's area of influence. Only do this once for the grab brush. */ @@ -1531,8 +1568,9 @@ void sculptmode_update_all_projverts(float *vertcosnos) Mesh *me= get_mesh(OBACT); unsigned i; - if(projverts) MEM_freeN(projverts); - projverts= MEM_mallocN(sizeof(ProjVert)*me->totvert,"ProjVerts"); + if(!projverts) + projverts = MEM_mallocN(sizeof(ProjVert)*me->totvert,"ProjVerts"); + for(i=0; itotvert; ++i) { project(vertcosnos ? &vertcosnos[i * 6] : me->mvert[i].co, projverts[i].co); projverts[i].inside= 0; @@ -1645,13 +1683,13 @@ void sculpt(void) SculptData *sd= sculpt_data(); SculptSession *ss= sculpt_session(); Object *ob= OBACT; - short mouse[2], mvalo[2], firsttime=1, mousebut; + /* lastSigMouse is for the rake, to store the last place the mouse movement was significant */ + short mouse[2], mvalo[2], lastSigMouse[2],firsttime=1, mousebut; short modifier_calculations= 0; EditData e; - RectNode *rn= NULL; short spacing= 32000; int scissor_box[4]; - + float offsetRot; if(!(G.f & G_SCULPTMODE) || G.obedit || !ob || ob->id.lib || !get_mesh(ob) || (get_mesh(ob)->totface == 0)) return; if(!(ob->lay & G.vd->lay)) @@ -1676,9 +1714,12 @@ void sculpt(void) ss->vertexcosnos = NULL; /* Check that vertex users are up-to-date */ - if(ob != active_ob || ss->vertex_users_size != get_mesh(ob)->totvert) { + if(ob != active_ob || !ss->vertex_users || ss->vertex_users_size != get_mesh(ob)->totvert) { sculptmode_free_vertexusers(ss); calc_vertex_users(); + if(projverts) + MEM_freeN(projverts); + projverts = NULL; active_ob= ob; } @@ -1689,9 +1730,6 @@ void sculpt(void) getmouseco_areawin(mvalo); - /* Make sure sculptdata has been init'd properly */ - if(!ss->vertex_users) calc_vertex_users(); - /* Init texture FIXME: Shouldn't be doing this every time! */ if(sd->texrept!=SCULPTREPT_3D) @@ -1700,7 +1738,8 @@ void sculpt(void) getmouseco_areawin(mouse); mvalo[0]= mouse[0]; mvalo[1]= mouse[1]; - + lastSigMouse[0]=mouse[0]; + lastSigMouse[1]=mouse[1]; mousebut = L_MOUSE; /* If modifier_calculations is true, then extra time must be spent @@ -1729,9 +1768,19 @@ void sculpt(void) /* Get original scissor box */ glGetIntegerv(GL_SCISSOR_BOX, scissor_box); - + + /* For raking, get the original angle*/ + offsetRot=tex_angle(); + while (get_mbut() & mousebut) { getmouseco_areawin(mouse); + /* If rake, and the mouse has moved over 10 pixels (euclidean) (prevents jitter) then get the new angle */ + if (sd->rake && (pow(lastSigMouse[0]-mouse[0],2)+pow(lastSigMouse[1]-mouse[1],2))>100){ + /*Nasty looking, but just orig + new angle really*/ + set_tex_angle(offsetRot+180.+to_deg(atan2((float)(mouse[1]-lastSigMouse[1]),(float)(mouse[0]-lastSigMouse[0])))); + lastSigMouse[0]=mouse[0]; + lastSigMouse[1]=mouse[1]; + } if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] || sculptmode_brush()->airbrush) { firsttime= 0; @@ -1771,28 +1820,7 @@ void sculpt(void) /* Draw the stored image to the screen */ glAccum(GL_RETURN, 1); - /* Clear each of the area(s) modified by the brush */ - for(rn=ss->damaged_rects.first; rn; rn= rn->next) { - rcti clp= rn->r; - rcti *win= &curarea->winrct; - - clp.xmin+= win->xmin; - clp.xmax+= win->xmin; - clp.ymin+= win->ymin; - clp.ymax+= win->ymin; - - if(clp.xminxmax && clp.xmax>win->xmin && - clp.yminymax && clp.ymax>win->ymin) { - if(clp.xminxmin) clp.xmin= win->xmin; - if(clp.yminymin) clp.ymin= win->ymin; - if(clp.xmax>win->xmax) clp.xmax= win->xmax; - if(clp.ymax>win->ymax) clp.ymax= win->ymax; - glScissor(clp.xmin+1, clp.ymin+1, - clp.xmax-clp.xmin-2,clp.ymax-clp.ymin-2); - } - - glClear(GL_DEPTH_BUFFER_BIT); - } + sculpt_clear_damaged_areas(ss); /* Draw all the polygons that are inside the modified area(s) */ glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]); @@ -1828,14 +1856,15 @@ void sculpt(void) else BIF_wait_for_statechange(); } + /* Set the rotation of the brush back to what it was before any rake */ + set_tex_angle(offsetRot); + if(sd->flags & SCULPT_INPUT_SMOOTH) { sculpt_stroke_apply_all(&e); calc_damaged_verts(&ss->damaged_verts,e.grabdata); BLI_freelistN(&ss->damaged_rects); } - if(projverts) MEM_freeN(projverts); - projverts= NULL; if(e.layer_disps) MEM_freeN(e.layer_disps); if(e.layer_store) MEM_freeN(e.layer_store); /* Free GrabData */ @@ -1847,7 +1876,16 @@ void sculpt(void) } sculpt_stroke_free(); - switch(G.scene->sculptdata.brush_type) { + sculpt_undo_push(G.scene->sculptdata.brush_type); + + if(G.vd->depths) G.vd->depths->damaged= 1; + + allqueue(REDRAWVIEW3D, 0); +} + +void sculpt_undo_push(const short brush_type) +{ + switch(brush_type) { case DRAW_BRUSH: BIF_undo_push("Draw Brush"); break; case SMOOTH_BRUSH: @@ -1865,10 +1903,6 @@ void sculpt(void) default: BIF_undo_push("Sculpting"); break; } - - if(G.vd->depths) G.vd->depths->damaged= 1; - - allqueue(REDRAWVIEW3D, 0); } void set_sculptmode(void) diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 84c77521841..2e560b05228 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1893,7 +1893,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } - else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) addsegment_nurb(); + else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) { + addsegment_nurb(); + } + else if(G.obedit->type == OB_ARMATURE) { + fill_bones_armature(); + } } else if(G.qual==LR_CTRLKEY) sort_faces(); @@ -2156,10 +2161,13 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) pose_movetolayer(); } else if (G.qual==LR_ALTKEY) { - if(G.obedit->type==OB_MESH) { + if (G.obedit->type == OB_MESH) { mergemenu(); DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); } + else if (G.obedit->type == OB_ARMATURE) { + merge_armature(); + } } else if ((G.qual==0) || (G.qual==LR_CTRLKEY)) { mirrormenu(); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 8a38c66738f..632af9e269b 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -815,7 +815,10 @@ static void transformEvent(unsigned short event, short val) { break; case PAGEUPKEY: case WHEELDOWNMOUSE: - if(Trans.flag & T_PROP_EDIT) { + if (Trans.flag & T_AUTOIK) { + transform_autoik_update(&Trans, 1); + } + else if(Trans.flag & T_PROP_EDIT) { Trans.propsize*= 1.1f; calculatePropRatio(&Trans); } @@ -831,7 +834,10 @@ static void transformEvent(unsigned short event, short val) { break; case PAGEDOWNKEY: case WHEELUPMOUSE: - if(Trans.flag & T_PROP_EDIT) { + if (Trans.flag & T_AUTOIK) { + transform_autoik_update(&Trans, -1); + } + else if (Trans.flag & T_PROP_EDIT) { Trans.propsize*= 0.90909090f; calculatePropRatio(&Trans); } @@ -2509,6 +2515,7 @@ void initTranslation(TransInfo *t) static void headerTranslation(TransInfo *t, float vec[3], char *str) { char tvec[60]; char distvec[20]; + char autoik[20]; float dvec[3]; float dist; @@ -2529,24 +2536,35 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) { sprintf(distvec, "%.4e", dist); else sprintf(distvec, "%.4f", dist); + + if(t->flag & T_AUTOIK) { + short chainlen= G.scene->toolsettings->autoik_chainlen; + + if(chainlen) + sprintf(autoik, "AutoIK-Len: %d", chainlen); + else + strcpy(autoik, ""); + } + else + strcpy(autoik, ""); if (t->con.mode & CON_APPLY) { switch(t->num.idx_max) { case 0: - sprintf(str, "D: %s (%s)%s %s", &tvec[0], distvec, t->con.text, t->proptext); + sprintf(str, "D: %s (%s)%s %s %s", &tvec[0], distvec, t->con.text, t->proptext, &autoik[0]); break; case 1: - sprintf(str, "D: %s D: %s (%s)%s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext); + sprintf(str, "D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext, &autoik[0]); break; case 2: - sprintf(str, "D: %s D: %s D: %s (%s)%s %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext); + sprintf(str, "D: %s D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]); } } else { if(t->flag & T_2D_EDIT) sprintf(str, "Dx: %s Dy: %s (%s)%s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext); else - sprintf(str, "Dx: %s Dy: %s Dz: %s (%s)%s %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext); + sprintf(str, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]); } } @@ -2592,7 +2610,7 @@ static void applyTranslation(TransInfo *t, float vec[3]) { int Translation(TransInfo *t, short mval[2]) { float tvec[3]; - char str[200]; + char str[250]; if(t->flag & T_SHIFT_MOD) { float dvec[3]; @@ -4094,3 +4112,4 @@ void BIF_TransformSetUndo(char *str) } + diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 12acf538431..bc0377696e4 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -696,6 +696,61 @@ static void set_pose_transflags(TransInfo *t, Object *ob) t->mode= TFM_ROTATION; } + +/* -------- Auto-IK ---------- */ + +/* adjust pose-channel's auto-ik chainlen */ +static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen) +{ + bConstraint *con; + + /* don't bother to search if no valid constraints */ + if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0) + return; + + /* check if pchan has ik-constraint */ + for (con= pchan->constraints.first; con; con= con->next) { + if (con->type == CONSTRAINT_TYPE_KINEMATIC) { + bKinematicConstraint *data= con->data; + + /* only accept if a temporary one (for auto-ik) */ + if (data->flag & CONSTRAINT_IK_TEMP) { + /* chainlen is new chainlen, but is limited by maximum chainlen */ + if ((chainlen==0) || (chainlen > data->max_rootbone)) + data->rootbone= data->max_rootbone; + else + data->rootbone= chainlen; + } + } + } +} + +/* change the chain-length of auto-ik */ +void transform_autoik_update (TransInfo *t, short mode) +{ + short *chainlen= &G.scene->toolsettings->autoik_chainlen; + bPoseChannel *pchan; + + /* mode determines what change to apply to chainlen */ + if (mode == 1) { + /* mode=1 is from WHEELMOUSEDOWN... increases len */ + (*chainlen)++; + } + else if (mode == -1) { + /* mode==-1 is from WHEELMOUSEUP... decreases len */ + if (*chainlen > 0) (*chainlen)--; + } + + /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */ + if (ELEM(NULL, t->poseobj, t->poseobj->pose)) + return; + + /* apply to all pose-channels */ + for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) { + pchan_autoik_adjust(pchan, *chainlen); + } +} + /* frees temporal IKs */ static void pose_grab_with_ik_clear(Object *ob) { @@ -723,19 +778,19 @@ static void pose_grab_with_ik_clear(Object *ob) } } -/* adds the IK to pchan */ -static void pose_grab_with_ik_add(bPoseChannel *pchan) +/* adds the IK to pchan - returns if added */ +static short pose_grab_with_ik_add(bPoseChannel *pchan) { bKinematicConstraint *data; bConstraint *con; - if (pchan == NULL) { // Sanity check - return; - } + /* Sanity check */ + if (pchan == NULL) + return 0; /* rule: not if there's already an IK on this channel */ for (con= pchan->constraints.first; con; con= con->next) - if(con->type==CONSTRAINT_TYPE_KINEMATIC) + if (con->type==CONSTRAINT_TYPE_KINEMATIC) break; if (con) { @@ -743,7 +798,7 @@ static void pose_grab_with_ik_add(bPoseChannel *pchan) data= has_targetless_ik(pchan); if (data) data->flag |= CONSTRAINT_IK_AUTO; - return; + return 0; } con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC); @@ -765,73 +820,79 @@ static void pose_grab_with_ik_add(bPoseChannel *pchan) data->rootbone++; pchan= pchan->parent; } + + /* make a copy of maximum chain-length */ + data->max_rootbone= data->rootbone; + + return 1; } /* bone is a canditate to get IK, but we don't do it if it has children connected */ -static void pose_grab_with_ik_children(bPose *pose, Bone *bone) +static short pose_grab_with_ik_children(bPose *pose, Bone *bone) { Bone *bonec; - int wentdeeper= 0; + short wentdeeper=0, added=0; /* go deeper if children & children are connected */ - for(bonec= bone->childbase.first; bonec; bonec= bonec->next) { - if(bonec->flag & BONE_CONNECTED) { + for (bonec= bone->childbase.first; bonec; bonec= bonec->next) { + if (bonec->flag & BONE_CONNECTED) { wentdeeper= 1; - pose_grab_with_ik_children(pose, bonec); + added+= pose_grab_with_ik_children(pose, bonec); } } - if(wentdeeper==0) { + if (wentdeeper==0) { bPoseChannel *pchan= get_pose_channel(pose, bone->name); - if(pchan) - pose_grab_with_ik_add(pchan); + if (pchan) + added+= pose_grab_with_ik_add(pchan); } + + return added; } /* main call which adds temporal IK chains */ -static void pose_grab_with_ik(Object *ob) +static short pose_grab_with_ik(Object *ob) { bArmature *arm; bPoseChannel *pchan, *pchansel= NULL; Bone *bonec; - if(ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0) - return; + if (ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0) + return 0; arm = ob->data; /* rule: only one Bone */ - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(pchan->bone->layer & arm->layer) { - if(pchan->bone->flag & BONE_SELECTED) { - if(pchansel) + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->bone->layer & arm->layer) { + if (pchan->bone->flag & BONE_SELECTED) { + if (pchansel) break; pchansel= pchan; } } } - if(pchan || pchansel==NULL) return; + if (pchan || pchansel==NULL) return 0; /* rule: no IK for solitary (unconnected) bone */ - for(bonec=pchansel->bone->childbase.first; bonec; bonec=bonec->next) { - if(bonec->flag & BONE_CONNECTED) { + for (bonec=pchansel->bone->childbase.first; bonec; bonec=bonec->next) { + if (bonec->flag & BONE_CONNECTED) { break; } } - if ((pchansel->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL)) return; + if ((pchansel->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL)) return 0; /* rule: if selected Bone is not a root bone, it gets a temporal IK */ - if(pchansel->parent) { + if (pchansel->parent) { /* only adds if there's no IK yet */ - pose_grab_with_ik_add(pchansel); + return pose_grab_with_ik_add(pchansel); } else { /* rule: go over the children and add IK to the tips */ - pose_grab_with_ik_children(ob->pose, pchansel->bone); + return pose_grab_with_ik_children(ob->pose, pchansel->bone); } } - /* only called with pose mode active object now */ static void createTransPose(TransInfo *t, Object *ob) { @@ -839,6 +900,7 @@ static void createTransPose(TransInfo *t, Object *ob) bPoseChannel *pchan; TransData *td; TransDataExtension *tdx; + short ik_on= 0; int i; t->total= 0; @@ -856,8 +918,10 @@ static void createTransPose(TransInfo *t, Object *ob) if (!(ob->lay & G.vd->lay)) return; /* do we need to add temporal IK chains? */ - if((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) - pose_grab_with_ik(ob); + if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) { + ik_on= pose_grab_with_ik(ob); + if (ik_on) t->flag |= T_AUTOIK; + } /* set flags and count total (warning, can change transform to rotate) */ set_pose_transflags(t, ob); @@ -891,6 +955,8 @@ static void createTransPose(TransInfo *t, Object *ob) if(td != (t->data+t->total)) printf("Bone selection count error\n"); + /* initialise initial auto=ik chainlen's? */ + if (ik_on) transform_autoik_update(t, 0); } /* ********************* armature ************** */ @@ -1500,6 +1566,7 @@ static void createTransParticleVerts(TransInfo *t) if(k==0 && pset->flag & PE_LOCK_FIRST) td->protectflag |= OB_LOCK_LOC; + td->ob = ob; td->ext = tx; td->tdi = NULL; if(t->mode == TFM_BAKE_TIME) { @@ -3544,3 +3611,4 @@ void createTransData(TransInfo *t) } + diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index d62d49c2de8..355c150657e 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -471,12 +471,13 @@ void TargetSnapMedian(TransInfo *t) if ((t->tsnap.status & TARGET_INIT) == 0) { TransData *td = NULL; + int i; t->tsnap.snapTarget[0] = 0; t->tsnap.snapTarget[1] = 0; t->tsnap.snapTarget[2] = 0; - for (td = t->data; td != NULL && td->flag & TD_SELECTED ; td++) + for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) { VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->iloc); } @@ -514,7 +515,8 @@ void TargetSnapClosest(TransInfo *t) // More than one selected item else { - for (td = t->data; td != NULL && td->flag & TD_SELECTED ; td++) + int i; + for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) { float loc[3]; float dist; diff --git a/source/blender/yafray/YafRay_Api.h b/source/blender/yafray/YafRay_Api.h index 8c47a79837f..a05e9752a1a 100644 --- a/source/blender/yafray/YafRay_Api.h +++ b/source/blender/yafray/YafRay_Api.h @@ -8,8 +8,6 @@ extern "C" { void YAF_switchPlugin(); void YAF_switchFile(); int YAF_exportScene(Render* re); - void YAF_addDupliMtx(Object* obj); - int YAF_objectKnownData(Object* obj); #ifdef __cplusplus } #endif diff --git a/source/blender/yafray/intern/api.cpp b/source/blender/yafray/intern/api.cpp index f59c5e1f73e..0cb1c6fafdf 100644 --- a/source/blender/yafray/intern/api.cpp +++ b/source/blender/yafray/intern/api.cpp @@ -11,6 +11,4 @@ extern "C" void YAF_switchPlugin() { YAFBLEND = &byplugin; } void YAF_switchFile() { YAFBLEND = &byfile; } int YAF_exportScene(Render* re) { return (int)YAFBLEND->exportScene(re); } - void YAF_addDupliMtx(Object* obj) { YAFBLEND->addDupliMtx(obj); } - int YAF_objectKnownData(Object* obj) { return (int)YAFBLEND->objectKnownData(obj); } } diff --git a/source/blender/yafray/intern/export_File.cpp b/source/blender/yafray/intern/export_File.cpp index c8c0b3c6bb1..48e4f267177 100644 --- a/source/blender/yafray/intern/export_File.cpp +++ b/source/blender/yafray/intern/export_File.cpp @@ -1230,7 +1230,8 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector &VLR_li string matname(face0mat->id.name); // use name in imgtex_shader list if 'TexFace' enabled for this material if (face0mat->mode & MA_FACETEXTURE) { - MTFace* tface = RE_vlakren_get_tface(re, face0, 0, NULL, 0); + ObjectRen *obr = face0->obr; + MTFace* tface = RE_vlakren_get_tface(obr, face0, obr->actmtface, NULL, 0); if (tface) { Image* fimg = (Image*)tface->tpage; if (fimg) matname = imgtex_shader[string(face0mat->id.name) + string(fimg->id.name)]; @@ -1407,12 +1408,13 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector &VLR_li fci2!=VLR_list.end();++fci2) { VlakRen* vlr = *fci2; + ObjectRen *obr = vlr->obr; Material* fmat = vlr->mat; bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0); string fmatname(fmat->id.name); // use name in imgtex_shader list if 'TexFace' enabled for this face material if (fmat->mode & MA_FACETEXTURE) { - MTFace* tface = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); + MTFace* tface = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); if (tface) { Image* fimg = (Image*)tface->tpage; if (fimg) fmatname = imgtex_shader[fmatname + string(fimg->id.name)]; @@ -1437,14 +1439,14 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector &VLR_li } else if (vlr->flag & R_FACE_SPLIT) { ui2++; ui3++; } - MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down) + MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // possible uvcoords (v upside down) if (uvc) { ostr << " u_a=\"" << uvc->uv[ui1][0] << "\" v_a=\"" << 1-uvc->uv[ui1][1] << "\"" << " u_b=\"" << uvc->uv[ui2][0] << "\" v_b=\"" << 1-uvc->uv[ui2][1] << "\"" << " u_c=\"" << uvc->uv[ui3][0] << "\" v_c=\"" << 1-uvc->uv[ui3][1] << "\""; } - MCol *mcol= RE_vlakren_get_mcol(re, vlr, 0, NULL, 0); + MCol *mcol= RE_vlakren_get_mcol(obr, vlr, obr->actmcol, NULL, 0); // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols if ((EXPORT_VCOL) && mcol) { diff --git a/source/blender/yafray/intern/export_Plugin.cpp b/source/blender/yafray/intern/export_Plugin.cpp index 6a6137fefe9..cccd6b1ab8d 100644 --- a/source/blender/yafray/intern/export_Plugin.cpp +++ b/source/blender/yafray/intern/export_Plugin.cpp @@ -1109,7 +1109,8 @@ void yafrayPluginRender_t::genUVcoords(vector &uvcoords, VlakRen void yafrayPluginRender_t::genVcol(vector &vcol, VlakRen *vlr, bool comple) { - MCol *mcol= RE_vlakren_get_mcol(re, vlr, 0, NULL, 0); + ObjectRen *obr= vlr->obr; + MCol *mcol= RE_vlakren_get_mcol(obr, vlr, obr->actmcol, NULL, 0); if (mcol) { @@ -1145,12 +1146,13 @@ void yafrayPluginRender_t::genFace(vector &faces,vector &shaders,ve map &vert_idx,VlakRen *vlr, int has_orco,bool has_uv) { + ObjectRen *obr= vlr->obr; Material* fmat = vlr->mat; bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0); string fmatname(fmat->id.name); // use name in imgtex_shader list if 'TexFace' enabled for this face material if (fmat->mode & MA_FACETEXTURE) { - MTFace* tface = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); + MTFace* tface = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); if (tface) { Image* fimg = (Image*)tface->tpage; if (fimg) fmatname = imgtex_shader[fmatname + string(fimg->id.name)]; @@ -1171,7 +1173,7 @@ void yafrayPluginRender_t::genFace(vector &faces,vector &shaders,ve faceshader.push_back(shaders.size()-1); } - MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down) + MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // possible uvcoords (v upside down) int idx1, idx2, idx3; idx1 = vert_idx.find(vlr->v1)->second; @@ -1192,11 +1194,12 @@ void yafrayPluginRender_t::genCompleFace(vector &faces,/*vector &sh map &vert_idx,VlakRen *vlr, int has_orco,bool has_uv) { + ObjectRen *obr= vlr->obr; Material* fmat = vlr->mat; bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0); faceshader.push_back(faceshader.back()); - MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down) + MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // possible uvcoords (v upside down) int idx1, idx2, idx3; idx1 = vert_idx.find(vlr->v3)->second; idx2 = vert_idx.find(vlr->v4)->second; @@ -1338,8 +1341,9 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector &VLR_ fci!=VLR_list.end();++fci) { VlakRen* vlr = *fci; + ObjectRen *obr = vlr->obr; genVertices(verts, vidx, vert_idx, vlr, has_orco, obj); - if(RE_vlakren_get_tface(re, vlr, 0, NULL, 0)) has_uv=true; + if(RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0)) has_uv=true; } // all faces using the index list created above vector faces; @@ -1382,7 +1386,6 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector &VLR_ // write all objects void yafrayPluginRender_t::writeAllObjects() { - // first all objects except dupliverts (and main instance object for dups) for (map >::const_iterator obi=all_objects.begin(); obi!=all_objects.end(); ++obi) @@ -1437,7 +1440,6 @@ void yafrayPluginRender_t::writeAllObjects() } } - } void yafrayPluginRender_t::writeAreaLamp(LampRen* lamp, int num, float iview[4][4]) diff --git a/source/blender/yafray/intern/yafray_Render.cpp b/source/blender/yafray/intern/yafray_Render.cpp index 1106e197335..fa7c61072f4 100644 --- a/source/blender/yafray/intern/yafray_Render.cpp +++ b/source/blender/yafray/intern/yafray_Render.cpp @@ -73,7 +73,20 @@ bool yafrayRender_t::exportScene(Render* re) // as well as associating them again with the original Object. bool yafrayRender_t::getAllMatTexObs() { + ObjectInstanceRen *obi; + ObjectRen *obr; VlakRen* vlr; + float mat[4][4]; + + // convert blender object instances to dupli matrices + for(obi=(ObjectInstanceRen*)re->instancetable.first; obi; obi=obi->next) { + if(obi->flag & R_DUPLI_TRANSFORMED) { + // compute object matrix with dupli transform, need to transform + // obi->mat out of view space for it + MTC_Mat4MulSerie(mat, re->viewinv, obi->mat, re->viewmat, obi->obr->ob->obmat, 0, 0, 0, 0); + addDupliMtx(obi->obr->ob, mat); + } + } // Blender does not include object which have total 0 alpha materials, // however, the objects might have been included in the dupliMtx list, @@ -84,69 +97,72 @@ bool yafrayRender_t::getAllMatTexObs() // but on the other hand that could also hide the real problem of course... map renderobs; - for (int i=0; i < re->totvlak; i++) { + for(obr=(ObjectRen*)re->objecttable.first; obr; obr=obr->next) { + for (int i=0; i < obr->totvlak; i++) { - if ((i & 255)==0) vlr=re->vlaknodes[i>>8].vlak; else vlr++; + if ((i & 255)==0) vlr=obr->vlaknodes[i>>8].vlak; else vlr++; - // ---- The materials & textures - // in this case, probably every face has a material assigned, which can be the default material, - // so checking that this is !0 is probably not necessary, but just in case... - Material* matr = vlr->mat; - if (matr) { - // The default assigned material seems to be nameless, no MA id, an empty string. - // Since this name is needed in yafray, make it 'blender_default' - if (strlen(matr->id.name)==0) - used_materials["blender_default"] = matr; - else - used_materials[matr->id.name] = matr; - // textures, all active channels - for (int m=0;mseptex & (1<mtex[m]; - // if no mtex, ignore - if (mx==NULL) continue; - // if no tex, ignore - Tex* tx = mx->tex; - if (tx==NULL) continue; - short txtp = tx->type; - // if texture type not available in yafray, ignore - if ((txtp==0) || - (txtp==TEX_MAGIC) || - (txtp==TEX_PLUGIN) || - (txtp==TEX_ENVMAP)) continue; - // if texture is stucci, only export if 'nor' enabled - if ((txtp==TEX_STUCCI) && !((mx->mapto & MAP_NORM) || (mx->maptoneg & MAP_NORM))) continue; - // In the case of an image texture, check that there is an actual image, otherwise ignore. - // Stupid error was here (...if (txtp & TEX_IMAGE)...), - // which happened to work sofar, but not anymore with the extended texture support.. - if ((txtp==TEX_IMAGE) && (!tx->ima)) continue; - used_textures[tx->id.name] = mx; - } - } - - // Make list of faces per object, ignore <3 vert faces, duplicate vertex sorting done later. - // ignore null object pointers. - // Also make list of facetexture images (material 'TexFace'). - if (vlr->ob) { - int nv = 0; // number of vertices - MTFace *tface; - - if (vlr->v4) nv=4; else if (vlr->v3) nv=3; - if (nv) { - renderobs[vlr->ob->id.name] = vlr->ob; - all_objects[vlr->ob].push_back(vlr); - - tface= RE_vlakren_get_tface(re, vlr, 0, NULL, 0); - if (tface && tface->tpage) { - Material* fmat = vlr->mat; - - // only save if TexFace enabled - if(fmat && (fmat->mode & MA_FACETEXTURE)) - imagetex[tface->tpage].insert(fmat); + // ---- The materials & textures + // in this case, probably every face has a material assigned, which can be the default material, + // so checking that this is !0 is probably not necessary, but just in case... + Material* matr = vlr->mat; + if (matr) { + // The default assigned material seems to be nameless, no MA id, an empty string. + // Since this name is needed in yafray, make it 'blender_default' + if (strlen(matr->id.name)==0) + used_materials["blender_default"] = matr; + else + used_materials[matr->id.name] = matr; + // textures, all active channels + for (int m=0;mseptex & (1<mtex[m]; + // if no mtex, ignore + if (mx==NULL) continue; + // if no tex, ignore + Tex* tx = mx->tex; + if (tx==NULL) continue; + short txtp = tx->type; + // if texture type not available in yafray, ignore + if ((txtp==0) || + (txtp==TEX_MAGIC) || + (txtp==TEX_PLUGIN) || + (txtp==TEX_ENVMAP)) continue; + // if texture is stucci, only export if 'nor' enabled + if ((txtp==TEX_STUCCI) && !((mx->mapto & MAP_NORM) || (mx->maptoneg & MAP_NORM))) continue; + // In the case of an image texture, check that there is an actual image, otherwise ignore. + // Stupid error was here (...if (txtp & TEX_IMAGE)...), + // which happened to work sofar, but not anymore with the extended texture support.. + if ((txtp==TEX_IMAGE) && (!tx->ima)) continue; + used_textures[tx->id.name] = mx; } } - } + // Make list of faces per object, ignore <3 vert faces, duplicate vertex sorting done later. + // ignore null object pointers. + // Also make list of facetexture images (material 'TexFace'). + if (vlr->obr->ob) { + int nv = 0; // number of vertices + MTFace *tface; + + if (vlr->v4) nv=4; else if (vlr->v3) nv=3; + if (nv) { + ObjectRen *obr= vlr->obr; + renderobs[obr->ob->id.name] = obr->ob; + all_objects[obr->ob].push_back(vlr); + + tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); + if (tface && tface->tpage) { + Material* fmat = vlr->mat; + + // only save if TexFace enabled + if(fmat && (fmat->mode & MA_FACETEXTURE)) + imagetex[tface->tpage].insert(fmat); + } + } + } + + } } // now remove any objects from dupliMtx_list which are not in the renderlist @@ -187,16 +203,16 @@ bool yafrayRender_t::getAllMatTexObs() return true; } - - -void yafrayRender_t::addDupliMtx(Object* obj) +void yafrayRender_t::addDupliMtx(Object* obj, float mat[][4]) { for (int i=0;i<4;i++) for (int j=0;j<4;j++) - dupliMtx_list[obj->id.name].push_back(obj->obmat[i][j]); + dupliMtx_list[obj->id.name].push_back(mat[i][j]); } +#if 0 + bool yafrayRender_t::objectKnownData(Object* obj) { // if object data already known, no need to include in renderlist, otherwise save object datapointer @@ -217,3 +233,5 @@ bool yafrayRender_t::objectKnownData(Object* obj) objectData[obj->data] = obj; return false; } +#endif + diff --git a/source/blender/yafray/intern/yafray_Render.h b/source/blender/yafray/intern/yafray_Render.h index 4002f514a6e..0debb0009fa 100644 --- a/source/blender/yafray/intern/yafray_Render.h +++ b/source/blender/yafray/intern/yafray_Render.h @@ -62,7 +62,7 @@ class yafrayRender_t // mtds bool exportScene(Render* re); - void addDupliMtx(Object* obj); + void addDupliMtx(Object* obj, float mat[][4]); bool objectKnownData(Object* obj); protected: diff --git a/source/nan_compile.mk b/source/nan_compile.mk index 192528aa5a6..d5bf04c4b33 100644 --- a/source/nan_compile.mk +++ b/source/nan_compile.mk @@ -184,13 +184,14 @@ ifeq ($(OS),solaris) REL_CFLAGS += -O1 REL_CCFLAGS += -O1 NAN_DEPEND = true - ifeq ($(CPU),sparc) + #ifeq ($(CPU),sparc) + ifeq ($(CPU),$(findstring $(CPU), "sparc")) OPENGL_HEADERS = /usr/openwin/share/include CPPFLAGS += -DSUN_OGL_NO_VERTEX_MACROS JAVA_HEADERS = /usr/java/include JAVA_SYSTEM_HEADERS = /usr/java/include/solaris else - OPENGL_HEADERS = /usr/X11/include + OPENGL_HEADERS = $(LCGDIR)/mesa/include endif AR = ar ARFLAGS = ruv diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 39479dfccf1..5fda29b8002 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -142,7 +142,9 @@ endif endif else ifeq ($(OS), solaris) - export NAN_OPENEXR ?= /usr/local + # this only exists at the moment for i386-64 CPU Types at the moment + export NAN_OPENEXR ?= $(LCGDIR)/openexr + export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a $(NAN_OPENEXR)/lib/libIlmThread.a -lrt else export NAN_OPENEXR ?= /usr/local @@ -469,8 +471,8 @@ endif export ID = $(shell /usr/ucb/whoami) export HOST = $(shell hostname) - export NAN_PYTHON ?= /usr/local - export NAN_PYTHON_VERSION ?= 2.3 + export NAN_PYTHON ?= $(LCGDIR)/python + export NAN_PYTHON_VERSION ?= 2.5 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a export NAN_OPENAL ?= $(LCGDIR)/openal @@ -480,7 +482,7 @@ endif export NAN_TIFF ?= /usr export NAN_ODE ?= $(LCGDIR)/ode export NAN_TERRAPLAY ?= - export NAN_MESA ?= /usr/src/Mesa-3.1 + export NAN_MESA ?= $(LCGDIR)/mesa export NAN_ZLIB ?= $(LCGDIR)/zlib export NAN_NSPR ?= $(LCGDIR)/nspr export NAN_FREETYPE ?= $(LCGDIR)/freetype diff --git a/source/nan_link.mk b/source/nan_link.mk index 35a0a9d0070..00d233962a9 100644 --- a/source/nan_link.mk +++ b/source/nan_link.mk @@ -117,10 +117,10 @@ ifeq ($(OS),openbsd) endif ifeq ($(OS),solaris) - ifeq ($(CPU), i386) - LLIBS = -L/usr/X11/lib - endif - LLIBS += -lGLU -lGL -lXmu -lXext -lXi -lX11 -lc -lm -ldl -lsocket -lnsl + ifeq (x86_64, $(findstring x86_64, $(CPU))) + LLIBS = -lrt + endif + LLIBS += -L$(NAN_MESA)/lib -lGLU -lGL -lXmu -lXext -lXi -lX11 -lc -lm -ldl -lsocket -lnsl DYNLDFLAGS = -shared $(LDFLAGS) endif diff --git a/tools/btools.py b/tools/btools.py index 488b434c58a..9075d7c7b12 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -46,7 +46,7 @@ def validate_arguments(args, bc): 'WITH_BF_QUICKTIME', 'BF_QUICKTIME', 'BF_QUICKTIME_INC', 'BF_QUICKTIME_LIB', 'BF_QUICKTIME_LIBPATH', 'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC', 'BF_OPENGL_LINKFLAGS', 'WITH_BF_FTGL', 'BF_FTGL', 'BF_FTGL_INC', 'BF_FTGL_LIB', - 'WITH_BF_FFMPEG', + 'WITH_BF_BPYAPI_V24X', 'WITH_BF_PLAYER', 'CFLAGS', 'CCFLAGS', 'CPPFLAGS', 'REL_CFLAGS', 'REL_CCFLAGS', @@ -174,6 +174,7 @@ def read_opts(cfg, args): ('BF_FFMPEG_INC', 'FFMPEG includes', ''), ('BF_FFMPEG_LIBPATH', 'FFMPEG library path', ''), + (BoolOption('WITH_BF_BPYAPI_V24X', 'Compile Blender 2.4x python api if true', 'true')), (BoolOption('WITH_BF_JPEG', 'Use JPEG if true', 'true')), ('BF_JPEG', 'JPEG base path', ''),