This commit is contained in:
Daniel Genrich 2007-12-18 17:29:35 +00:00
commit a8a5776160
83 changed files with 5300 additions and 4342 deletions

@ -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<<bitIdx)) {
pixel[0] = col[0];

@ -13,11 +13,10 @@
#include <algorithm>
#include <stdio.h>
#if !defined(linux) && (defined (__sparc) || defined (__sparc__))
#if (defined (__sun__) || defined (__sun)) || (!defined(linux) && (defined (__sparc) || defined (__sparc__)))
#include <ieeefp.h>
#endif
// just use default rounding for platforms where its not available
#ifndef round
#define round(x) (x)

@ -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 <ieeefp.h>
#endif
/*****************************************************************************/
//! coarse step functions
/*****************************************************************************/

@ -13,7 +13,7 @@
#include "loop_tools.h"
#include <stdlib.h>
#if !defined(linux) && (defined (__sparc) || defined (__sparc__))
#if (defined (__sun__) || defined (__sun)) || (!defined(linux) && (defined (__sparc) || defined (__sparc__)))
#include <ieeefp.h>
#endif

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

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

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

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

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

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

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

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

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

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

@ -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; w<maxw; w++){
@ -586,7 +587,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C
//pa->verts[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; p<totpart; p++,pa++){
psys_particle_on_dm(ob,dm,part->from,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; i<child_nbr; i++){
for(p=0; p<psys->totpart; p++,cpa++){
@ -923,8 +926,10 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
tree=BLI_kdtree_new(totvert);
for(p=0; p<totvert; p++){
if(orcodata)
if(orcodata) {
VECCOPY(co,orcodata[p])
transform_mesh_orco_verts((Mesh*)ob->data, &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; p<totpart; p++, pa++)
reset_particle(pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot);
@ -4167,7 +4178,7 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
ParticleSettings *part=psys->part;
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; p<totpart; p++,pa++){
for(p=0, pa=psys->particles; p<totpart; p++,pa++){
if(pa->r_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 */
}

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

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

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

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

@ -57,11 +57,7 @@
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#if defined(__sun__) && !defined(__sparc__)
#include <mesa/glu.h>
#else
#include <GL/glu.h>
#endif
#endif
/*
* these should be phased out. cpack should be replaced in

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

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

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

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

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

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

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

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

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

@ -41,6 +41,7 @@
#include <BKE_main.h>
#include <BKE_curve.h>
#include <BKE_library.h>
#include <BKE_utildefines.h>
#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 );

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

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

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

@ -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; a<re->totvlak; 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; a<obr->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<obr->totvert; 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; a<re->totvert; 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 */

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

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

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

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

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

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

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

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

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

File diff suppressed because it is too large Load Diff

@ -148,19 +148,16 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
envre->totvlak= 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; a<re->totvert; 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; a<re->tothalo; 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; a<obr->tothalo; a++) {
if((a & 255)==0) har= obr->bloha[a>>8];
else har++;
for(a=0; a<re->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<re->totvlak; 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; a<obr->totvlak; 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; a<obr->totvlak; 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) {

@ -984,6 +984,5 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *dxt, f
texres->tb*= fx;
}
return retval;
}

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

@ -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;v<re->totvlak;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;v<obr->totvlak;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; v<re->totvlak; 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; v<obr->totvlak; 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);

@ -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.labda<is->labda) *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;
}

@ -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<R.tothalo; a++) {
if((a & 255)==0)
har= R.bloha[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<<pa->sample;
for(y=0; y<pa->recty; y++) {
for(x=0; x<pa->rectx; 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<<sample;
for(y=0; y<pa->recty; y++) {
for(x=0; x<pa->rectx; 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->sample<R.osa; pa->sample++) {
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->sample<R.osa; pa->sample+=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; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, rp++, fcol+=4, offs++) {
for(x=pa->disprect.xmin; x<pa->disprect.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<R.tothalo; a++) {
if((a & 255)==0) har= R.bloha[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(; v<R.totvlak; v++) {
vlr= RE_findOrAddVlak(&R, v);
if((bs->actob && 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(; v<obr->totvlak; 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 */

File diff suppressed because it is too large Load Diff

@ -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; a<re->totvert; 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; a<re->totvlak; 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(z<minz) minz= z;
if(z>maxz) 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; a<obr->totvlak; 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(z<minz) minz= z;
if(z>maxz) 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; samples<shb->totbuf; 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; a<totthread; a++)
BLI_insert_thread(&threads, re);
/* keep rendering as long as there are shadow buffers not ready */
do {
if((g_break=test_break()))
break;
PIL_sleep_ms(50);
BLI_lock_thread(LOCK_CUSTOM1);
for(lar=re->lampren.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; a<re->totvlak; 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; a<obr->totvlak; 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)
}
}

@ -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<<i1;
p2= 1<<i2;
p3= 1<<i3;
if(shi->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;

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

@ -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; a<obr->totstrand; 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; b<strand->totvert-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; b<strand->totvert-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; a<re->totstrand; 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; a<obr->totstrand; 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; b<strand->totvert; 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; b<strand->totvert; 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; b<strand->totvert; 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; b<strand->totvert; 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
}

@ -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])<fabs(nor[1]) && fabs(nor[2])<fabs(nor[1]) ) vlr->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;

File diff suppressed because it is too large Load Diff

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

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

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

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

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

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

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

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

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

@ -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; a<me->totface; 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;

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

@ -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; a<MAX_MTEX; a++) {
MTex *mtex= sd->mtex[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; i<me->totvert; ++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.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);
}
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)

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

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

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

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

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

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

@ -1230,7 +1230,8 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &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<VlakRen*> &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<VlakRen*> &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) {

@ -1109,7 +1109,8 @@ void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> &uvcoords, VlakRen
void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> &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<int> &faces,vector<string> &shaders,ve
map<VertRen*, int> &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<int> &faces,vector<string> &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<int> &faces,/*vector<string> &sh
map<VertRen*, int> &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<VlakRen*> &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<int> faces;
@ -1382,7 +1386,6 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_
// write all objects
void yafrayPluginRender_t::writeAllObjects()
{
// first all objects except dupliverts (and main instance object for dups)
for (map<Object*, vector<VlakRen*> >::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])

@ -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<string, Object*> 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;m<MAX_MTEX;m++) {
if (matr->septex & (1<<m)) continue; // only active channels
MTex* mx = matr->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;m<MAX_MTEX;m++) {
if (matr->septex & (1<<m)) continue; // only active channels
MTex* mx = matr->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

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

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

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

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

@ -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', ''),