Particles
========= - Fix crash in particle transform with the particle system not editable. - Particle child distribution and caching is now multithreaded. - Child particles now have a separate Render Amount next to the existing Amount. The render amount particles are now only distributed and cached at render time, which should make editing with child particles faster. - Two new options for diffuse strand shading: - Surface Diffuse: computes the strand normal taking the normal at the surface into account. - Blending Distance: the distance in Blender units over which to blend in the normal at the surface. - Special strand rendering for more memory efficient and faster hair and grass. This is a work in progress, and has a number of known issues, don't report bugs to me for this feature yet. More info: http://www.blender.org/development/current-projects/changes-since-244/particles/
This commit is contained in:
@@ -54,6 +54,7 @@ struct MVert;
|
|||||||
struct IpoCurve;
|
struct IpoCurve;
|
||||||
struct LinkNode;
|
struct LinkNode;
|
||||||
struct KDTree;
|
struct KDTree;
|
||||||
|
struct RNG;
|
||||||
|
|
||||||
typedef struct ParticleEffectorCache {
|
typedef struct ParticleEffectorCache {
|
||||||
struct ParticleEffectorCache *next, *prev;
|
struct ParticleEffectorCache *next, *prev;
|
||||||
@@ -148,6 +149,42 @@ typedef struct ParticleEdit{
|
|||||||
int totkeys;
|
int totkeys;
|
||||||
} ParticleEdit;
|
} ParticleEdit;
|
||||||
|
|
||||||
|
typedef struct ParticleThreadContext {
|
||||||
|
/* shared */
|
||||||
|
struct Object *ob;
|
||||||
|
struct DerivedMesh *dm;
|
||||||
|
struct ParticleSystemModifierData *psmd;
|
||||||
|
struct ParticleSystem *psys;
|
||||||
|
struct Material *ma;
|
||||||
|
|
||||||
|
/* distribution */
|
||||||
|
struct KDTree *tree;
|
||||||
|
|
||||||
|
struct ParticleSeam *seams;
|
||||||
|
int totseam;
|
||||||
|
|
||||||
|
float *jit, *jitoff, *weight;
|
||||||
|
float maxweight;
|
||||||
|
int *index, jitlevel;
|
||||||
|
|
||||||
|
int from, cfrom, distr;
|
||||||
|
|
||||||
|
/* path caching */
|
||||||
|
int editupdate, between, steps;
|
||||||
|
int totchild, totparent;
|
||||||
|
|
||||||
|
float cfra;
|
||||||
|
|
||||||
|
float *vg_length, *vg_clump, *vg_kink;
|
||||||
|
float *vg_rough1, *vg_rough2, *vg_roughe;
|
||||||
|
} ParticleThreadContext;
|
||||||
|
|
||||||
|
typedef struct ParticleThread {
|
||||||
|
ParticleThreadContext *ctx;
|
||||||
|
struct RNG *rng, *rng_path;
|
||||||
|
int num, tot;
|
||||||
|
} ParticleThread;
|
||||||
|
|
||||||
/* ----------- functions needed outside particlesystem ---------------- */
|
/* ----------- functions needed outside particlesystem ---------------- */
|
||||||
/* particle.c */
|
/* particle.c */
|
||||||
int count_particles(struct ParticleSystem *psys);
|
int count_particles(struct ParticleSystem *psys);
|
||||||
@@ -170,6 +207,7 @@ int psys_in_edit_mode(struct ParticleSystem *psys);
|
|||||||
void psys_free_settings(struct ParticleSettings *part);
|
void psys_free_settings(struct ParticleSettings *part);
|
||||||
void free_child_path_cache(struct ParticleSystem *psys);
|
void free_child_path_cache(struct ParticleSystem *psys);
|
||||||
void psys_free_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_hair(struct ParticleSystem *psys);
|
||||||
void free_keyed_keys(struct ParticleSystem *psys);
|
void free_keyed_keys(struct ParticleSystem *psys);
|
||||||
void psys_free(struct Object * ob, struct ParticleSystem * psys);
|
void psys_free(struct Object * ob, struct ParticleSystem * psys);
|
||||||
@@ -195,11 +233,19 @@ void psys_cache_child_paths(struct Object *ob, struct ParticleSystem *psys, floa
|
|||||||
int do_guide(struct ParticleKey *state, int pa_num, float time, struct ListBase *lb);
|
int do_guide(struct ParticleKey *state, int pa_num, float time, struct ListBase *lb);
|
||||||
float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size);
|
float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size);
|
||||||
float psys_get_timestep(struct ParticleSettings *part);
|
float psys_get_timestep(struct ParticleSettings *part);
|
||||||
float psys_get_child_time(struct ParticleSystem *psys, int child_nbr, float cfra);
|
float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra);
|
||||||
float psys_get_child_size(struct ParticleSystem *psys, int child_nbr, float cfra, float *pa_time);
|
float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time);
|
||||||
void psys_get_particle_on_path(struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel);
|
void psys_get_particle_on_path(struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel);
|
||||||
int psys_get_particle_state(struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always);
|
int psys_get_particle_state(struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always);
|
||||||
|
|
||||||
|
ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys, int totthread);
|
||||||
|
int psys_threads_init_distribution(ParticleThread *threads, struct DerivedMesh *dm, int from);
|
||||||
|
int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate);
|
||||||
|
void psys_threads_free(ParticleThread *threads);
|
||||||
|
|
||||||
|
void psys_thread_distribute_particle(ParticleThread *thread, struct ParticleData *pa, struct ChildParticle *cpa, int p);
|
||||||
|
void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i);
|
||||||
|
|
||||||
/* particle_system.c */
|
/* particle_system.c */
|
||||||
int psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys);
|
int psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys);
|
||||||
void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys);
|
void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys);
|
||||||
|
|||||||
@@ -640,7 +640,7 @@ static void new_particle_duplilist(ListBase *lb, Scene *sce, Object *par, Partic
|
|||||||
pa_num = a;
|
pa_num = a;
|
||||||
pa_time = psys->particles[psys->child[a - totpart].parent].time;
|
pa_time = psys->particles[psys->child[a - totpart].parent].time;
|
||||||
|
|
||||||
size=psys_get_child_size(psys, a - totpart, ctime, 0);
|
size=psys_get_child_size(psys, &psys->child[a - totpart], ctime, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(part->draw_as==PART_DRAW_GR) {
|
if(part->draw_as==PART_DRAW_GR) {
|
||||||
@@ -783,7 +783,7 @@ ListBase *object_duplilist(Scene *sce, Object *ob)
|
|||||||
{
|
{
|
||||||
ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist");
|
ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist");
|
||||||
duplilist->first= duplilist->last= NULL;
|
duplilist->first= duplilist->last= NULL;
|
||||||
|
|
||||||
if(ob->transflag & OB_DUPLI) {
|
if(ob->transflag & OB_DUPLI) {
|
||||||
if(ob->transflag & OB_DUPLIPARTS) {
|
if(ob->transflag & OB_DUPLIPARTS) {
|
||||||
ParticleSystem *psys = ob->particlesystem.first;
|
ParticleSystem *psys = ob->particlesystem.first;
|
||||||
@@ -808,7 +808,7 @@ ListBase *object_duplilist(Scene *sce, Object *ob)
|
|||||||
DupliObject *dob;
|
DupliObject *dob;
|
||||||
|
|
||||||
group_duplilist(duplilist, ob, 0); /* now recursive */
|
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 makde, requiring parent matrices */
|
||||||
for(dob= duplilist->first; dob; dob= dob->next)
|
for(dob= duplilist->first; dob; dob= dob->next)
|
||||||
Mat4CpyMat4(dob->ob->obmat, dob->mat);
|
Mat4CpyMat4(dob->ob->obmat, dob->mat);
|
||||||
|
|||||||
@@ -687,6 +687,9 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
|
|||||||
/* will become or-ed result of all node modes */
|
/* will become or-ed result of all node modes */
|
||||||
ma->mode_l= ma->mode;
|
ma->mode_l= ma->mode;
|
||||||
ma->mode_l &= ~MA_SHLESS;
|
ma->mode_l &= ~MA_SHLESS;
|
||||||
|
|
||||||
|
if(ma->strand_surfnor > 0.0f)
|
||||||
|
ma->mode_l |= MA_STR_SURFDIFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
|
static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
#include "BLI_kdtree.h"
|
#include "BLI_kdtree.h"
|
||||||
#include "BLI_linklist.h"
|
#include "BLI_linklist.h"
|
||||||
#include "BLI_rand.h"
|
#include "BLI_rand.h"
|
||||||
|
#include "BLI_threads.h"
|
||||||
|
|
||||||
#include "BKE_anim.h"
|
#include "BKE_anim.h"
|
||||||
|
|
||||||
@@ -299,6 +300,27 @@ void psys_free_path_cache(ParticleSystem *psys)
|
|||||||
}
|
}
|
||||||
free_child_path_cache(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 */
|
/* free everything */
|
||||||
void psys_free(Object *ob, ParticleSystem * psys)
|
void psys_free(Object *ob, ParticleSystem * psys)
|
||||||
{
|
{
|
||||||
@@ -1195,41 +1217,33 @@ static void do_rough_end(float *loc, float t, float fac, float shape, ParticleKe
|
|||||||
|
|
||||||
VECADD(state->co,state->co,rough);
|
VECADD(state->co,state->co,rough);
|
||||||
}
|
}
|
||||||
static int check_path_length(int k, int p, ParticleCacheKey **cache, ParticleCacheKey *state, float length, float *dvec)
|
static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec)
|
||||||
{
|
{
|
||||||
static float max_length = 1.0, cur_length = 0.0;
|
if(*cur_length + length > max_length){
|
||||||
|
//if(p<totparent){
|
||||||
if(k) {
|
// if(k<=(int)cache[totpart+p]->time){
|
||||||
if(cur_length + length > max_length){
|
// /* parents need to be calculated fully first so that they don't mess up their children */
|
||||||
//if(p<totparent){
|
// /* we'll make a note of where we got to though so that they're easy to finish later */
|
||||||
// if(k<=(int)cache[totpart+p]->time){
|
// state->time=(max_length-*cur_length)/length;
|
||||||
// /* parents need to be calculated fully first so that they don't mess up their children */
|
// cache[totpart+p]->time=(float)k;
|
||||||
// /* we'll make a note of where we got to though so that they're easy to finish later */
|
// }
|
||||||
// state->time=(max_length-cur_length)/length;
|
//}
|
||||||
// cache[totpart+p]->time=(float)k;
|
//else{
|
||||||
// }
|
VecMulf(dvec, (max_length - *cur_length) / length);
|
||||||
//}
|
VECADD(state->co, (state - 1)->co, dvec);
|
||||||
//else{
|
keys->steps = k;
|
||||||
VecMulf(dvec, (max_length - cur_length) / length);
|
/* something over the maximum step value */
|
||||||
VECADD(state->co, (state - 1)->co, dvec);
|
return k=100000;
|
||||||
cache[p]->steps = k;
|
//}
|
||||||
/* something over the maximum step value */
|
|
||||||
return k=100000;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cur_length+=length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {/* reset signal */
|
else {
|
||||||
max_length=length;
|
*cur_length+=length;
|
||||||
cur_length=0.0;
|
return k;
|
||||||
}
|
}
|
||||||
return k;
|
|
||||||
}
|
}
|
||||||
static void finalize_path_length(int p, ParticleCacheKey **cache)
|
static void finalize_path_length(ParticleCacheKey *keys)
|
||||||
{
|
{
|
||||||
ParticleCacheKey *state = cache[p];
|
ParticleCacheKey *state = keys;
|
||||||
float dvec[3];
|
float dvec[3];
|
||||||
state += state->steps;
|
state += state->steps;
|
||||||
|
|
||||||
@@ -1301,42 +1315,54 @@ void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSys
|
|||||||
if(orcos)
|
if(orcos)
|
||||||
MEM_freeN(orcos);
|
MEM_freeN(orcos);
|
||||||
}
|
}
|
||||||
void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int editupdate)
|
|
||||||
|
static void get_strand_normal(Material *ma, float *surfnor, float surfdist, float *nor)
|
||||||
{
|
{
|
||||||
|
float cross[3], nstrand[3], vnor[3], blend;
|
||||||
|
|
||||||
|
if(!((ma->mode & MA_STR_SURFDIFF) || (ma->strand_surfnor > 0.0f)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(ma->mode & MA_STR_SURFDIFF) {
|
||||||
|
Crossf(cross, surfnor, nor);
|
||||||
|
Crossf(nstrand, nor, cross);
|
||||||
|
|
||||||
|
blend= INPR(nstrand, surfnor);
|
||||||
|
CLAMP(blend, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
VecLerpf(vnor, nstrand, surfnor, blend);
|
||||||
|
Normalize(vnor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
VECCOPY(vnor, nor)
|
||||||
|
|
||||||
|
if(ma->strand_surfnor > 0.0f) {
|
||||||
|
if(ma->strand_surfnor > surfdist) {
|
||||||
|
blend= (ma->strand_surfnor - surfdist)/ma->strand_surfnor;
|
||||||
|
VecLerpf(vnor, vnor, surfnor, blend);
|
||||||
|
Normalize(vnor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VECCOPY(nor, vnor);
|
||||||
|
}
|
||||||
|
|
||||||
|
int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate)
|
||||||
|
{
|
||||||
|
ParticleThreadContext *ctx= threads[0].ctx;
|
||||||
|
Object *ob= ctx->ob;
|
||||||
|
ParticleSystem *psys= ctx->psys;
|
||||||
ParticleSettings *part = psys->part;
|
ParticleSettings *part = psys->part;
|
||||||
ParticleEditSettings *pset = &G.scene->toolsettings->particle;
|
ParticleEditSettings *pset = &G.scene->toolsettings->particle;
|
||||||
ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
|
int totparent=0, between=0;
|
||||||
ParticleData *pa;
|
|
||||||
ChildParticle *cpa;
|
|
||||||
ParticleCacheKey **cache = psys->childcache, **pcache = psys->pathcache;
|
|
||||||
ParticleCacheKey *tcache, *state, *par=0, *key[4];
|
|
||||||
ParticleTexture ptex;
|
|
||||||
Material *ma = give_current_material(ob, part->omat);
|
|
||||||
|
|
||||||
float length, pa_length = 1.0, pa_clump = 1.0, pa_kink = 1.0;
|
|
||||||
float pa_rough1 = 1.0, pa_rough2 = 1.0, pa_roughe = 1.0;
|
|
||||||
float t, rough_t;
|
|
||||||
float dvec[3], orco[3], ornor[3], imat[4][4];
|
|
||||||
float *vg_length = 0, *vg_clump = 0, *vg_kink = 0;
|
|
||||||
float *vg_rough1 = 0, *vg_rough2 = 0, *vg_roughe = 0;
|
|
||||||
float cpa_1st[3];
|
|
||||||
|
|
||||||
int k, i, totparent=0, between=0, edit=0;
|
|
||||||
int steps = (int)pow(2.0,(double)part->draw_step);
|
int steps = (int)pow(2.0,(double)part->draw_step);
|
||||||
int totchild = psys->totchild;
|
int totchild = psys->totchild;
|
||||||
int cpa_num; short cpa_from;
|
int i, seed, totthread= threads[0].tot;
|
||||||
|
|
||||||
if(part->flag & PART_ANIM_BRANCHING)
|
|
||||||
BLI_srandom(31415926 + psys->seed + (int)cfra);
|
|
||||||
else
|
|
||||||
BLI_srandom(31415926 + psys->seed);
|
|
||||||
|
|
||||||
/*---start figuring out what is actually wanted---*/
|
/*---start figuring out what is actually wanted---*/
|
||||||
if(psys_in_edit_mode(psys)){
|
if(psys_in_edit_mode(psys))
|
||||||
if(G.rendering==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0)
|
if(G.rendering==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0)
|
||||||
totchild=0;
|
totchild=0;
|
||||||
edit=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
|
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
|
||||||
totparent=(int)(totchild*part->parents*0.3);
|
totparent=(int)(totchild*part->parents*0.3);
|
||||||
@@ -1346,15 +1372,387 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed
|
|||||||
|
|
||||||
if(G.rendering)
|
if(G.rendering)
|
||||||
steps=(int)pow(2.0,(double)part->ren_step);
|
steps=(int)pow(2.0,(double)part->ren_step);
|
||||||
else if(part->flag & PART_CHILD_RENDER){
|
|
||||||
totchild=0;
|
|
||||||
}
|
|
||||||
else{
|
else{
|
||||||
totchild=(int)((float)totchild*(float)part->disp/100.0f);
|
totchild=(int)((float)totchild*(float)part->disp/100.0f);
|
||||||
totparent=MIN2(totparent,totchild);
|
totparent=MIN2(totparent,totchild);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(totchild==0) return;
|
if(totchild==0) return 0;
|
||||||
|
|
||||||
|
/* init random number generator */
|
||||||
|
if(ctx->psys->part->flag & PART_ANIM_BRANCHING)
|
||||||
|
seed= 31415926 + ctx->psys->seed + (int)cfra;
|
||||||
|
else
|
||||||
|
seed= 31415926 + ctx->psys->seed;
|
||||||
|
|
||||||
|
if(part->flag & PART_BRANCHING || ctx->editupdate || totchild < 10000)
|
||||||
|
totthread= 1;
|
||||||
|
|
||||||
|
for(i=0; i<totthread; i++) {
|
||||||
|
threads[i].rng_path= rng_new(seed);
|
||||||
|
threads[i].tot= totthread;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill context values */
|
||||||
|
ctx->between= between;
|
||||||
|
ctx->steps= steps;
|
||||||
|
ctx->totchild= totchild;
|
||||||
|
ctx->totparent= totparent;
|
||||||
|
ctx->cfra= cfra;
|
||||||
|
|
||||||
|
psys->lattice = psys_get_lattice(ob, psys);
|
||||||
|
|
||||||
|
/* cache all relevant vertex groups if they exist */
|
||||||
|
if(part->from!=PART_FROM_PARTICLE){
|
||||||
|
ctx->vg_length = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_LENGTH);
|
||||||
|
ctx->vg_clump = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_CLUMP);
|
||||||
|
ctx->vg_kink = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_KINK);
|
||||||
|
ctx->vg_rough1 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH1);
|
||||||
|
ctx->vg_rough2 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH2);
|
||||||
|
ctx->vg_roughe = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGHE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set correct ipo timing */
|
||||||
|
if(part->flag&PART_ABS_TIME && part->ipo){
|
||||||
|
calc_ipo(part->ipo, cfra);
|
||||||
|
execute_ipo((ID *)part, part->ipo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* note: this function must be thread safe, except for branching! */
|
||||||
|
void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i)
|
||||||
|
{
|
||||||
|
ParticleThreadContext *ctx= thread->ctx;
|
||||||
|
Object *ob= ctx->ob;
|
||||||
|
ParticleSystem *psys = ctx->psys;
|
||||||
|
ParticleSettings *part = psys->part;
|
||||||
|
ParticleCacheKey **cache= psys->childcache;
|
||||||
|
ParticleCacheKey **pcache= psys->pathcache;
|
||||||
|
ParticleCacheKey *state, *par = NULL, *key[4];
|
||||||
|
ParticleData *pa;
|
||||||
|
ParticleTexture ptex;
|
||||||
|
float *cpa_fuv=0;
|
||||||
|
float orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3];
|
||||||
|
float branch_begin, branch_end, branch_prob, branchfac, rough_rand;
|
||||||
|
float pa_rough1, pa_rough2, pa_roughe, length, pa_length, pa_clump, pa_kink;
|
||||||
|
float max_length = 1.0f, cur_length = 0.0f;
|
||||||
|
int k, cpa_num, guided=0;
|
||||||
|
short cpa_from;
|
||||||
|
|
||||||
|
if(part->flag & PART_BRANCHING) {
|
||||||
|
branch_begin=rng_getFloat(thread->rng_path);
|
||||||
|
branch_end=branch_begin+(1.0f-branch_begin)*rng_getFloat(thread->rng_path);
|
||||||
|
branch_prob=rng_getFloat(thread->rng_path);
|
||||||
|
rough_rand=rng_getFloat(thread->rng_path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
branch_begin= 0.0f;
|
||||||
|
branch_end= 0.0f;
|
||||||
|
branch_prob= 0.0f;
|
||||||
|
rough_rand= 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i<psys->totpart){
|
||||||
|
branch_begin=0.0f;
|
||||||
|
branch_end=1.0f;
|
||||||
|
branch_prob=0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ctx->between){
|
||||||
|
int w, needupdate;
|
||||||
|
float foffset;
|
||||||
|
|
||||||
|
if(ctx->editupdate && !(part->flag & PART_BRANCHING)) {
|
||||||
|
needupdate= 0;
|
||||||
|
w= 0;
|
||||||
|
while(w<4 && cpa->pa[w]>=0) {
|
||||||
|
if(psys->particles[cpa->pa[w]].flag & PARS_EDIT_RECALC) {
|
||||||
|
needupdate= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!needupdate)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
memset(keys, 0, sizeof(*keys)*(ctx->steps+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get parent paths */
|
||||||
|
w= 0;
|
||||||
|
while(w<4 && cpa->pa[w]>=0){
|
||||||
|
key[w] = pcache[cpa->pa[w]];
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the original coordinates (orco) for texture usage */
|
||||||
|
cpa_num = cpa->num;
|
||||||
|
|
||||||
|
foffset= cpa->foffset;
|
||||||
|
if(part->childtype == PART_CHILD_FACES)
|
||||||
|
foffset = -(2.0f + part->childspread);
|
||||||
|
cpa_fuv = cpa->fuv;
|
||||||
|
cpa_from = PART_FROM_FACE;
|
||||||
|
|
||||||
|
psys_particle_on_emitter(ob,ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,orco,ornor,0,0);
|
||||||
|
|
||||||
|
/* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
|
||||||
|
VECCOPY(cpa_1st,orco);
|
||||||
|
Mat4MulVecfl(ob->obmat,cpa_1st);
|
||||||
|
|
||||||
|
pa=0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(ctx->editupdate && !(part->flag & PART_BRANCHING)) {
|
||||||
|
if(!(psys->particles[cpa->parent].flag & PARS_EDIT_RECALC))
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(keys, 0, sizeof(*keys)*(ctx->steps+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the parent path */
|
||||||
|
key[0]=pcache[cpa->parent];
|
||||||
|
|
||||||
|
/* get the original coordinates (orco) for texture usage */
|
||||||
|
pa=psys->particles+cpa->parent;
|
||||||
|
|
||||||
|
cpa_from=part->from;
|
||||||
|
cpa_num=pa->num;
|
||||||
|
cpa_fuv=pa->fuv;
|
||||||
|
|
||||||
|
psys_particle_on_emitter(ob,ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,orco,ornor,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
keys->steps = ctx->steps;
|
||||||
|
|
||||||
|
/* correct child ipo timing */
|
||||||
|
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
|
||||||
|
float dsta=part->end-part->sta;
|
||||||
|
calc_ipo(part->ipo, 100.0f*(ctx->cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0])));
|
||||||
|
execute_ipo((ID *)part, part->ipo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get different child parameters from textures & vgroups */
|
||||||
|
ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]);
|
||||||
|
ptex.clump=1.0;
|
||||||
|
ptex.kink=1.0;
|
||||||
|
|
||||||
|
get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,&ptex,MAP_PA_CACHE);
|
||||||
|
|
||||||
|
pa_length=ptex.length;
|
||||||
|
pa_clump=ptex.clump;
|
||||||
|
pa_kink=ptex.kink;
|
||||||
|
pa_rough1=1.0;
|
||||||
|
pa_rough2=1.0;
|
||||||
|
pa_roughe=1.0;
|
||||||
|
|
||||||
|
if(ctx->vg_length)
|
||||||
|
pa_length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length);
|
||||||
|
if(ctx->vg_clump)
|
||||||
|
pa_clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump);
|
||||||
|
if(ctx->vg_kink)
|
||||||
|
pa_kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink);
|
||||||
|
if(ctx->vg_rough1)
|
||||||
|
pa_rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1);
|
||||||
|
if(ctx->vg_rough2)
|
||||||
|
pa_rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2);
|
||||||
|
if(ctx->vg_roughe)
|
||||||
|
pa_roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe);
|
||||||
|
|
||||||
|
/* create the child path */
|
||||||
|
for(k=0,state=keys; k<=ctx->steps; k++,state++){
|
||||||
|
t=(float)k/(float)ctx->steps;
|
||||||
|
|
||||||
|
if(ctx->between){
|
||||||
|
int w=0;
|
||||||
|
|
||||||
|
state->co[0] = state->co[1] = state->co[2] = 0.0f;
|
||||||
|
state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
|
||||||
|
|
||||||
|
//QUATCOPY(state->rot,key[0]->rot);
|
||||||
|
|
||||||
|
/* child position is the weighted sum of parent positions */
|
||||||
|
while(w<4 && cpa->pa[w]>=0){
|
||||||
|
state->co[0] += cpa->w[w] * key[w]->co[0];
|
||||||
|
state->co[1] += cpa->w[w] * key[w]->co[1];
|
||||||
|
state->co[2] += cpa->w[w] * key[w]->co[2];
|
||||||
|
|
||||||
|
state->vel[0] += cpa->w[w] * key[w]->vel[0];
|
||||||
|
state->vel[1] += cpa->w[w] * key[w]->vel[1];
|
||||||
|
state->vel[2] += cpa->w[w] * key[w]->vel[2];
|
||||||
|
key[w]++;
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
if(k==0){
|
||||||
|
/* calculate the offset between actual child root position and first position interpolated from parents */
|
||||||
|
VECSUB(cpa_1st,cpa_1st,state->co);
|
||||||
|
}
|
||||||
|
/* apply offset for correct positioning */
|
||||||
|
VECADD(state->co,state->co,cpa_1st);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
/* offset the child from the parent position */
|
||||||
|
offset_child(cpa, (ParticleKey*)key[0], (ParticleKey*)state, part->childflat, part->childrad);
|
||||||
|
|
||||||
|
key[0]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ctx->totparent){
|
||||||
|
if(i>=ctx->totparent)
|
||||||
|
/* this is not threadsafe, but should only happen for
|
||||||
|
* branching particles particles, which are not threaded */
|
||||||
|
par = cache[cpa->parent] + k;
|
||||||
|
else
|
||||||
|
par=0;
|
||||||
|
}
|
||||||
|
else if(cpa->parent>=0){
|
||||||
|
par=pcache[cpa->parent]+k;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply different deformations to the child path */
|
||||||
|
if(part->flag & PART_CHILD_GUIDE)
|
||||||
|
guided = do_guide((ParticleKey*)state, i, t, &(psys->effectors)); //safe to cast, since only co and vel are used
|
||||||
|
|
||||||
|
if(guided==0){
|
||||||
|
if(part->kink)
|
||||||
|
do_prekink((ParticleKey*)state, (ParticleKey*)par, par->rot, t,
|
||||||
|
part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat);
|
||||||
|
|
||||||
|
do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump);
|
||||||
|
|
||||||
|
if(part->kink)
|
||||||
|
do_postkink((ParticleKey*)state, (ParticleKey*)par, par->rot, t,
|
||||||
|
part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING)
|
||||||
|
rough_t = t * rough_rand;
|
||||||
|
else
|
||||||
|
rough_t = t;
|
||||||
|
|
||||||
|
if(part->rough1 != 0.0 && pa_rough1 != 0.0)
|
||||||
|
do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state);
|
||||||
|
|
||||||
|
if(part->rough2 != 0.0 && pa_rough2 != 0.0)
|
||||||
|
do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state);
|
||||||
|
|
||||||
|
if(part->rough_end != 0.0 && pa_roughe != 0.0)
|
||||||
|
do_rough_end(cpa->rand, rough_t, pa_roughe*part->rough_end, part->rough_end_shape, (ParticleKey*)state, (ParticleKey*)par);
|
||||||
|
|
||||||
|
if(part->flag & PART_BRANCHING && ctx->between==0){
|
||||||
|
if(branch_prob > part->branch_thres){
|
||||||
|
branchfac=0.0f;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(part->flag & PART_SYMM_BRANCHING){
|
||||||
|
if(t < branch_begin || t > branch_end)
|
||||||
|
branchfac=0.0f;
|
||||||
|
else{
|
||||||
|
if((t-branch_begin)/(branch_end-branch_begin)<0.5)
|
||||||
|
branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin);
|
||||||
|
else
|
||||||
|
branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin);
|
||||||
|
|
||||||
|
CLAMP(branchfac,0.0f,1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(t < branch_begin){
|
||||||
|
branchfac=0.0f;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f);
|
||||||
|
CLAMP(branchfac,0.0f,1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i<psys->totpart)
|
||||||
|
VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac);
|
||||||
|
else
|
||||||
|
/* this is not threadsafe, but should only happen for
|
||||||
|
* branching particles particles, which are not threaded */
|
||||||
|
VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have to correct velocity because of kink & clump */
|
||||||
|
if(k>1){
|
||||||
|
VECSUB((state-1)->vel,state->co,(state-2)->co);
|
||||||
|
VecMulf((state-1)->vel,0.5);
|
||||||
|
|
||||||
|
if(part->draw & PART_DRAW_MAT_COL)
|
||||||
|
get_strand_normal(ctx->ma, ornor, cur_length, (state-1)->vel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if path needs to be cut before actual end of data points */
|
||||||
|
if(k){
|
||||||
|
VECSUB(dvec,state->co,(state-1)->co);
|
||||||
|
if(part->flag&PART_ABS_LENGTH)
|
||||||
|
length=VecLength(dvec);
|
||||||
|
else
|
||||||
|
length=1.0f/(float)ctx->steps;
|
||||||
|
|
||||||
|
k=check_path_length(k,keys,state,max_length,&cur_length,length,dvec);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
/* initialize length calculation */
|
||||||
|
if(part->flag&PART_ABS_LENGTH)
|
||||||
|
max_length= part->abslength*pa_length;
|
||||||
|
else
|
||||||
|
max_length= pa_length;
|
||||||
|
|
||||||
|
cur_length= 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(part->draw & PART_DRAW_MAT_COL) {
|
||||||
|
VECCOPY(state->col, &ctx->ma->r)
|
||||||
|
get_strand_normal(ctx->ma, ornor, cur_length, state->vel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now let's finalise the interpolated parents that we might have left half done before */
|
||||||
|
if(i<ctx->totparent)
|
||||||
|
finalize_path_length(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *exec_child_path_cache(void *data)
|
||||||
|
{
|
||||||
|
ParticleThread *thread= (ParticleThread*)data;
|
||||||
|
ParticleThreadContext *ctx= thread->ctx;
|
||||||
|
ParticleSystem *psys= ctx->psys;
|
||||||
|
ParticleCacheKey **cache= psys->childcache;
|
||||||
|
ChildParticle *cpa;
|
||||||
|
int i, totchild= ctx->totchild;
|
||||||
|
|
||||||
|
cpa= psys->child + thread->num;
|
||||||
|
for(i=thread->num; i<totchild; i+=thread->tot, cpa+=thread->tot)
|
||||||
|
psys_thread_create_path(thread, cpa, cache[i], i);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int editupdate)
|
||||||
|
{
|
||||||
|
ParticleSettings *part = psys->part;
|
||||||
|
ParticleThread *pthreads;
|
||||||
|
ParticleThreadContext *ctx;
|
||||||
|
ParticleCacheKey **cache, *tcache;
|
||||||
|
ListBase threads;
|
||||||
|
int i, totchild, totparent, totthread;
|
||||||
|
|
||||||
|
pthreads= psys_threads_create(ob, psys, G.scene->r.threads);
|
||||||
|
|
||||||
|
if(!psys_threads_init_path(pthreads, cfra, editupdate)) {
|
||||||
|
psys_threads_free(pthreads);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx= pthreads[0].ctx;
|
||||||
|
totchild= ctx->totchild;
|
||||||
|
totparent= ctx->totparent;
|
||||||
|
|
||||||
if(editupdate && psys->childcache && !(part->flag & PART_BRANCHING) && totchild == psys->totchildcache) {
|
if(editupdate && psys->childcache && !(part->flag & PART_BRANCHING) && totchild == psys->totchildcache) {
|
||||||
cache = psys->childcache;
|
cache = psys->childcache;
|
||||||
@@ -1364,317 +1762,29 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed
|
|||||||
free_child_path_cache(psys);
|
free_child_path_cache(psys);
|
||||||
|
|
||||||
cache = psys->childcache = MEM_callocN(totchild*sizeof(void *), "Child path cache array");
|
cache = psys->childcache = MEM_callocN(totchild*sizeof(void *), "Child path cache array");
|
||||||
tcache = MEM_callocN(totchild * (steps + 1) * sizeof(ParticleCacheKey), "Child path cache");
|
tcache = MEM_callocN(totchild * (ctx->steps + 1) * sizeof(ParticleCacheKey), "Child path cache");
|
||||||
for(i=0; i<totchild; i++)
|
for(i=0; i<totchild; i++)
|
||||||
cache[i] = tcache + i * (steps + 1);
|
cache[i] = tcache + i * (ctx->steps + 1);
|
||||||
|
|
||||||
|
psys->totchildcache = totchild;
|
||||||
}
|
}
|
||||||
|
|
||||||
psys->lattice = psys_get_lattice(ob,psys);
|
totthread= pthreads[0].tot;
|
||||||
|
|
||||||
/* cache all relevant vertex groups if they exist */
|
if(totthread > 1) {
|
||||||
if(part->from!=PART_FROM_PARTICLE){
|
BLI_init_threads(&threads, exec_child_path_cache, totthread);
|
||||||
vg_length = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_LENGTH);
|
|
||||||
vg_clump = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_CLUMP);
|
for(i=0; i<totthread; i++)
|
||||||
vg_kink = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_KINK);
|
BLI_insert_thread(&threads, &pthreads[i]);
|
||||||
vg_rough1 = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROUGH1);
|
|
||||||
vg_rough2 = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROUGH2);
|
BLI_end_threads(&threads);
|
||||||
vg_roughe = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROUGHE);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
exec_child_path_cache(&pthreads[0]);
|
||||||
|
|
||||||
/* set correct ipo timing */
|
psys_threads_free(pthreads);
|
||||||
if(part->flag&PART_ABS_TIME && part->ipo){
|
|
||||||
calc_ipo(part->ipo, cfra);
|
|
||||||
execute_ipo((ID *)part, part->ipo);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4Invert(imat,ob->obmat);
|
|
||||||
|
|
||||||
for(i=0,cpa=psys->child; i<totchild; i++, cpa++){
|
|
||||||
int guided=0;
|
|
||||||
float *cpa_fuv=0;
|
|
||||||
float branch_begin=0.0f, branch_end=0.0f, branch_prob=0.0f;
|
|
||||||
float branchfac, rough_rand=0.0f;
|
|
||||||
|
|
||||||
if(part->flag & PART_BRANCHING) {
|
|
||||||
branch_begin=BLI_frand();
|
|
||||||
branch_end=branch_begin+(1.0f-branch_begin)*BLI_frand();
|
|
||||||
branch_prob=BLI_frand();
|
|
||||||
rough_rand=BLI_frand();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i<psys->totpart){
|
|
||||||
branch_begin=0.0f;
|
|
||||||
branch_end=1.0f;
|
|
||||||
branch_prob=0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(between){
|
|
||||||
int w, needupdate;
|
|
||||||
float foffset;
|
|
||||||
|
|
||||||
if(editupdate && !(part->flag & PART_BRANCHING)) {
|
|
||||||
needupdate= 0;
|
|
||||||
w= 0;
|
|
||||||
while(w<4 && cpa->pa[w]>=0) {
|
|
||||||
if(psys->particles[cpa->pa[w]].flag & PARS_EDIT_RECALC) {
|
|
||||||
needupdate= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
w++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!needupdate)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get parent paths */
|
|
||||||
w= 0;
|
|
||||||
while(w<4 && cpa->pa[w]>=0){
|
|
||||||
key[w] = pcache[cpa->pa[w]];
|
|
||||||
w++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the original coordinates (orco) for texture usage */
|
|
||||||
cpa_num = cpa->num;
|
|
||||||
|
|
||||||
foffset= cpa->foffset;
|
|
||||||
if(part->childtype == PART_CHILD_FACES)
|
|
||||||
foffset = -(2.0f + part->childspread);
|
|
||||||
cpa_fuv = cpa->fuv;
|
|
||||||
cpa_from = PART_FROM_FACE;
|
|
||||||
|
|
||||||
psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,orco,ornor,0,0);
|
|
||||||
|
|
||||||
/* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
|
|
||||||
VECCOPY(cpa_1st,orco);
|
|
||||||
Mat4MulVecfl(ob->obmat,cpa_1st);
|
|
||||||
|
|
||||||
pa=0;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if(editupdate && !(part->flag & PART_BRANCHING)) {
|
|
||||||
if(!(psys->particles[cpa->parent].flag & PARS_EDIT_RECALC))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the parent path */
|
|
||||||
key[0]=pcache[cpa->parent];
|
|
||||||
|
|
||||||
/* get the original coordinates (orco) for texture usage */
|
|
||||||
pa=psys->particles+cpa->parent;
|
|
||||||
|
|
||||||
cpa_from=part->from;
|
|
||||||
cpa_num=pa->num;
|
|
||||||
cpa_fuv=pa->fuv;
|
|
||||||
|
|
||||||
psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,orco,ornor,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache[i]->steps = steps;
|
|
||||||
|
|
||||||
/* correct child ipo timing */
|
|
||||||
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
|
|
||||||
float dsta=part->end-part->sta;
|
|
||||||
calc_ipo(part->ipo, 100.0f*(cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0])));
|
|
||||||
execute_ipo((ID *)part, part->ipo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get different child parameters from textures & vgroups */
|
|
||||||
ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]);
|
|
||||||
ptex.clump=1.0;
|
|
||||||
ptex.kink=1.0;
|
|
||||||
|
|
||||||
get_cpa_texture(psmd->dm,ma,cpa_num,cpa_fuv,orco,&ptex,MAP_PA_CACHE);
|
|
||||||
|
|
||||||
pa_length=ptex.length;
|
|
||||||
pa_clump=ptex.clump;
|
|
||||||
pa_kink=ptex.kink;
|
|
||||||
pa_rough1=1.0;
|
|
||||||
pa_rough2=1.0;
|
|
||||||
pa_roughe=1.0;
|
|
||||||
|
|
||||||
if(vg_length)
|
|
||||||
pa_length*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_length);
|
|
||||||
if(vg_clump)
|
|
||||||
pa_clump*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_clump);
|
|
||||||
if(vg_kink)
|
|
||||||
pa_kink*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_kink);
|
|
||||||
if(vg_rough1)
|
|
||||||
pa_rough1*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_rough1);
|
|
||||||
if(vg_rough2)
|
|
||||||
pa_rough2*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_rough2);
|
|
||||||
if(vg_roughe)
|
|
||||||
pa_roughe*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_roughe);
|
|
||||||
|
|
||||||
/* create the child path */
|
|
||||||
for(k=0,state=cache[i]; k<=steps; k++,state++){
|
|
||||||
t=(float)k/(float)steps;
|
|
||||||
|
|
||||||
if(between){
|
|
||||||
int w=0;
|
|
||||||
|
|
||||||
state->co[0] = state->co[1] = state->co[2] = 0.0f;
|
|
||||||
state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
|
|
||||||
|
|
||||||
//QUATCOPY(state->rot,key[0]->rot);
|
|
||||||
|
|
||||||
/* child position is the weighted sum of parent positions */
|
|
||||||
while(w<4 && cpa->pa[w]>=0){
|
|
||||||
state->co[0] += cpa->w[w] * key[w]->co[0];
|
|
||||||
state->co[1] += cpa->w[w] * key[w]->co[1];
|
|
||||||
state->co[2] += cpa->w[w] * key[w]->co[2];
|
|
||||||
|
|
||||||
state->vel[0] += cpa->w[w] * key[w]->vel[0];
|
|
||||||
state->vel[1] += cpa->w[w] * key[w]->vel[1];
|
|
||||||
state->vel[2] += cpa->w[w] * key[w]->vel[2];
|
|
||||||
key[w]++;
|
|
||||||
w++;
|
|
||||||
}
|
|
||||||
if(k==0){
|
|
||||||
/* calculate the offset between actual child root position and first position interpolated from parents */
|
|
||||||
VECSUB(cpa_1st,cpa_1st,state->co);
|
|
||||||
}
|
|
||||||
/* apply offset for correct positioning */
|
|
||||||
VECADD(state->co,state->co,cpa_1st);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
/* offset the child from the parent position */
|
|
||||||
offset_child(cpa, (ParticleKey*)key[0], (ParticleKey*)state, part->childflat, part->childrad);
|
|
||||||
|
|
||||||
key[0]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(totparent){
|
|
||||||
if(i>=totparent)
|
|
||||||
par = cache[cpa->parent] + k;
|
|
||||||
else
|
|
||||||
par=0;
|
|
||||||
}
|
|
||||||
else if(cpa->parent>=0){
|
|
||||||
par=pcache[cpa->parent]+k;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* apply different deformations to the child path */
|
|
||||||
if(part->flag & PART_CHILD_GUIDE)
|
|
||||||
guided = do_guide((ParticleKey*)state, i, t, &(psys->effectors)); //safe to cast, since only co and vel are used
|
|
||||||
|
|
||||||
if(guided==0){
|
|
||||||
if(part->kink)
|
|
||||||
do_prekink((ParticleKey*)state, (ParticleKey*)par, par->rot, t,
|
|
||||||
part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat);
|
|
||||||
|
|
||||||
do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump);
|
|
||||||
|
|
||||||
if(part->kink)
|
|
||||||
do_postkink((ParticleKey*)state, (ParticleKey*)par, par->rot, t,
|
|
||||||
part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(part->flag & PART_BRANCHING && between == 0 && part->flag & PART_ANIM_BRANCHING)
|
|
||||||
rough_t = t * rough_rand;
|
|
||||||
else
|
|
||||||
rough_t = t;
|
|
||||||
|
|
||||||
if(part->rough1 != 0.0 && pa_rough1 != 0.0)
|
|
||||||
do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state);
|
|
||||||
|
|
||||||
if(part->rough2 != 0.0 && pa_rough2 != 0.0)
|
|
||||||
do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state);
|
|
||||||
|
|
||||||
if(part->rough_end != 0.0 && pa_roughe != 0.0)
|
|
||||||
do_rough_end(cpa->rand, rough_t, pa_roughe*part->rough_end, part->rough_end_shape, (ParticleKey*)state, (ParticleKey*)par);
|
|
||||||
|
|
||||||
if(part->flag & PART_BRANCHING && between==0){
|
|
||||||
if(branch_prob > part->branch_thres){
|
|
||||||
branchfac=0.0f;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if(part->flag & PART_SYMM_BRANCHING){
|
|
||||||
if(t < branch_begin || t > branch_end)
|
|
||||||
branchfac=0.0f;
|
|
||||||
else{
|
|
||||||
if((t-branch_begin)/(branch_end-branch_begin)<0.5)
|
|
||||||
branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin);
|
|
||||||
else
|
|
||||||
branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin);
|
|
||||||
|
|
||||||
CLAMP(branchfac,0.0f,1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if(t < branch_begin){
|
|
||||||
branchfac=0.0f;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f);
|
|
||||||
CLAMP(branchfac,0.0f,1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i<psys->totpart){
|
|
||||||
VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we have to correct velocity because of kink & clump */
|
|
||||||
if(k>1){
|
|
||||||
VECSUB((state-1)->vel,state->co,(state-2)->co);
|
|
||||||
VecMulf((state-1)->vel,0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if path needs to be cut before actual end of data points */
|
|
||||||
if(k){
|
|
||||||
VECSUB(dvec,state->co,(state-1)->co);
|
|
||||||
if(part->flag&PART_ABS_LENGTH)
|
|
||||||
length=VecLength(dvec);
|
|
||||||
else
|
|
||||||
length=1.0f/(float)steps;
|
|
||||||
|
|
||||||
k=check_path_length(k,i,cache,state,length,dvec);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
/* initialize length calculation */
|
|
||||||
if(part->flag&PART_ABS_LENGTH)
|
|
||||||
check_path_length(0,0,0,0,part->abslength*pa_length,0);
|
|
||||||
else
|
|
||||||
check_path_length(0,0,0,0,pa_length,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(part->draw & PART_DRAW_MAT_COL)
|
|
||||||
VECCOPY(state->col, &ma->r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* now let's finalise the interpolated parents that we might have left half done before */
|
|
||||||
if(totchild) for(i=0,cpa=psys->child; i<totparent; i++, cpa++)
|
|
||||||
finalize_path_length(i,cache);
|
|
||||||
|
|
||||||
if(vg_length)
|
|
||||||
MEM_freeN(vg_length);
|
|
||||||
if(vg_clump)
|
|
||||||
MEM_freeN(vg_clump);
|
|
||||||
if(vg_kink)
|
|
||||||
MEM_freeN(vg_kink);
|
|
||||||
if(vg_rough1)
|
|
||||||
MEM_freeN(vg_rough1);
|
|
||||||
if(vg_rough2)
|
|
||||||
MEM_freeN(vg_roughe);
|
|
||||||
if(vg_roughe)
|
|
||||||
MEM_freeN(vg_roughe);
|
|
||||||
|
|
||||||
psys->totchildcache = totchild;
|
|
||||||
|
|
||||||
if(psys->lattice){
|
|
||||||
end_latt_deform();
|
|
||||||
psys->lattice=0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculates paths ready for drawing/rendering. */
|
/* Calculates paths ready for drawing/rendering. */
|
||||||
/* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */
|
/* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */
|
||||||
/* -Makes child strands possible and creates them too into the cache. */
|
/* -Makes child strands possible and creates them too into the cache. */
|
||||||
@@ -2260,6 +2370,7 @@ static void default_particle_settings(ParticleSettings *part)
|
|||||||
part->childsize=1.0;
|
part->childsize=1.0;
|
||||||
|
|
||||||
part->child_nbr=10;
|
part->child_nbr=10;
|
||||||
|
part->ren_child_nbr=100;
|
||||||
part->childrad=0.2f;
|
part->childrad=0.2f;
|
||||||
part->childflat=0.0f;
|
part->childflat=0.0f;
|
||||||
part->clumppow=0.0f;
|
part->clumppow=0.0f;
|
||||||
@@ -2491,12 +2602,14 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd
|
|||||||
else
|
else
|
||||||
//psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->fuv,pa->foffset,texco,0,0,0);
|
//psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->fuv,pa->foffset,texco,0,0,0);
|
||||||
/* <jahka> anyways I think it will be too small a difference to notice, so psys_get_texture should only know about the original mesh structure.. no dm needed anywhere */
|
/* <jahka> anyways I think it will be too small a difference to notice, so psys_get_texture should only know about the original mesh structure.. no dm needed anywhere */
|
||||||
psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,-1,pa->fuv,pa->foffset,texco,0,0,0);
|
/* <brecht> the code only does dm based lookup now, so passing num_dmcache anyway to avoid^
|
||||||
|
* massive slowdown here */
|
||||||
|
psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,texco,0,0,0);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->fuv,pa->offset,texco,0,0,0);
|
//psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->fuv,pa->offset,texco,0,0,0);
|
||||||
/* ditto above */
|
/* ditto above */
|
||||||
psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,-1,pa->fuv,pa->foffset,texco,0,0,0);
|
psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,texco,0,0,0);
|
||||||
}
|
}
|
||||||
externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3);
|
externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3);
|
||||||
|
|
||||||
@@ -2566,10 +2679,9 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd,
|
|||||||
|
|
||||||
return size*part->size;
|
return size*part->size;
|
||||||
}
|
}
|
||||||
float psys_get_child_time(ParticleSystem *psys, int child_nbr, float cfra)
|
float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra)
|
||||||
{
|
{
|
||||||
ParticleSettings *part = psys->part;
|
ParticleSettings *part = psys->part;
|
||||||
ChildParticle *cpa=psys->child+child_nbr;
|
|
||||||
|
|
||||||
if(part->childtype==PART_CHILD_FACES){
|
if(part->childtype==PART_CHILD_FACES){
|
||||||
float time;
|
float time;
|
||||||
@@ -2587,17 +2699,16 @@ float psys_get_child_time(ParticleSystem *psys, int child_nbr, float cfra)
|
|||||||
return (cfra-pa->time)/pa->lifetime;
|
return (cfra-pa->time)/pa->lifetime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float psys_get_child_size(ParticleSystem *psys, int child_nbr, float cfra, float *pa_time)
|
float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time)
|
||||||
{
|
{
|
||||||
ParticleSettings *part = psys->part;
|
ParticleSettings *part = psys->part;
|
||||||
ChildParticle *cpa = psys->child + child_nbr;
|
|
||||||
float size, time;
|
float size, time;
|
||||||
|
|
||||||
if(part->childtype==PART_CHILD_FACES){
|
if(part->childtype==PART_CHILD_FACES){
|
||||||
if(pa_time)
|
if(pa_time)
|
||||||
time=*pa_time;
|
time=*pa_time;
|
||||||
else
|
else
|
||||||
time=psys_get_child_time(psys,child_nbr,cfra);
|
time=psys_get_child_time(psys,cpa,cfra);
|
||||||
|
|
||||||
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
|
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
|
||||||
calc_ipo(part->ipo, 100*time);
|
calc_ipo(part->ipo, 100*time);
|
||||||
@@ -2645,9 +2756,6 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
|
|||||||
// edit=1;
|
// edit=1;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if(G.rendering==0 && part->flag & PART_CHILD_RENDER)
|
|
||||||
totchild=0;
|
|
||||||
|
|
||||||
/* user want's cubic interpolation but only without sb it possible */
|
/* user want's cubic interpolation but only without sb it possible */
|
||||||
//if(interpolation==PART_INTER_CUBIC && baked && psys->softflag==OB_SB_ENABLE)
|
//if(interpolation==PART_INTER_CUBIC && baked && psys->softflag==OB_SB_ENABLE)
|
||||||
// interpolation=PART_INTER_BSPLINE;
|
// interpolation=PART_INTER_BSPLINE;
|
||||||
@@ -2907,8 +3015,6 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey
|
|||||||
cfra=bsystem_time(0,(float)G.scene->r.cfra,0.0);
|
cfra=bsystem_time(0,(float)G.scene->r.cfra,0.0);
|
||||||
|
|
||||||
if(psys->totchild && p>=totpart){
|
if(psys->totchild && p>=totpart){
|
||||||
if(G.rendering==0 && part->flag&PART_CHILD_RENDER)
|
|
||||||
return 0;
|
|
||||||
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
|
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
|
||||||
between=1;
|
between=1;
|
||||||
}
|
}
|
||||||
@@ -2919,7 +3025,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey
|
|||||||
pa=psys->particles+p;
|
pa=psys->particles+p;
|
||||||
|
|
||||||
if(between){
|
if(between){
|
||||||
state->time = psys_get_child_time(psys,p-totpart,cfra);
|
state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra);
|
||||||
|
|
||||||
if(always==0)
|
if(always==0)
|
||||||
if((state->time<0.0 && (part->flag & PART_UNBORN)==0)
|
if((state->time<0.0 && (part->flag & PART_UNBORN)==0)
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
#include "BLI_kdtree.h"
|
#include "BLI_kdtree.h"
|
||||||
#include "BLI_linklist.h"
|
#include "BLI_linklist.h"
|
||||||
|
#include "BLI_threads.h"
|
||||||
|
|
||||||
#include "BKE_anim.h"
|
#include "BKE_anim.h"
|
||||||
#include "BKE_bad_level_calls.h"
|
#include "BKE_bad_level_calls.h"
|
||||||
@@ -106,7 +107,7 @@ static int get_current_display_percentage(ParticleSystem *psys)
|
|||||||
static void alloc_particles(ParticleSystem *psys, int new_totpart)
|
static void alloc_particles(ParticleSystem *psys, int new_totpart)
|
||||||
{
|
{
|
||||||
ParticleData *newpars = 0, *pa;
|
ParticleData *newpars = 0, *pa;
|
||||||
int i, totpart, totsaved = 0;
|
int i, child_nbr, totpart, totsaved = 0;
|
||||||
|
|
||||||
if(new_totpart<0){
|
if(new_totpart<0){
|
||||||
if(psys->part->distr==PART_DISTR_GRID){
|
if(psys->part->distr==PART_DISTR_GRID){
|
||||||
@@ -134,13 +135,14 @@ static void alloc_particles(ParticleSystem *psys, int new_totpart)
|
|||||||
}
|
}
|
||||||
psys->particles=newpars;
|
psys->particles=newpars;
|
||||||
|
|
||||||
if(psys->part->child_nbr && psys->part->childtype){
|
child_nbr= (G.rendering)? psys->part->ren_child_nbr: psys->part->child_nbr;
|
||||||
|
if(child_nbr && psys->part->childtype){
|
||||||
if(psys->child)
|
if(psys->child)
|
||||||
MEM_freeN(psys->child);
|
MEM_freeN(psys->child);
|
||||||
psys->child = NULL;
|
psys->child = NULL;
|
||||||
if(totpart)
|
if(totpart)
|
||||||
psys->child= MEM_callocN(totpart*psys->part->child_nbr*sizeof(ChildParticle), "child_particles");
|
psys->child= MEM_callocN(totpart*child_nbr*sizeof(ChildParticle), "child_particles");
|
||||||
psys->totchild=totpart*psys->part->child_nbr;
|
psys->totchild=totpart*child_nbr;
|
||||||
}
|
}
|
||||||
else if(psys->child){
|
else if(psys->child){
|
||||||
MEM_freeN(psys->child);
|
MEM_freeN(psys->child);
|
||||||
@@ -462,6 +464,297 @@ static int binary_search_distribution(float *sum, int n, float value)
|
|||||||
return low;
|
return low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* note: this function must be thread safe, for from == PART_FROM_CHILD */
|
||||||
|
#define ONLY_WORKING_WITH_PA_VERTS 0
|
||||||
|
void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p)
|
||||||
|
{
|
||||||
|
ParticleThreadContext *ctx= thread->ctx;
|
||||||
|
Object *ob= ctx->ob;
|
||||||
|
DerivedMesh *dm= ctx->dm;
|
||||||
|
ParticleData *tpars=0, *tpa;
|
||||||
|
ParticleSettings *part= ctx->psys->part;
|
||||||
|
float *v1, *v2, *v3, *v4, nor[3], co1[3], co2[3], nor1[3];
|
||||||
|
float cur_d, min_d;
|
||||||
|
int from= ctx->from;
|
||||||
|
int cfrom= ctx->cfrom;
|
||||||
|
int distr= ctx->distr;
|
||||||
|
int i, intersect, tot;
|
||||||
|
|
||||||
|
if(from == PART_FROM_VERT) {
|
||||||
|
/* TODO_PARTICLE - use original index */
|
||||||
|
pa->num= ctx->index[p];
|
||||||
|
pa->fuv[0] = 1.0f;
|
||||||
|
pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
|
||||||
|
//pa->verts[0] = pa->verts[1] = pa->verts[2] = 0;
|
||||||
|
|
||||||
|
#if ONLY_WORKING_WITH_PA_VERTS
|
||||||
|
if(ctx->tree){
|
||||||
|
KDTreeNearest ptn[3];
|
||||||
|
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);
|
||||||
|
maxw = BLI_kdtree_find_n_nearest(ctx->tree,3,co1,NULL,ptn);
|
||||||
|
|
||||||
|
for(w=0; w<maxw; w++){
|
||||||
|
pa->verts[w]=ptn->num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if(from == PART_FROM_FACE || from == PART_FROM_VOLUME) {
|
||||||
|
MFace *mface;
|
||||||
|
|
||||||
|
pa->num = i = ctx->index[p];
|
||||||
|
mface = dm->getFaceData(dm,i,CD_MFACE);
|
||||||
|
|
||||||
|
switch(distr){
|
||||||
|
case PART_DISTR_JIT:
|
||||||
|
ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel);
|
||||||
|
psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv);
|
||||||
|
ctx->jitoff[i]++;
|
||||||
|
//ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel);
|
||||||
|
break;
|
||||||
|
case PART_DISTR_RAND:
|
||||||
|
psys_uv_to_w(rng_getFloat(thread->rng), rng_getFloat(thread->rng), mface->v4, pa->fuv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pa->foffset= 0.0f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
pa->verts[0] = mface->v1;
|
||||||
|
pa->verts[1] = mface->v2;
|
||||||
|
pa->verts[2] = mface->v3;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* experimental */
|
||||||
|
if(from==PART_FROM_VOLUME){
|
||||||
|
MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
|
||||||
|
|
||||||
|
tot=dm->getNumFaces(dm);
|
||||||
|
|
||||||
|
psys_interpolate_face(mvert,mface,0,pa->fuv,co1,nor,0,0);
|
||||||
|
|
||||||
|
Normalize(nor);
|
||||||
|
VecMulf(nor,-100.0);
|
||||||
|
|
||||||
|
VECADD(co2,co1,nor);
|
||||||
|
|
||||||
|
min_d=2.0;
|
||||||
|
intersect=0;
|
||||||
|
|
||||||
|
for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){
|
||||||
|
if(i==pa->num) continue;
|
||||||
|
|
||||||
|
v1=mvert[mface->v1].co;
|
||||||
|
v2=mvert[mface->v2].co;
|
||||||
|
v3=mvert[mface->v3].co;
|
||||||
|
|
||||||
|
if(LineIntersectsTriangle(co1, co2, v2, v3, v1, &cur_d, 0)){
|
||||||
|
if(cur_d<min_d){
|
||||||
|
min_d=cur_d;
|
||||||
|
pa->foffset=cur_d*50.0f; /* to the middle of volume */
|
||||||
|
intersect=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mface->v4){
|
||||||
|
v4=mvert[mface->v4].co;
|
||||||
|
|
||||||
|
if(LineIntersectsTriangle(co1, co2, v4, v1, v3, &cur_d, 0)){
|
||||||
|
if(cur_d<min_d){
|
||||||
|
min_d=cur_d;
|
||||||
|
pa->foffset=cur_d*50.0f; /* to the middle of volume */
|
||||||
|
intersect=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(intersect==0)
|
||||||
|
pa->foffset=0.0;
|
||||||
|
else switch(distr){
|
||||||
|
case PART_DISTR_JIT:
|
||||||
|
pa->foffset*= ctx->jit[2*(int)ctx->jitoff[i]];
|
||||||
|
break;
|
||||||
|
case PART_DISTR_RAND:
|
||||||
|
pa->foffset*=BLI_frand();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(from == PART_FROM_PARTICLE) {
|
||||||
|
//pa->verts[0]=0; /* not applicable */
|
||||||
|
//pa->verts[1]=0;
|
||||||
|
//pa->verts[2]=0;
|
||||||
|
|
||||||
|
tpa=tpars+ctx->index[p];
|
||||||
|
pa->num=ctx->index[p];
|
||||||
|
pa->fuv[0]=tpa->fuv[0];
|
||||||
|
pa->fuv[1]=tpa->fuv[1];
|
||||||
|
/* abusing foffset a little for timing in near reaction */
|
||||||
|
pa->foffset=ctx->weight[ctx->index[p]];
|
||||||
|
ctx->weight[ctx->index[p]]+=ctx->maxweight;
|
||||||
|
}
|
||||||
|
else if(from == PART_FROM_CHILD) {
|
||||||
|
MFace *mf;
|
||||||
|
|
||||||
|
if(ctx->index[p] < 0) {
|
||||||
|
cpa->num=0;
|
||||||
|
cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f;
|
||||||
|
cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
|
||||||
|
cpa->rand[0]=cpa->rand[1]=cpa->rand[2]=0.0f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE);
|
||||||
|
|
||||||
|
//switch(distr){
|
||||||
|
// case PART_DISTR_JIT:
|
||||||
|
// i=index[p];
|
||||||
|
// psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mf->v4, cpa->fuv);
|
||||||
|
// ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel);
|
||||||
|
// break;
|
||||||
|
// case PART_DISTR_RAND:
|
||||||
|
psys_uv_to_w(rng_getFloat(thread->rng), rng_getFloat(thread->rng), mf->v4, cpa->fuv);
|
||||||
|
// break;
|
||||||
|
//}
|
||||||
|
|
||||||
|
cpa->rand[0] = rng_getFloat(thread->rng);
|
||||||
|
cpa->rand[1] = rng_getFloat(thread->rng);
|
||||||
|
cpa->rand[2] = rng_getFloat(thread->rng);
|
||||||
|
cpa->num = ctx->index[p];
|
||||||
|
|
||||||
|
if(ctx->tree){
|
||||||
|
KDTreeNearest ptn[10];
|
||||||
|
int w,maxw, do_seams;
|
||||||
|
float maxd,mind,dd,totw=0.0;
|
||||||
|
int parent[10];
|
||||||
|
float pweight[10];
|
||||||
|
|
||||||
|
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);
|
||||||
|
maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,co1,nor1,ptn);
|
||||||
|
|
||||||
|
maxd=ptn[maxw-1].dist;
|
||||||
|
mind=ptn[0].dist;
|
||||||
|
dd=maxd-mind;
|
||||||
|
|
||||||
|
/* the weights here could be done better */
|
||||||
|
for(w=0; w<maxw; w++){
|
||||||
|
parent[w]=ptn[w].index;
|
||||||
|
pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd));
|
||||||
|
//totw+=cpa->w[w];
|
||||||
|
}
|
||||||
|
for(;w<10; w++){
|
||||||
|
parent[w]=-1;
|
||||||
|
pweight[w]=0.0f;
|
||||||
|
}
|
||||||
|
if(do_seams){
|
||||||
|
ParticleSeam *seam=ctx->seams;
|
||||||
|
float temp[3],temp2[3],tan[3];
|
||||||
|
float inp,cur_len,min_len=10000.0f;
|
||||||
|
int min_seam=0, near_vert=0;
|
||||||
|
/* find closest seam */
|
||||||
|
for(i=0; i<ctx->totseam; i++, seam++){
|
||||||
|
VecSubf(temp,co1,seam->v0);
|
||||||
|
inp=Inpf(temp,seam->dir)/seam->length2;
|
||||||
|
if(inp<0.0f){
|
||||||
|
cur_len=VecLenf(co1,seam->v0);
|
||||||
|
}
|
||||||
|
else if(inp>1.0f){
|
||||||
|
cur_len=VecLenf(co1,seam->v1);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
VecCopyf(temp2,seam->dir);
|
||||||
|
VecMulf(temp2,inp);
|
||||||
|
cur_len=VecLenf(temp,temp2);
|
||||||
|
}
|
||||||
|
if(cur_len<min_len){
|
||||||
|
min_len=cur_len;
|
||||||
|
min_seam=i;
|
||||||
|
if(inp<0.0f) near_vert=-1;
|
||||||
|
else if(inp>1.0f) near_vert=1;
|
||||||
|
else near_vert=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seam=ctx->seams+min_seam;
|
||||||
|
|
||||||
|
VecCopyf(temp,seam->v0);
|
||||||
|
|
||||||
|
if(near_vert){
|
||||||
|
if(near_vert==-1)
|
||||||
|
VecSubf(tan,co1,seam->v0);
|
||||||
|
else{
|
||||||
|
VecSubf(tan,co1,seam->v1);
|
||||||
|
VecCopyf(temp,seam->v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Normalize(tan);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
VecCopyf(tan,seam->tan);
|
||||||
|
VecSubf(temp2,co1,temp);
|
||||||
|
if(Inpf(tan,temp2)<0.0f)
|
||||||
|
VecMulf(tan,-1.0f);
|
||||||
|
}
|
||||||
|
for(w=0; w<maxw; w++){
|
||||||
|
VecSubf(temp2,ptn[w].co,temp);
|
||||||
|
if(Inpf(tan,temp2)<0.0f){
|
||||||
|
parent[w]=-1;
|
||||||
|
pweight[w]=0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(w=0,i=0; w<maxw && i<4; w++){
|
||||||
|
if(parent[w]>=0){
|
||||||
|
cpa->pa[i]=parent[w];
|
||||||
|
cpa->w[i]=pweight[w];
|
||||||
|
totw+=pweight[w];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(;i<4; i++){
|
||||||
|
cpa->pa[i]=-1;
|
||||||
|
cpa->w[i]=0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(totw>0.0f) for(w=0; w<4; w++)
|
||||||
|
cpa->w[w]/=totw;
|
||||||
|
|
||||||
|
cpa->parent=cpa->pa[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *exec_distribution(void *data)
|
||||||
|
{
|
||||||
|
ParticleThread *thread= (ParticleThread*)data;
|
||||||
|
ParticleSystem *psys= thread->ctx->psys;
|
||||||
|
ParticleData *pa;
|
||||||
|
ChildParticle *cpa;
|
||||||
|
int p, totpart;
|
||||||
|
|
||||||
|
if(thread->ctx->from == PART_FROM_CHILD) {
|
||||||
|
totpart= psys->totchild;
|
||||||
|
cpa= psys->child + thread->num;
|
||||||
|
|
||||||
|
rng_skip(thread->rng, 5*thread->num);
|
||||||
|
for(p=thread->num; p<totpart; p+=thread->tot, cpa+=thread->tot) {
|
||||||
|
psys_thread_distribute_particle(thread, NULL, cpa, p);
|
||||||
|
rng_skip(thread->rng, 5*(thread->tot-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
totpart= psys->totpart;
|
||||||
|
pa= psys->particles + thread->num;
|
||||||
|
for(p=thread->num; p<totpart; p+=thread->tot, pa+=thread->tot)
|
||||||
|
psys_thread_distribute_particle(thread, pa, NULL, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* creates a distribution of coordinates on a DerivedMesh */
|
/* creates a distribution of coordinates on a DerivedMesh */
|
||||||
/* */
|
/* */
|
||||||
/* 1. lets check from what we are emitting */
|
/* 1. lets check from what we are emitting */
|
||||||
@@ -477,39 +770,39 @@ static int binary_search_distribution(float *sum, int n, float value)
|
|||||||
/* 6. and we're done! */
|
/* 6. and we're done! */
|
||||||
|
|
||||||
/* This is to denote functionality that does not yet work with mesh - only derived mesh */
|
/* This is to denote functionality that does not yet work with mesh - only derived mesh */
|
||||||
#define ONLY_WORKING_WITH_PA_VERTS 0
|
int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm, int from)
|
||||||
static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, ParticleSystem *psys, int from)
|
|
||||||
{
|
{
|
||||||
|
ParticleThreadContext *ctx= threads[0].ctx;
|
||||||
|
Object *ob= ctx->ob;
|
||||||
|
ParticleSystem *psys= ctx->psys;
|
||||||
Object *tob;
|
Object *tob;
|
||||||
ParticleData *pa=0, *tpars=0, *tpa;
|
ParticleData *pa=0, *tpars;
|
||||||
ParticleSettings *part;
|
ParticleSettings *part;
|
||||||
ParticleSystem *tpsys;
|
ParticleSystem *tpsys;
|
||||||
|
ParticleSeam *seams= 0;
|
||||||
ChildParticle *cpa=0;
|
ChildParticle *cpa=0;
|
||||||
KDTree *tree=0;
|
KDTree *tree=0;
|
||||||
ParticleSeam *seams=0;
|
DerivedMesh *dm= NULL;
|
||||||
float *jit= NULL;
|
float *jit= NULL;
|
||||||
int p=0,i;
|
int i, seed, p=0, totthread= threads[0].tot;
|
||||||
int no_distr=0, cfrom=0;
|
int no_distr=0, cfrom=0;
|
||||||
int tot=0, totpart, *index=0, children=0, totseam=0;
|
int tot=0, totpart, *index=0, children=0, totseam=0;
|
||||||
//int *vertpart=0;
|
//int *vertpart=0;
|
||||||
int jitlevel= 1, intersect, distr;
|
int jitlevel= 1, distr;
|
||||||
float *weight=0,*sum=0,*jitoff=0;
|
float *weight=0,*sum=0,*jitoff=0;
|
||||||
float cur, maxweight=0.0, tweight, totweight;
|
float cur, maxweight=0.0, tweight, totweight, co[3], nor[3];
|
||||||
float *v1, *v2, *v3, *v4, co[3], nor[3], co1[3], co2[3], nor1[3];
|
|
||||||
float cur_d, min_d;
|
|
||||||
DerivedMesh *dm= NULL;
|
|
||||||
|
|
||||||
if(ob==0 || psys==0 || psys->part==0)
|
if(ob==0 || psys==0 || psys->part==0)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
part=psys->part;
|
part=psys->part;
|
||||||
totpart=psys->totpart;
|
totpart=psys->totpart;
|
||||||
if(totpart==0)
|
if(totpart==0)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (!finaldm->deformedOnly && !CustomData_has_layer( &finaldm->faceData, CD_ORIGINDEX ) ) {
|
if (!finaldm->deformedOnly && !CustomData_has_layer( &finaldm->faceData, CD_ORIGINDEX ) ) {
|
||||||
error("Can't paint with the current modifier stack, disable destructive modifiers");
|
error("Can't paint with the current modifier stack, disable destructive modifiers");
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_srandom(31415926 + psys->seed);
|
BLI_srandom(31415926 + psys->seed);
|
||||||
@@ -579,7 +872,9 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
/* no need to figure out distribution */
|
/* no need to figure out distribution */
|
||||||
for(i=0; i<part->child_nbr; i++){
|
int child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr;
|
||||||
|
|
||||||
|
for(i=0; i<child_nbr; i++){
|
||||||
for(p=0; p<psys->totpart; p++,cpa++){
|
for(p=0; p<psys->totpart; p++,cpa++){
|
||||||
float length=2.0;
|
float length=2.0;
|
||||||
cpa->parent=p;
|
cpa->parent=p;
|
||||||
@@ -600,7 +895,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -610,7 +905,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl
|
|||||||
if(part->distr==PART_DISTR_GRID){
|
if(part->distr==PART_DISTR_GRID){
|
||||||
distribute_particles_in_grid(dm,psys);
|
distribute_particles_in_grid(dm,psys);
|
||||||
dm->release(dm);
|
dm->release(dm);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
distr=part->distr;
|
distr=part->distr;
|
||||||
@@ -674,7 +969,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(dm != finaldm) dm->release(dm);
|
if(dm != finaldm) dm->release(dm);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. */
|
/* 2. */
|
||||||
@@ -796,6 +1091,8 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MEM_freeN(sum);
|
||||||
|
|
||||||
/* weights are no longer used except for FROM_PARTICLE, which needs them zeroed for indexing */
|
/* weights are no longer used except for FROM_PARTICLE, which needs them zeroed for indexing */
|
||||||
if(from==PART_FROM_PARTICLE){
|
if(from==PART_FROM_PARTICLE){
|
||||||
for(i=0; i<tot; i++)
|
for(i=0; i<tot; i++)
|
||||||
@@ -820,277 +1117,71 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 5. */
|
/* 5. */
|
||||||
if(children) from=PART_FROM_CHILD;
|
if(children)
|
||||||
for(p=0,pa=psys->particles; p<totpart; p++,pa++,cpa++){
|
from=PART_FROM_CHILD;
|
||||||
switch(from){
|
|
||||||
case PART_FROM_VERT:
|
|
||||||
/* TODO_PARTICLE - use original index */
|
|
||||||
pa->num=index[p];
|
|
||||||
pa->fuv[0] = 1.0f;
|
|
||||||
pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
|
|
||||||
//pa->verts[0] = pa->verts[1] = pa->verts[2] = 0;
|
|
||||||
|
|
||||||
#if ONLY_WORKING_WITH_PA_VERTS
|
ctx->tree= tree;
|
||||||
if(tree){
|
ctx->seams= seams;
|
||||||
KDTreeNearest ptn[3];
|
ctx->totseam= totseam;
|
||||||
int w,maxw;
|
ctx->psys= psys;
|
||||||
|
ctx->index= index;
|
||||||
|
ctx->jit= jit;
|
||||||
|
ctx->jitlevel= jitlevel;
|
||||||
|
ctx->jitoff= jitoff;
|
||||||
|
ctx->weight= weight;
|
||||||
|
ctx->maxweight= maxweight;
|
||||||
|
ctx->from= from;
|
||||||
|
ctx->cfrom= cfrom;
|
||||||
|
ctx->distr= distr;
|
||||||
|
ctx->dm= dm;
|
||||||
|
|
||||||
psys_particle_on_dm(ob,dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0);
|
seed= 31415926 + ctx->psys->seed;
|
||||||
maxw = BLI_kdtree_find_n_nearest(tree,3,co1,NULL,ptn);
|
|
||||||
|
|
||||||
for(w=0; w<maxw; w++){
|
if(from!=PART_FROM_CHILD || psys->totchild < 10000)
|
||||||
pa->verts[w]=ptn->num;
|
totthread= 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case PART_FROM_FACE:
|
|
||||||
case PART_FROM_VOLUME:
|
|
||||||
{
|
|
||||||
MFace *mface;
|
|
||||||
pa->num = i = index[p];
|
|
||||||
mface = dm->getFaceData(dm,i,CD_MFACE);
|
|
||||||
|
|
||||||
switch(distr){
|
|
||||||
case PART_DISTR_JIT:
|
|
||||||
jitoff[i] = fmod(jitoff[i],(float)jitlevel);
|
|
||||||
psys_uv_to_w(jit[2*(int)jitoff[i]], jit[2*(int)jitoff[i]+1], mface->v4, pa->fuv);
|
|
||||||
jitoff[i]++;
|
|
||||||
//jitoff[i]=(float)fmod(jitoff[i]+maxweight/weight[i],(float)jitlevel);
|
|
||||||
break;
|
|
||||||
case PART_DISTR_RAND:
|
|
||||||
psys_uv_to_w(BLI_frand(), BLI_frand(), mface->v4, pa->fuv);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pa->foffset= 0.0f;
|
|
||||||
|
|
||||||
/*
|
|
||||||
pa->verts[0] = mface->v1;
|
|
||||||
pa->verts[1] = mface->v2;
|
|
||||||
pa->verts[2] = mface->v3;
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* experimental */
|
|
||||||
if(from==PART_FROM_VOLUME){
|
|
||||||
MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
|
|
||||||
|
|
||||||
tot=dm->getNumFaces(dm);
|
|
||||||
|
|
||||||
psys_interpolate_face(mvert,mface,0,pa->fuv,co1,nor,0,0);
|
|
||||||
|
|
||||||
Normalize(nor);
|
|
||||||
VecMulf(nor,-100.0);
|
|
||||||
|
|
||||||
VECADD(co2,co1,nor);
|
|
||||||
|
|
||||||
min_d=2.0;
|
|
||||||
intersect=0;
|
|
||||||
|
|
||||||
for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){
|
|
||||||
if(i==pa->num) continue;
|
|
||||||
|
|
||||||
v1=mvert[mface->v1].co;
|
|
||||||
v2=mvert[mface->v2].co;
|
|
||||||
v3=mvert[mface->v3].co;
|
|
||||||
|
|
||||||
if(LineIntersectsTriangle(co1, co2, v2, v3, v1, &cur_d, 0)){
|
|
||||||
if(cur_d<min_d){
|
|
||||||
min_d=cur_d;
|
|
||||||
pa->foffset=cur_d*50.0f; /* to the middle of volume */
|
|
||||||
intersect=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(mface->v4){
|
|
||||||
v4=mvert[mface->v4].co;
|
|
||||||
|
|
||||||
if(LineIntersectsTriangle(co1, co2, v4, v1, v3, &cur_d, 0)){
|
|
||||||
if(cur_d<min_d){
|
|
||||||
min_d=cur_d;
|
|
||||||
pa->foffset=cur_d*50.0f; /* to the middle of volume */
|
|
||||||
intersect=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(intersect==0)
|
|
||||||
pa->foffset=0.0;
|
|
||||||
else switch(distr){
|
|
||||||
case PART_DISTR_JIT:
|
|
||||||
pa->foffset*= jit[2*(int)jitoff[i]];
|
|
||||||
break;
|
|
||||||
case PART_DISTR_RAND:
|
|
||||||
pa->foffset*=BLI_frand();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PART_FROM_PARTICLE:
|
|
||||||
|
|
||||||
//pa->verts[0]=0; /* not applicable */
|
|
||||||
//pa->verts[1]=0;
|
|
||||||
//pa->verts[2]=0;
|
|
||||||
|
|
||||||
tpa=tpars+index[p];
|
|
||||||
pa->num=index[p];
|
|
||||||
pa->fuv[0]=tpa->fuv[0];
|
|
||||||
pa->fuv[1]=tpa->fuv[1];
|
|
||||||
/* abusing foffset a little for timing in near reaction */
|
|
||||||
pa->foffset=weight[index[p]];
|
|
||||||
weight[index[p]]+=maxweight;
|
|
||||||
break;
|
|
||||||
case PART_FROM_CHILD:
|
|
||||||
if(index[p]>=0){
|
|
||||||
MFace *mf;
|
|
||||||
|
|
||||||
mf=dm->getFaceData(dm,index[p],CD_MFACE);
|
|
||||||
|
|
||||||
//switch(distr){
|
|
||||||
// case PART_DISTR_JIT:
|
|
||||||
// i=index[p];
|
|
||||||
// psys_uv_to_w(jit[2*(int)jitoff[i]], jit[2*(int)jitoff[i]+1], mf->v4, cpa->fuv);
|
|
||||||
// jitoff[i]=(float)fmod(jitoff[i]+maxweight/weight[i],(float)jitlevel);
|
|
||||||
// break;
|
|
||||||
// case PART_DISTR_RAND:
|
|
||||||
psys_uv_to_w(BLI_frand(), BLI_frand(), mf->v4, cpa->fuv);
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
cpa->rand[0] = BLI_frand();
|
|
||||||
cpa->rand[1] = BLI_frand();
|
|
||||||
cpa->rand[2] = BLI_frand();
|
|
||||||
cpa->num = index[p];
|
|
||||||
|
|
||||||
if(tree){
|
|
||||||
KDTreeNearest ptn[10];
|
|
||||||
int w,maxw, do_seams;
|
|
||||||
float maxd,mind,dd,totw=0.0;
|
|
||||||
int parent[10];
|
|
||||||
float pweight[10];
|
|
||||||
|
|
||||||
do_seams= (part->flag&PART_CHILD_SEAMS && seams);
|
|
||||||
|
|
||||||
psys_particle_on_dm(ob,dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0);
|
|
||||||
maxw = BLI_kdtree_find_n_nearest(tree,(do_seams)?10:4,co1,nor1,ptn);
|
|
||||||
|
|
||||||
maxd=ptn[maxw-1].dist;
|
|
||||||
mind=ptn[0].dist;
|
|
||||||
dd=maxd-mind;
|
|
||||||
|
|
||||||
/* the weights here could be done better */
|
|
||||||
for(w=0; w<maxw; w++){
|
|
||||||
parent[w]=ptn[w].index;
|
|
||||||
pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd));
|
|
||||||
//totw+=cpa->w[w];
|
|
||||||
}
|
|
||||||
for(;w<10; w++){
|
|
||||||
parent[w]=-1;
|
|
||||||
pweight[w]=0.0f;
|
|
||||||
}
|
|
||||||
if(do_seams){
|
|
||||||
ParticleSeam *seam=seams;
|
|
||||||
float temp[3],temp2[3],tan[3];
|
|
||||||
float inp,cur_len,min_len=10000.0f;
|
|
||||||
int min_seam=0, near_vert=0;
|
|
||||||
/* find closest seam */
|
|
||||||
for(i=0; i<totseam; i++, seam++){
|
|
||||||
VecSubf(temp,co1,seam->v0);
|
|
||||||
inp=Inpf(temp,seam->dir)/seam->length2;
|
|
||||||
if(inp<0.0f){
|
|
||||||
cur_len=VecLenf(co1,seam->v0);
|
|
||||||
}
|
|
||||||
else if(inp>1.0f){
|
|
||||||
cur_len=VecLenf(co1,seam->v1);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
VecCopyf(temp2,seam->dir);
|
|
||||||
VecMulf(temp2,inp);
|
|
||||||
cur_len=VecLenf(temp,temp2);
|
|
||||||
}
|
|
||||||
if(cur_len<min_len){
|
|
||||||
min_len=cur_len;
|
|
||||||
min_seam=i;
|
|
||||||
if(inp<0.0f) near_vert=-1;
|
|
||||||
else if(inp>1.0f) near_vert=1;
|
|
||||||
else near_vert=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
seam=seams+min_seam;
|
|
||||||
|
|
||||||
VecCopyf(temp,seam->v0);
|
|
||||||
|
|
||||||
if(near_vert){
|
|
||||||
if(near_vert==-1)
|
|
||||||
VecSubf(tan,co1,seam->v0);
|
|
||||||
else{
|
|
||||||
VecSubf(tan,co1,seam->v1);
|
|
||||||
VecCopyf(temp,seam->v1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Normalize(tan);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
VecCopyf(tan,seam->tan);
|
|
||||||
VecSubf(temp2,co1,temp);
|
|
||||||
if(Inpf(tan,temp2)<0.0f)
|
|
||||||
VecMulf(tan,-1.0f);
|
|
||||||
}
|
|
||||||
for(w=0; w<maxw; w++){
|
|
||||||
VecSubf(temp2,ptn[w].co,temp);
|
|
||||||
if(Inpf(tan,temp2)<0.0f){
|
|
||||||
parent[w]=-1;
|
|
||||||
pweight[w]=0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for(w=0,i=0; w<maxw && i<4; w++){
|
|
||||||
if(parent[w]>=0){
|
|
||||||
cpa->pa[i]=parent[w];
|
|
||||||
cpa->w[i]=pweight[w];
|
|
||||||
totw+=pweight[w];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(;i<4; i++){
|
|
||||||
cpa->pa[i]=-1;
|
|
||||||
cpa->w[i]=0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(totw>0.0f) for(w=0; w<4; w++)
|
|
||||||
cpa->w[w]/=totw;
|
|
||||||
|
|
||||||
cpa->parent=cpa->pa[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
cpa->num=0;
|
|
||||||
cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f;
|
|
||||||
cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
|
|
||||||
cpa->rand[0]=cpa->rand[1]=cpa->rand[2]=0.0f;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 6. */
|
|
||||||
if(jit) MEM_freeN(jit);
|
|
||||||
if(sum) MEM_freeN(sum);
|
|
||||||
if(jitoff) MEM_freeN(jitoff);
|
|
||||||
if(weight){
|
|
||||||
MEM_freeN(weight);
|
|
||||||
weight=0;
|
|
||||||
}
|
|
||||||
if(index) MEM_freeN(index);
|
|
||||||
if(seams) MEM_freeN(seams);
|
|
||||||
//if(vertpart) MEM_freeN(vertpart);
|
|
||||||
BLI_kdtree_free(tree);
|
|
||||||
|
|
||||||
|
for(i=0; i<totthread; i++) {
|
||||||
|
threads[i].rng= rng_new(seed);
|
||||||
|
threads[i].tot= totthread;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, ParticleSystem *psys, int from)
|
||||||
|
{
|
||||||
|
ListBase threads;
|
||||||
|
ParticleThread *pthreads;
|
||||||
|
ParticleThreadContext *ctx;
|
||||||
|
int i, totthread;
|
||||||
|
|
||||||
|
pthreads= psys_threads_create(ob, psys, G.scene->r.threads);
|
||||||
|
|
||||||
|
if(!psys_threads_init_distribution(pthreads, finaldm, from)) {
|
||||||
|
psys_threads_free(pthreads);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
totthread= pthreads[0].tot;
|
||||||
|
if(totthread > 1) {
|
||||||
|
BLI_init_threads(&threads, exec_distribution, totthread);
|
||||||
|
|
||||||
|
for(i=0; i<totthread; i++)
|
||||||
|
BLI_insert_thread(&threads, &pthreads[i]);
|
||||||
|
|
||||||
|
BLI_end_threads(&threads);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
exec_distribution(&pthreads[0]);
|
||||||
|
|
||||||
if (from == PART_FROM_FACE)
|
if (from == PART_FROM_FACE)
|
||||||
psys_calc_dmfaces(ob, finaldm, psys);
|
psys_calc_dmfaces(ob, finaldm, psys);
|
||||||
|
|
||||||
if(dm != finaldm) dm->release(dm);
|
ctx= pthreads[0].ctx;
|
||||||
|
if(ctx->dm != finaldm)
|
||||||
|
ctx->dm->release(ctx->dm);
|
||||||
|
|
||||||
|
psys_threads_free(pthreads);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ready for future use, to emit particles without geometry */
|
/* ready for future use, to emit particles without geometry */
|
||||||
@@ -1135,6 +1226,79 @@ static void distribute_particles(Object *ob, ParticleSystem *psys, int from)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* threaded child particle distribution and path caching */
|
||||||
|
ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys, int totthread)
|
||||||
|
{
|
||||||
|
ParticleThread *threads;
|
||||||
|
ParticleThreadContext *ctx;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread");
|
||||||
|
ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext");
|
||||||
|
|
||||||
|
ctx->ob= ob;
|
||||||
|
ctx->psys= psys;
|
||||||
|
ctx->psmd= psys_get_modifier(ob, psys);
|
||||||
|
ctx->dm= ctx->psmd->dm;
|
||||||
|
ctx->ma= give_current_material(ob, psys->part->omat);
|
||||||
|
|
||||||
|
memset(threads, 0, sizeof(ParticleThread)*totthread);
|
||||||
|
|
||||||
|
for(i=0; i<totthread; i++) {
|
||||||
|
threads[i].ctx= ctx;
|
||||||
|
threads[i].num= i;
|
||||||
|
threads[i].tot= totthread;
|
||||||
|
}
|
||||||
|
|
||||||
|
return threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
void psys_threads_free(ParticleThread *threads)
|
||||||
|
{
|
||||||
|
ParticleThreadContext *ctx= threads[0].ctx;
|
||||||
|
int i, totthread= threads[0].tot;
|
||||||
|
|
||||||
|
/* path caching */
|
||||||
|
if(ctx->vg_length)
|
||||||
|
MEM_freeN(ctx->vg_length);
|
||||||
|
if(ctx->vg_clump)
|
||||||
|
MEM_freeN(ctx->vg_clump);
|
||||||
|
if(ctx->vg_kink)
|
||||||
|
MEM_freeN(ctx->vg_kink);
|
||||||
|
if(ctx->vg_rough1)
|
||||||
|
MEM_freeN(ctx->vg_rough1);
|
||||||
|
if(ctx->vg_rough2)
|
||||||
|
MEM_freeN(ctx->vg_roughe);
|
||||||
|
if(ctx->vg_roughe)
|
||||||
|
MEM_freeN(ctx->vg_roughe);
|
||||||
|
|
||||||
|
if(ctx->psys->lattice){
|
||||||
|
end_latt_deform();
|
||||||
|
ctx->psys->lattice=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* distribution */
|
||||||
|
if(ctx->jit) MEM_freeN(ctx->jit);
|
||||||
|
if(ctx->jitoff) MEM_freeN(ctx->jitoff);
|
||||||
|
if(ctx->weight) MEM_freeN(ctx->weight);
|
||||||
|
if(ctx->index) MEM_freeN(ctx->index);
|
||||||
|
if(ctx->seams) MEM_freeN(ctx->seams);
|
||||||
|
//if(ctx->vertpart) MEM_freeN(ctx->vertpart);
|
||||||
|
BLI_kdtree_free(ctx->tree);
|
||||||
|
|
||||||
|
/* threads */
|
||||||
|
for(i=0; i<totthread; i++) {
|
||||||
|
if(threads[i].rng)
|
||||||
|
rng_free(threads[i].rng);
|
||||||
|
if(threads[i].rng_path)
|
||||||
|
rng_free(threads[i].rng_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeN(ctx);
|
||||||
|
MEM_freeN(threads);
|
||||||
|
}
|
||||||
|
|
||||||
/* set particle parameters that don't change during particle's life */
|
/* set particle parameters that don't change during particle's life */
|
||||||
void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd)
|
void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd)
|
||||||
{
|
{
|
||||||
@@ -3980,8 +4144,9 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
|
|||||||
ParticleSettings *part=psys->part;
|
ParticleSettings *part=psys->part;
|
||||||
ParticleEditSettings *pset=&G.scene->toolsettings->particle;
|
ParticleEditSettings *pset=&G.scene->toolsettings->particle;
|
||||||
int distr=0,alloc=0;
|
int distr=0,alloc=0;
|
||||||
|
int child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr;
|
||||||
|
|
||||||
if((psys->part->childtype && psys->totchild != psys->totpart*part->child_nbr) || psys->recalc&PSYS_ALLOC)
|
if((psys->part->childtype && psys->totchild != psys->totpart*child_nbr) || psys->recalc&PSYS_ALLOC)
|
||||||
alloc=1;
|
alloc=1;
|
||||||
|
|
||||||
if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT)))
|
if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT)))
|
||||||
@@ -4003,9 +4168,9 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
|
|||||||
|| part->draw_as==PART_DRAW_PATH || part->draw&PART_DRAW_KEYS)){
|
|| part->draw_as==PART_DRAW_PATH || part->draw&PART_DRAW_KEYS)){
|
||||||
psys_cache_paths(ob, psys, cfra, 0);
|
psys_cache_paths(ob, psys, cfra, 0);
|
||||||
|
|
||||||
if(part->childtype){
|
/* for render, child particle paths are computed on the fly */
|
||||||
if((G.rendering || (part->flag&PART_CHILD_RENDER)==0)
|
if(part->childtype) {
|
||||||
|| (psys_in_edit_mode(psys) && (pset->flag&PE_SHOW_CHILD)))
|
if(((psys->totchild!=0)) || (psys_in_edit_mode(psys) && (pset->flag&PE_SHOW_CHILD)))
|
||||||
psys_cache_child_paths(ob, psys, cfra, 0);
|
psys_cache_child_paths(ob, psys, cfra, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4133,6 +4298,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
|
|||||||
int totpart,oldtotpart=0,p;
|
int totpart,oldtotpart=0,p;
|
||||||
float disp, *vg_vel=0, *vg_tan=0, *vg_rot=0, *vg_size=0;
|
float disp, *vg_vel=0, *vg_tan=0, *vg_rot=0, *vg_size=0;
|
||||||
int init=0,distr=0,alloc=0;
|
int init=0,distr=0,alloc=0;
|
||||||
|
int child_nbr;
|
||||||
|
|
||||||
/*----start validity checks----*/
|
/*----start validity checks----*/
|
||||||
|
|
||||||
@@ -4197,7 +4363,8 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
|
|||||||
else
|
else
|
||||||
totpart = psys->part->totpart;
|
totpart = psys->part->totpart;
|
||||||
|
|
||||||
if(oldtotpart != totpart || psys->recalc&PSYS_ALLOC || (psys->part->childtype && psys->totchild != psys->totpart*part->child_nbr))
|
child_nbr= (G.rendering)? 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;
|
alloc = 1;
|
||||||
|
|
||||||
if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT) && ob==OBACT))
|
if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT) && ob==OBACT))
|
||||||
@@ -4368,7 +4535,7 @@ void particle_system_update(Object *ob, ParticleSystem *psys){
|
|||||||
if(psys->softflag&OB_SB_ENABLE)
|
if(psys->softflag&OB_SB_ENABLE)
|
||||||
psys_to_softbody(ob,psys,1);
|
psys_to_softbody(ob,psys,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
system_step(ob,psys,psmd,cfra);
|
system_step(ob,psys,psmd,cfra);
|
||||||
|
|
||||||
Mat4CpyMat4(psys->imat, ob->imat); /* used for duplicators */
|
Mat4CpyMat4(psys->imat, ob->imat); /* used for duplicators */
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ double rng_getDouble (struct RNG* rng);
|
|||||||
float rng_getFloat (struct RNG* rng);
|
float rng_getFloat (struct RNG* rng);
|
||||||
void rng_shuffleArray(struct RNG *rng, void *data, int elemSize, int numElems);
|
void rng_shuffleArray(struct RNG *rng, void *data, int elemSize, int numElems);
|
||||||
|
|
||||||
|
/** Note that skipping is as slow as generating n numbers! */
|
||||||
|
void rng_skip (struct RNG *rng, int n);
|
||||||
|
|
||||||
/** Seed the random number generator */
|
/** Seed the random number generator */
|
||||||
void BLI_srand (unsigned int seed);
|
void BLI_srand (unsigned int seed);
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,14 @@ void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems)
|
|||||||
free(temp);
|
free(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rng_skip(RNG *rng, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
rng_getInt(rng);
|
||||||
|
}
|
||||||
|
|
||||||
/***/
|
/***/
|
||||||
|
|
||||||
static RNG theBLI_rng = {0};
|
static RNG theBLI_rng = {0};
|
||||||
|
|||||||
@@ -6671,6 +6671,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
Image *ima;
|
Image *ima;
|
||||||
Lamp *la;
|
Lamp *la;
|
||||||
Material *ma;
|
Material *ma;
|
||||||
|
ParticleSettings *part;
|
||||||
|
|
||||||
/* unless the file was created 2.44.3 but not 2.45, update the constraints */
|
/* unless the file was created 2.44.3 but not 2.45, update the constraints */
|
||||||
if ( !(main->versionfile==244 && main->subversionfile==3) &&
|
if ( !(main->versionfile==244 && main->subversionfile==3) &&
|
||||||
@@ -6833,7 +6834,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
|
ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(part=main->particle.first; part; part=part->id.next)
|
||||||
|
if(part->ren_child_nbr==0)
|
||||||
|
part->ren_child_nbr= part->child_nbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) {
|
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) {
|
||||||
@@ -7075,7 +7079,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
|
|
||||||
/* convert settings from old particle system */
|
/* convert settings from old particle system */
|
||||||
/* general settings */
|
/* general settings */
|
||||||
part->totpart = paf->totpart;
|
part->totpart = MIN2(paf->totpart, 100000);
|
||||||
part->sta = paf->sta;
|
part->sta = paf->sta;
|
||||||
part->end = paf->end;
|
part->end = paf->end;
|
||||||
part->lifetime = paf->lifetime;
|
part->lifetime = paf->lifetime;
|
||||||
@@ -7149,7 +7153,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(sce= main->scene.first; sce; sce=sce->id.next) {
|
for(sce= main->scene.first; sce; sce=sce->id.next) {
|
||||||
ParticleEditSettings *pset= &sce->toolsettings->particle;
|
ParticleEditSettings *pset= &sce->toolsettings->particle;
|
||||||
int a;
|
int a;
|
||||||
@@ -7184,11 +7187,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
|
|
||||||
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 10)) {
|
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 10)) {
|
||||||
Object *ob;
|
Object *ob;
|
||||||
/* dupliface scale */
|
|
||||||
for(ob= main->object.first; ob; ob= ob->id.next) {
|
|
||||||
ob->dupfacesca = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* dupliface scale */
|
||||||
|
for(ob= main->object.first; ob; ob= ob->id.next)
|
||||||
|
ob->dupfacesca = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ void PE_create_particle_edit(struct Object *ob, struct ParticleSystem *psys);
|
|||||||
void PE_free_particle_edit(struct ParticleSystem *psys);
|
void PE_free_particle_edit(struct ParticleSystem *psys);
|
||||||
|
|
||||||
void PE_change_act(void *ob_v, void *act_v);
|
void PE_change_act(void *ob_v, void *act_v);
|
||||||
|
int PE_can_edit(struct ParticleSystem *psys);
|
||||||
|
|
||||||
/* access */
|
/* access */
|
||||||
struct ParticleSystem *PE_get_current(struct Object *ob);
|
struct ParticleSystem *PE_get_current(struct Object *ob);
|
||||||
|
|||||||
@@ -84,11 +84,11 @@ typedef struct Material {
|
|||||||
int mode, mode_l; /* mode_l is the or-ed result of all layer modes */
|
int mode, mode_l; /* mode_l is the or-ed result of all layer modes */
|
||||||
short flarec, starc, linec, ringc;
|
short flarec, starc, linec, ringc;
|
||||||
float hasize, flaresize, subsize, flareboost;
|
float hasize, flaresize, subsize, flareboost;
|
||||||
float strand_sta, strand_end, strand_ease;
|
float strand_sta, strand_end, strand_ease, strand_surfnor;
|
||||||
char strand_uvname[32];
|
char strand_uvname[32];
|
||||||
|
|
||||||
float sbias; /* shadow bias */
|
float sbias; /* shadow bias */
|
||||||
float shad_alpha, padf; /* in use for irregular shadowbuffer */
|
float shad_alpha; /* in use for irregular shadowbuffer */
|
||||||
|
|
||||||
/* for buttons and render*/
|
/* for buttons and render*/
|
||||||
char rgbsel, texact, pr_type, use_nodes;
|
char rgbsel, texact, pr_type, use_nodes;
|
||||||
@@ -121,6 +121,7 @@ typedef struct Material {
|
|||||||
float fhdist, xyfrict;
|
float fhdist, xyfrict;
|
||||||
short dynamode, pad2;
|
short dynamode, pad2;
|
||||||
|
|
||||||
|
/* subsurface scattering */
|
||||||
float sss_radius[3], sss_col[3];
|
float sss_radius[3], sss_col[3];
|
||||||
float sss_error, sss_scale, sss_ior;
|
float sss_error, sss_scale, sss_ior;
|
||||||
float sss_colfac, sss_texfac;
|
float sss_colfac, sss_texfac;
|
||||||
@@ -191,6 +192,7 @@ typedef struct Material {
|
|||||||
#define MA_GROUP_NOLAY 0x10000000
|
#define MA_GROUP_NOLAY 0x10000000
|
||||||
#define MA_FACETEXTURE_ALPHA 0x20000000
|
#define MA_FACETEXTURE_ALPHA 0x20000000
|
||||||
#define MA_STR_B_UNITS 0x40000000
|
#define MA_STR_B_UNITS 0x40000000
|
||||||
|
#define MA_STR_SURFDIFF 0x80000000
|
||||||
|
|
||||||
#define MA_MODE_MASK 0x4fffffff /* all valid mode bits */
|
#define MA_MODE_MASK 0x4fffffff /* all valid mode bits */
|
||||||
|
|
||||||
|
|||||||
@@ -134,9 +134,9 @@ typedef struct ParticleSettings {
|
|||||||
/* global physical properties */
|
/* global physical properties */
|
||||||
float acc[3], dragfac, brownfac, dampfac;
|
float acc[3], dragfac, brownfac, dampfac;
|
||||||
/* length */
|
/* length */
|
||||||
float length, abslength, randlength;
|
float length, abslength, randlength, pad;
|
||||||
/* children */
|
/* children */
|
||||||
int child_nbr;
|
int child_nbr, ren_child_nbr;
|
||||||
float parents, childsize, childrandsize;
|
float parents, childsize, childrandsize;
|
||||||
float childrad, childflat, childspread;
|
float childrad, childflat, childspread;
|
||||||
/* clumping */
|
/* clumping */
|
||||||
@@ -204,7 +204,7 @@ typedef struct ParticleSystem{
|
|||||||
/* no special why's, just seem reasonable */
|
/* no special why's, just seem reasonable */
|
||||||
/* changing these (atleast upwards) should not cause any major problems */
|
/* changing these (atleast upwards) should not cause any major problems */
|
||||||
#define MAX_PARTS 100000 /* real particles/system */
|
#define MAX_PARTS 100000 /* real particles/system */
|
||||||
#define MAX_PART_CHILDREN 1000 /* child particles/real particles */
|
#define MAX_PART_CHILDREN 10000 /* child particles/real particles */
|
||||||
#define MAX_BOIDNEIGHBOURS 10 /* neigbours considered/boid */
|
#define MAX_BOIDNEIGHBOURS 10 /* neigbours considered/boid */
|
||||||
|
|
||||||
/* part->type */
|
/* part->type */
|
||||||
@@ -299,9 +299,10 @@ typedef struct ParticleSystem{
|
|||||||
#define PART_DRAW_NUM 512
|
#define PART_DRAW_NUM 512
|
||||||
#define PART_DRAW_RAND_GR 1024
|
#define PART_DRAW_RAND_GR 1024
|
||||||
#define PART_DRAW_REN_ADAPT 2048
|
#define PART_DRAW_REN_ADAPT 2048
|
||||||
#define PART_DRAW_VEL_LENGTH (1<<12)
|
#define PART_DRAW_VEL_LENGTH (1<<12)
|
||||||
#define PART_DRAW_MAT_COL (1<<13)
|
#define PART_DRAW_MAT_COL (1<<13)
|
||||||
#define PART_DRAW_WHOLE_GR (1<<14)
|
#define PART_DRAW_WHOLE_GR (1<<14)
|
||||||
|
#define PART_DRAW_REN_STRAND (1<<15)
|
||||||
|
|
||||||
/* part->bb_align */
|
/* part->bb_align */
|
||||||
#define PART_BB_X 0
|
#define PART_BB_X 0
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ typedef struct RenderLayer {
|
|||||||
|
|
||||||
float *rectf; /* 4 float, standard rgba buffer (read not above!) */
|
float *rectf; /* 4 float, standard rgba buffer (read not above!) */
|
||||||
float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */
|
float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */
|
||||||
|
float *scolrect; /* 4 float, optional strand buffer, needs storage for display updates */
|
||||||
|
|
||||||
ListBase passes;
|
ListBase passes;
|
||||||
|
|
||||||
@@ -121,7 +122,7 @@ typedef struct RenderResult {
|
|||||||
} RenderResult;
|
} RenderResult;
|
||||||
|
|
||||||
typedef struct RenderStats {
|
typedef struct RenderStats {
|
||||||
int totface, totvert, tothalo, totlamp, totpart;
|
int totface, totvert, totstrand, tothalo, totlamp, totpart;
|
||||||
short curfield, curblur, curpart, partsdone, convertdone;
|
short curfield, curblur, curpart, partsdone, convertdone;
|
||||||
double starttime, lastframetime;
|
double starttime, lastframetime;
|
||||||
char *infostr;
|
char *infostr;
|
||||||
|
|||||||
@@ -154,6 +154,8 @@ typedef struct ShadeInput
|
|||||||
/* stored copy of original face normal (facenor)
|
/* stored copy of original face normal (facenor)
|
||||||
* before flipping. Used in Front/back output on geometry node */
|
* before flipping. Used in Front/back output on geometry node */
|
||||||
float orignor[3];
|
float orignor[3];
|
||||||
|
/* for strand shading, normal at the surface */
|
||||||
|
float surfnor[3], surfdist;
|
||||||
|
|
||||||
/* from initialize, part or renderlayer */
|
/* from initialize, part or renderlayer */
|
||||||
short do_preview; /* for nodes, in previewrender */
|
short do_preview; /* for nodes, in previewrender */
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ struct MemArena;
|
|||||||
struct VertTableNode;
|
struct VertTableNode;
|
||||||
struct VlakTableNode;
|
struct VlakTableNode;
|
||||||
struct GHash;
|
struct GHash;
|
||||||
|
struct RenderBuckets;
|
||||||
|
|
||||||
#define TABLEINITSIZE 1024
|
#define TABLEINITSIZE 1024
|
||||||
#define LAMPINITSIZE 256
|
#define LAMPINITSIZE 256
|
||||||
@@ -159,7 +160,7 @@ struct Render
|
|||||||
float cfra;
|
float cfra;
|
||||||
|
|
||||||
/* render database */
|
/* render database */
|
||||||
int totvlak, totvert, tothalo, totlamp;
|
int totvlak, totvert, tothalo, totstrand, totlamp;
|
||||||
ListBase lights; /* GroupObject pointers */
|
ListBase lights; /* GroupObject pointers */
|
||||||
ListBase lampren; /* storage, for free */
|
ListBase lampren; /* storage, for free */
|
||||||
|
|
||||||
@@ -167,9 +168,13 @@ struct Render
|
|||||||
struct VertTableNode *vertnodes;
|
struct VertTableNode *vertnodes;
|
||||||
int vlaknodeslen;
|
int vlaknodeslen;
|
||||||
struct VlakTableNode *vlaknodes;
|
struct VlakTableNode *vlaknodes;
|
||||||
|
int strandnodeslen;
|
||||||
|
struct StrandTableNode *strandnodes;
|
||||||
int blohalen;
|
int blohalen;
|
||||||
struct HaloRen **bloha;
|
struct HaloRen **bloha;
|
||||||
ListBase objecttable;
|
ListBase objecttable;
|
||||||
|
ListBase strandbufs;
|
||||||
|
struct RenderBuckets *strandbuckets;
|
||||||
|
|
||||||
struct Image *backbuf, *bakebuf;
|
struct Image *backbuf, *bakebuf;
|
||||||
|
|
||||||
@@ -234,7 +239,7 @@ typedef struct ShadBuf {
|
|||||||
typedef struct ObjectRen {
|
typedef struct ObjectRen {
|
||||||
struct ObjectRen *next, *prev;
|
struct ObjectRen *next, *prev;
|
||||||
struct Object *ob, *par;
|
struct Object *ob, *par;
|
||||||
int index, startvert, endvert, startface, endface;
|
int index, startvert, endvert, startface, endface, startstrand, endstrand;
|
||||||
float *vectors;
|
float *vectors;
|
||||||
} ObjectRen;
|
} ObjectRen;
|
||||||
|
|
||||||
@@ -297,6 +302,36 @@ typedef struct HaloRen
|
|||||||
struct Material *mat;
|
struct Material *mat;
|
||||||
} HaloRen;
|
} HaloRen;
|
||||||
|
|
||||||
|
typedef struct StrandVert {
|
||||||
|
float co[3];
|
||||||
|
float strandco;
|
||||||
|
} StrandVert;
|
||||||
|
|
||||||
|
typedef struct StrandBuffer {
|
||||||
|
struct StrandBuffer *next, *prev;
|
||||||
|
struct StrandVert *vert;
|
||||||
|
int totvert;
|
||||||
|
|
||||||
|
struct Object *ob;
|
||||||
|
struct Material *ma;
|
||||||
|
unsigned int lay;
|
||||||
|
int overrideuv;
|
||||||
|
int flag, maxdepth;
|
||||||
|
float adaptcos;
|
||||||
|
|
||||||
|
float winmat[4][4];
|
||||||
|
int winx, winy;
|
||||||
|
} StrandBuffer;
|
||||||
|
|
||||||
|
typedef struct StrandRen {
|
||||||
|
StrandVert *vert;
|
||||||
|
StrandBuffer *buffer;
|
||||||
|
int totvert, flag;
|
||||||
|
int clip, index;
|
||||||
|
float orco[3];
|
||||||
|
} StrandRen;
|
||||||
|
|
||||||
|
|
||||||
struct LampRen;
|
struct LampRen;
|
||||||
struct MTex;
|
struct MTex;
|
||||||
|
|
||||||
@@ -417,6 +452,9 @@ typedef struct LampRen {
|
|||||||
#define R_SNPROJ_Z 4
|
#define R_SNPROJ_Z 4
|
||||||
#define R_FLIPPED_NO 8
|
#define R_FLIPPED_NO 8
|
||||||
|
|
||||||
|
/* strandbuffer->flag */
|
||||||
|
#define R_STRAND_BSPLINE 1
|
||||||
|
#define R_STRAND_B_UNITS 2
|
||||||
|
|
||||||
|
|
||||||
#endif /* RENDER_TYPES_H */
|
#endif /* RENDER_TYPES_H */
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ struct Render;
|
|||||||
struct MCol;
|
struct MCol;
|
||||||
struct MTFace;
|
struct MTFace;
|
||||||
struct CustomData;
|
struct CustomData;
|
||||||
|
struct StrandBuffer;
|
||||||
|
struct StrandRen;
|
||||||
|
|
||||||
#define RE_QUAD_MASK 0x7FFFFFF
|
#define RE_QUAD_MASK 0x7FFFFFF
|
||||||
#define RE_QUAD_OFFS 0x8000000
|
#define RE_QUAD_OFFS 0x8000000
|
||||||
@@ -59,9 +61,20 @@ typedef struct VlakTableNode {
|
|||||||
struct MTFace **mtface;
|
struct MTFace **mtface;
|
||||||
struct MCol **mcol;
|
struct MCol **mcol;
|
||||||
int totmtface, totmcol;
|
int totmtface, totmcol;
|
||||||
|
float *surfnor;
|
||||||
struct CustomDataNames **names;
|
struct CustomDataNames **names;
|
||||||
} VlakTableNode;
|
} VlakTableNode;
|
||||||
|
|
||||||
|
typedef struct StrandTableNode {
|
||||||
|
struct StrandRen *strand;
|
||||||
|
float *winspeed;
|
||||||
|
float *surfnor;
|
||||||
|
struct MCol **mcol;
|
||||||
|
float **uv;
|
||||||
|
int totuv, totmcol;
|
||||||
|
struct CustomDataNames **names;
|
||||||
|
} StrandTableNode;
|
||||||
|
|
||||||
typedef struct CustomDataNames{
|
typedef struct CustomDataNames{
|
||||||
struct CustomDataNames *next, *prev;
|
struct CustomDataNames *next, *prev;
|
||||||
|
|
||||||
@@ -75,18 +88,20 @@ void free_renderdata_vertnodes(struct VertTableNode *vertnodes);
|
|||||||
void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes);
|
void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes);
|
||||||
|
|
||||||
void set_normalflags(Render *re);
|
void set_normalflags(Render *re);
|
||||||
void project_renderdata(struct Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs);
|
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 */
|
/* functions are not exported... so wrong names */
|
||||||
|
|
||||||
struct VlakRen *RE_findOrAddVlak(struct Render *re, int nr);
|
struct VlakRen *RE_findOrAddVlak(struct Render *re, int nr);
|
||||||
struct VertRen *RE_findOrAddVert(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_findOrAddHalo(struct Render *re, int nr);
|
||||||
struct HaloRen *RE_inithalo(struct Render *re, struct Material *ma, float *vec, float *vec1, float *orco, float hasize,
|
struct HaloRen *RE_inithalo(struct Render *re, struct Material *ma, float *vec, float *vec1, float *orco, float hasize,
|
||||||
float vectsize, int seed);
|
float vectsize, int seed);
|
||||||
struct HaloRen *RE_inithalo_particle(struct Render *re, struct DerivedMesh *dm, struct Material *ma, float *vec, float *vec1,
|
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);
|
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);
|
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);
|
||||||
|
|
||||||
float *RE_vertren_get_sticky(struct Render *re, struct VertRen *ver, int verify);
|
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_stress(struct Render *re, struct VertRen *ver, int verify);
|
||||||
@@ -97,6 +112,12 @@ float *RE_vertren_get_winspeed(struct Render *re, struct VertRen *ver, int verif
|
|||||||
|
|
||||||
struct MTFace *RE_vlakren_get_tface(struct Render *re, VlakRen *ren, int n, char **name, int verify);
|
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);
|
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_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 VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver);
|
struct VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver);
|
||||||
struct VlakRen *RE_vlakren_copy(struct Render *re, struct VlakRen *vlr);
|
struct VlakRen *RE_vlakren_copy(struct Render *re, struct VlakRen *vlr);
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ struct RenderPart;
|
|||||||
struct RenderLayer;
|
struct RenderLayer;
|
||||||
struct PixStr;
|
struct PixStr;
|
||||||
struct LampRen;
|
struct LampRen;
|
||||||
|
struct VlakRen;
|
||||||
|
struct StrandSegment;
|
||||||
|
struct StrandPoint;
|
||||||
|
|
||||||
/* shadeinput.c */
|
/* shadeinput.c */
|
||||||
|
|
||||||
@@ -56,6 +59,8 @@ 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_uv(struct ShadeInput *shi);
|
||||||
void shade_input_set_normals(struct ShadeInput *shi);
|
void shade_input_set_normals(struct ShadeInput *shi);
|
||||||
void shade_input_set_shade_texco(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);
|
||||||
void shade_input_do_shade(struct ShadeInput *shi, struct ShadeResult *shr);
|
void shade_input_do_shade(struct ShadeInput *shi, struct ShadeResult *shr);
|
||||||
|
|
||||||
void shade_input_initialize(struct ShadeInput *shi, struct RenderPart *pa, struct RenderLayer *rl, int sample);
|
void shade_input_initialize(struct ShadeInput *shi, struct RenderPart *pa, struct RenderLayer *rl, int sample);
|
||||||
|
|||||||
192
source/blender/render/intern/include/strand.h
Normal file
192
source/blender/render/intern/include/strand.h
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* $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 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 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
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@ 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_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_solid(struct RenderPart *pa, unsigned int layer, short layflag);
|
||||||
unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass);
|
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 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));
|
||||||
|
|
||||||
|
|||||||
@@ -1212,12 +1212,10 @@ static void render_particle_system(Render *re, Object *ob, Object *par, PartEff
|
|||||||
if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore...
|
if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore...
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* future thread problem... */
|
/* future thread problem... */
|
||||||
static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *uvco, int totuv,
|
static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *surfnor,
|
||||||
float *vec, float *vec1, float ctime, int first, int line,
|
float *uvco, int totuv, float *vec, float *vec1, float ctime,
|
||||||
int adapt, float adapt_angle, float adapt_pix, int override_uv)
|
int first, int line, int adapt, float adapt_angle, float adapt_pix, int override_uv)
|
||||||
{
|
{
|
||||||
static VertRen *v1= NULL, *v2= NULL;
|
static VertRen *v1= NULL, *v2= NULL;
|
||||||
VlakRen *vlr;
|
VlakRen *vlr;
|
||||||
@@ -1314,6 +1312,11 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
|
|||||||
vlr->ec= ME_V2V3;
|
vlr->ec= ME_V2V3;
|
||||||
vlr->lay= ob->lay;
|
vlr->lay= ob->lay;
|
||||||
|
|
||||||
|
if(surfnor) {
|
||||||
|
float *snor= RE_vlakren_get_surfnor(re, vlr, 1);
|
||||||
|
VECCOPY(snor, surfnor);
|
||||||
|
}
|
||||||
|
|
||||||
if(uvco){
|
if(uvco){
|
||||||
for(i=0; i<totuv; i++){
|
for(i=0; i<totuv; i++){
|
||||||
MTFace *mtf;
|
MTFace *mtf;
|
||||||
@@ -1428,6 +1431,11 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
|
|||||||
vlr->ec= ME_V2V3;
|
vlr->ec= ME_V2V3;
|
||||||
vlr->lay= ob->lay;
|
vlr->lay= ob->lay;
|
||||||
|
|
||||||
|
if(surfnor) {
|
||||||
|
float *snor= RE_vlakren_get_surfnor(re, vlr, 1);
|
||||||
|
VECCOPY(snor, surfnor);
|
||||||
|
}
|
||||||
|
|
||||||
if(uvco){
|
if(uvco){
|
||||||
for(i=0; i<totuv; i++){
|
for(i=0; i<totuv; i++){
|
||||||
MTFace *mtf;
|
MTFace *mtf;
|
||||||
@@ -1683,7 +1691,7 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Material *ma, int path, int first, int line,
|
static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Material *ma, int path, int first, int line,
|
||||||
float time, float *loc, float *loc1, float *orco, int totuv, float *uvco,
|
float time, float *loc, float *loc1, float *orco, float *surfnor, int totuv, float *uvco,
|
||||||
float size, int seed, int override_uv, int adapt, float adapt_angle, float adapt_pix)
|
float size, int seed, int override_uv, int adapt, float adapt_angle, float adapt_pix)
|
||||||
{
|
{
|
||||||
HaloRen *har=0;
|
HaloRen *har=0;
|
||||||
@@ -1695,7 +1703,7 @@ static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Materia
|
|||||||
if(har) har->lay= ob->lay;
|
if(har) har->lay= ob->lay;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
static_particle_strand(re, ob, ma, orco, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv);
|
static_particle_strand(re, ob, ma, orco, surfnor, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
har= RE_inithalo_particle(re, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed);
|
har= RE_inithalo_particle(re, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed);
|
||||||
@@ -1715,8 +1723,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
ParticleKey *states=0;
|
ParticleKey *states=0;
|
||||||
ParticleKey state;
|
ParticleKey state;
|
||||||
ParticleCacheKey *cache=0;
|
ParticleCacheKey *cache=0;
|
||||||
float loc[3],loc1[3],loc0[3],vel[3],imat[4][4], time;
|
StrandBuffer *strandbuf=0;
|
||||||
float *orco=0,*uvco=0;
|
StrandVert *svert=0;
|
||||||
|
StrandRen *strand=0;
|
||||||
|
RNG *rng= 0;
|
||||||
|
float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],ornor[3],time;
|
||||||
|
float *orco=0,*surfnor=0,*uvco=0;
|
||||||
float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0);
|
float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0);
|
||||||
float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random;
|
float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random;
|
||||||
int i, a, k, max_k=0, totpart, totvlako, totverto, totuv=0, override_uv=-1;
|
int i, a, k, max_k=0, totpart, totvlako, totverto, totuv=0, override_uv=-1;
|
||||||
@@ -1750,15 +1762,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(G.rendering == 0) { /* preview render */
|
if(G.rendering == 0) { /* preview render */
|
||||||
if(part->flag & PART_CHILD_RENDER)
|
totchild = (int)((float)totchild * (float)part->disp / 100.0f);
|
||||||
totchild = 0;
|
|
||||||
else
|
|
||||||
totchild = (int)((float)totchild * (float)part->disp / 100.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
psys->flag|=PSYS_DRAWING;
|
psys->flag|=PSYS_DRAWING;
|
||||||
|
|
||||||
BLI_srandom(psys->seed);
|
rng= rng_new(psys->seed);
|
||||||
|
|
||||||
ma= give_render_material(re, ob, part->omat);
|
ma= give_render_material(re, ob, part->omat);
|
||||||
|
|
||||||
@@ -1773,9 +1782,15 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
RE_vlakren_set_customdata_names(re, &psmd->dm->faceData);
|
RE_vlakren_set_customdata_names(re, &psmd->dm->faceData);
|
||||||
totuv=CustomData_number_of_layers(&psmd->dm->faceData,CD_MTFACE);
|
totuv=CustomData_number_of_layers(&psmd->dm->faceData,CD_MTFACE);
|
||||||
|
|
||||||
if(ma->texco & TEXCO_UV && totuv)
|
if(ma->texco & TEXCO_UV && totuv) {
|
||||||
uvco = MEM_callocN(totuv*2*sizeof(float),"particle_uvs");
|
uvco = MEM_callocN(totuv*2*sizeof(float),"particle_uvs");
|
||||||
|
|
||||||
|
if(ma->strand_uvname[0]) {
|
||||||
|
override_uv= CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,ma->strand_uvname);
|
||||||
|
override_uv-= CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(part->draw_as==PART_DRAW_BB){
|
if(part->draw_as==PART_DRAW_BB){
|
||||||
int first_uv=CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE);
|
int first_uv=CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE);
|
||||||
|
|
||||||
@@ -1819,7 +1834,10 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
|
|
||||||
re->flag |= R_HALO;
|
re->flag |= R_HALO;
|
||||||
|
|
||||||
Mat4Invert(imat,ob->obmat);
|
MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
|
||||||
|
MTC_Mat4Invert(ob->imat, mat); /* need to be that way, for imat texture */
|
||||||
|
Mat3CpyMat4(nmat, ob->imat);
|
||||||
|
Mat3Transp(nmat);
|
||||||
|
|
||||||
totvlako= re->totvlak;
|
totvlako= re->totvlak;
|
||||||
totverto= re->totvert;
|
totverto= re->totvert;
|
||||||
@@ -1838,8 +1856,8 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
//if(part->phystype==PART_PHYS_KEYED && (psys->flag&PSYS_BAKED)==0)
|
//if(part->phystype==PART_PHYS_KEYED && (psys->flag&PSYS_BAKED)==0)
|
||||||
// path_nbr*=psys->totkeyed;
|
// path_nbr*=psys->totkeyed;
|
||||||
|
|
||||||
if(path_nbr){
|
if(path_nbr) {
|
||||||
if((ma->mode & (MA_HALO|MA_WIRE))==0){
|
if((ma->mode & (MA_HALO|MA_WIRE))==0) {
|
||||||
orco= MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos");
|
orco= MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos");
|
||||||
if (!re->orco_hash)
|
if (!re->orco_hash)
|
||||||
re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
|
re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
|
||||||
@@ -1848,12 +1866,30 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
path=1;
|
path=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(part->draw&PART_DRAW_REN_ADAPT){
|
if(part->draw&PART_DRAW_REN_ADAPT) {
|
||||||
adapt=1;
|
adapt=1;
|
||||||
adapt_pix=(float)part->adapt_pix;
|
adapt_pix=(float)part->adapt_pix;
|
||||||
adapt_angle=cos((float)part->adapt_angle*(float)(M_PI/180.0));
|
adapt_angle=cos((float)part->adapt_angle*(float)(M_PI/180.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(re->r.renderer==R_INTERN && part->draw&PART_DRAW_REN_STRAND) {
|
||||||
|
strandbuf= RE_addStrandBuffer(re, ob, (totpart+totchild)*(path_nbr+1));
|
||||||
|
strandbuf->ma= ma;
|
||||||
|
strandbuf->lay= ob->lay;
|
||||||
|
Mat4CpyMat4(strandbuf->winmat, re->winmat);
|
||||||
|
strandbuf->winx= re->winx;
|
||||||
|
strandbuf->winy= re->winy;
|
||||||
|
strandbuf->maxdepth= 2; /* TODO */
|
||||||
|
strandbuf->adaptcos= cos((float)part->adapt_angle*(float)(M_PI/180.0));
|
||||||
|
strandbuf->overrideuv= override_uv;
|
||||||
|
|
||||||
|
if(part->flag & PART_HAIR_BSPLINE)
|
||||||
|
strandbuf->flag |= R_STRAND_BSPLINE;
|
||||||
|
if(ma->mode & MA_STR_B_UNITS)
|
||||||
|
strandbuf->flag |= R_STRAND_B_UNITS;
|
||||||
|
|
||||||
|
svert= strandbuf->vert;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(keys_possible && part->draw&PART_DRAW_KEYS){
|
else if(keys_possible && part->draw&PART_DRAW_KEYS){
|
||||||
@@ -1872,7 +1908,8 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
|
|
||||||
/* 3. start creating renderable things */
|
/* 3. start creating renderable things */
|
||||||
for(a=0,pa=pars; a<totpart+totchild; a++, pa++) {
|
for(a=0,pa=pars; a<totpart+totchild; a++, pa++) {
|
||||||
random = BLI_frand();
|
random = rng_getFloat(rng);
|
||||||
|
|
||||||
if(a<totpart){
|
if(a<totpart){
|
||||||
if(pa->flag & PARS_UNEXIST) continue;
|
if(pa->flag & PARS_UNEXIST) continue;
|
||||||
|
|
||||||
@@ -1895,10 +1932,10 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
/* get orco */
|
/* get orco */
|
||||||
if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
|
if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
|
||||||
tpa=tpsys->particles+pa->num;
|
tpa=tpsys->particles+pa->num;
|
||||||
psys_particle_on_emitter(ob, psmd,tpart->from,tpa->num, -1,tpa->fuv,tpa->foffset,orco,0,0,0);
|
psys_particle_on_emitter(ob, psmd,tpart->from,tpa->num, -1,tpa->fuv,tpa->foffset,orco,ornor,0,0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,orco,0,0,0);
|
psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,orco,ornor,0,0);
|
||||||
|
|
||||||
if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
|
if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
|
||||||
layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE);
|
layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE);
|
||||||
@@ -1913,8 +1950,6 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
|
|
||||||
psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*n);
|
psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*n);
|
||||||
}
|
}
|
||||||
override_uv=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,ma->strand_uvname)-
|
|
||||||
CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_size=pa->size;
|
pa_size=pa->size;
|
||||||
@@ -1930,7 +1965,8 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
ChildParticle *cpa= psys->child+a-totpart;
|
ChildParticle *cpa= psys->child+a-totpart;
|
||||||
pa_time=psys_get_child_time(psys, a-totpart, cfra);
|
|
||||||
|
pa_time=psys_get_child_time(psys, cpa, cfra);
|
||||||
|
|
||||||
if((part->flag&PART_ABS_TIME)==0){
|
if((part->flag&PART_ABS_TIME)==0){
|
||||||
if(ma->ipo){
|
if(ma->ipo){
|
||||||
@@ -1945,14 +1981,14 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_size=psys_get_child_size(psys, a-totpart, cfra, &pa_time);
|
pa_size=psys_get_child_size(psys, cpa, cfra, &pa_time);
|
||||||
|
|
||||||
r_tilt=2.0f*cpa->rand[2];
|
r_tilt=2.0f*cpa->rand[2];
|
||||||
|
|
||||||
/* get orco */
|
/* get orco */
|
||||||
psys_particle_on_emitter(ob, psmd,
|
psys_particle_on_emitter(ob, psmd,
|
||||||
(part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
|
(part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
|
||||||
cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,orco,0,0,0);
|
cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,orco,ornor,0,0);
|
||||||
|
|
||||||
if(uvco){
|
if(uvco){
|
||||||
layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE);
|
layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE);
|
||||||
@@ -1991,7 +2027,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(path_nbr){
|
if(path_nbr) {
|
||||||
cache = psys->childcache[a-totpart];
|
cache = psys->childcache[a-totpart];
|
||||||
max_k = (int)cache->steps;
|
max_k = (int)cache->steps;
|
||||||
}
|
}
|
||||||
@@ -2003,6 +2039,36 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
orco[2] = (orco[2]-loc_tex[2])/size_tex[2];
|
orco[2] = (orco[2]-loc_tex[2])/size_tex[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ma->mode_l & MA_STR_SURFDIFF) {
|
||||||
|
Mat3MulVecfl(nmat, ornor);
|
||||||
|
surfnor= ornor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
surfnor= NULL;
|
||||||
|
|
||||||
|
if(strandbuf) { /* strand render */
|
||||||
|
strand= RE_findOrAddStrand(re, re->totstrand++);
|
||||||
|
strand->buffer= strandbuf;
|
||||||
|
strand->vert= svert;
|
||||||
|
VECCOPY(strand->orco, orco);
|
||||||
|
|
||||||
|
if(surfnor) {
|
||||||
|
float *snor= RE_strandren_get_surfnor(re, strand, 1);
|
||||||
|
VECCOPY(snor, surfnor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(uvco){
|
||||||
|
for(i=0; i<totuv; i++){
|
||||||
|
if(i != override_uv) {
|
||||||
|
float *uv= RE_strandren_get_uv(re, strand, i, NULL, 1);
|
||||||
|
|
||||||
|
uv[0]= uvco[2*i];
|
||||||
|
uv[1]= uvco[2*i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(k=0; k<=path_nbr; k++){
|
for(k=0; k<=path_nbr; k++){
|
||||||
if(path_nbr){
|
if(path_nbr){
|
||||||
time=(float)k/(float)path_nbr;
|
time=(float)k/(float)path_nbr;
|
||||||
@@ -2026,7 +2092,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
if(part->draw_as!=PART_DRAW_BB)
|
if(part->draw_as!=PART_DRAW_BB)
|
||||||
MTC_Mat4MulVecfl(re->viewmat,loc);
|
MTC_Mat4MulVecfl(re->viewmat,loc);
|
||||||
|
|
||||||
if(part->draw_as==PART_DRAW_LINE){
|
if(part->draw_as==PART_DRAW_LINE) {
|
||||||
VECCOPY(vel,state.vel);
|
VECCOPY(vel,state.vel);
|
||||||
//VECADD(vel,vel,state.co);
|
//VECADD(vel,vel,state.co);
|
||||||
MTC_Mat4Mul3Vecfl(re->viewmat,vel);
|
MTC_Mat4Mul3Vecfl(re->viewmat,vel);
|
||||||
@@ -2038,27 +2104,33 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
VECADDFAC(loc1,loc,vel,part->draw_line[1]);
|
VECADDFAC(loc1,loc,vel,part->draw_line[1]);
|
||||||
|
|
||||||
render_new_particle(re,ob,psmd->dm,ma,1,0,1,0.0f,loc0,loc1,
|
render_new_particle(re,ob,psmd->dm,ma,1,0,1,0.0f,loc0,loc1,
|
||||||
orco,totuv,uvco,hasize,seed,override_uv,0,0,0);
|
orco,surfnor,totuv,uvco,hasize,seed,override_uv,0,0,0);
|
||||||
}
|
}
|
||||||
else if(part->draw_as==PART_DRAW_BB){
|
else if(part->draw_as==PART_DRAW_BB) {
|
||||||
VECCOPY(vel,state.vel);
|
VECCOPY(vel,state.vel);
|
||||||
//MTC_Mat4Mul3Vecfl(re->viewmat,vel);
|
//MTC_Mat4Mul3Vecfl(re->viewmat,vel);
|
||||||
particle_billboard(re,ob,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt),
|
particle_billboard(re,ob,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt),
|
||||||
part->bb_align,part->draw&PART_DRAW_BB_LOCK,
|
part->bb_align,part->draw&PART_DRAW_BB_LOCK,
|
||||||
a,totpart+totchild,part->bb_uv_split,part->bb_anim,part->bb_split_offset,random,pa_time,part->bb_offset,uv);
|
a,totpart+totchild,part->bb_uv_split,part->bb_anim,part->bb_split_offset,random,pa_time,part->bb_offset,uv);
|
||||||
}
|
}
|
||||||
|
else if(strandbuf) {
|
||||||
|
VECCOPY(svert->co, loc);
|
||||||
|
svert->strandco= -1.0f + 2.0f*time;
|
||||||
|
svert++;
|
||||||
|
strand->totvert++;
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
if(k==1){
|
if(k==1){
|
||||||
VECSUB(loc0,loc1,loc);
|
VECSUB(loc0,loc1,loc);
|
||||||
VECADD(loc0,loc1,loc0);
|
VECADD(loc0,loc1,loc0);
|
||||||
render_new_particle(re,ob,psmd->dm,ma,path,1,0,0.0f,loc1,loc0,
|
render_new_particle(re,ob,psmd->dm,ma,path,1,0,0.0f,loc1,loc0,
|
||||||
orco,totuv,uvco,hasize,seed,override_uv,
|
orco,surfnor,totuv,uvco,hasize,seed,override_uv,
|
||||||
adapt,adapt_angle,adapt_pix);
|
adapt,adapt_angle,adapt_pix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(path_nbr==0 || k)
|
if(path_nbr==0 || k)
|
||||||
render_new_particle(re,ob,psmd->dm,ma,path,0,0,time,loc,loc1,
|
render_new_particle(re,ob,psmd->dm,ma,path,0,0,time,loc,loc1,
|
||||||
orco,totuv,uvco,hasize,seed,override_uv,
|
orco,surfnor,totuv,uvco,hasize,seed,override_uv,
|
||||||
adapt,adapt_angle,adapt_pix);
|
adapt,adapt_angle,adapt_pix);
|
||||||
|
|
||||||
VECCOPY(loc1,loc);
|
VECCOPY(loc1,loc);
|
||||||
@@ -2067,6 +2139,9 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
|
|
||||||
if(orco1==0)
|
if(orco1==0)
|
||||||
orco+=3;
|
orco+=3;
|
||||||
|
|
||||||
|
if(re->test_break())
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4. clean up */
|
/* 4. clean up */
|
||||||
@@ -2083,6 +2158,8 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
|
|
||||||
if(states)
|
if(states)
|
||||||
MEM_freeN(states);
|
MEM_freeN(states);
|
||||||
|
|
||||||
|
rng_free(rng);
|
||||||
|
|
||||||
psys->flag &= ~PSYS_DRAWING;
|
psys->flag &= ~PSYS_DRAWING;
|
||||||
|
|
||||||
@@ -2091,9 +2168,9 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
|
|||||||
psys->lattice=0;
|
psys->lattice=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(path && (ma->mode & MA_TANGENT_STR)==0)
|
if(path && (ma->mode_l & MA_TANGENT_STR)==0)
|
||||||
calc_vertexnormals(re, totverto, totvlako, 0);
|
calc_vertexnormals(re, totverto, totvlako, 0);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2249,7 +2326,7 @@ static void render_static_particle_system(Render *re, Object *ob, PartEff *paf)
|
|||||||
if(ctime + paf->staticstep < mtime)
|
if(ctime + paf->staticstep < mtime)
|
||||||
strandco= (ctime-pa->time)/(mtime-pa->time);
|
strandco= (ctime-pa->time)/(mtime-pa->time);
|
||||||
|
|
||||||
static_particle_strand(re, ob, ma, orco, 0, 0, vec, vec1, strandco, first, 0,0,0,0,-1);
|
static_particle_strand(re, ob, ma, orco, 0, 0, 0, vec, vec1, strandco, first, 0,0,0,0,-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3704,10 +3781,11 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i
|
|||||||
static double lasttime= 0.0;
|
static double lasttime= 0.0;
|
||||||
double time;
|
double time;
|
||||||
float mat[4][4];
|
float mat[4][4];
|
||||||
int startface, startvert, allow_render=1;
|
int startface, startvert, startstrand, allow_render=1;
|
||||||
|
|
||||||
startface=re->totvlak;
|
startface=re->totvlak;
|
||||||
startvert=re->totvert;
|
startvert=re->totvert;
|
||||||
|
startstrand=re->totstrand;
|
||||||
|
|
||||||
ob->flag |= OB_DONE;
|
ob->flag |= OB_DONE;
|
||||||
|
|
||||||
@@ -3748,18 +3826,20 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i
|
|||||||
if(allow_render==0 && ob->type==OB_MESH)
|
if(allow_render==0 && ob->type==OB_MESH)
|
||||||
dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
|
dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
|
||||||
|
|
||||||
for(; psys; psys=psys->next)
|
for(; psys; psys=psys->next) {
|
||||||
render_new_particle_system(re, ob, psys);
|
render_new_particle_system(re, ob, psys);
|
||||||
|
psys_free_render_memory(ob, psys);
|
||||||
|
}
|
||||||
|
|
||||||
if(dm)
|
if(dm)
|
||||||
dm->release(dm);
|
dm->release(dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generic post process here */
|
/* generic post process here */
|
||||||
|
if(startvert!=re->totvert || startstrand!=re->totstrand)
|
||||||
|
RE_addRenderObject(re, ob, par, index, startvert, re->totvert, startface, re->totvlak, startstrand, re->totstrand);
|
||||||
|
|
||||||
if(startvert!=re->totvert) {
|
if(startvert!=re->totvert) {
|
||||||
|
|
||||||
RE_addRenderObject(re, ob, par, index, startvert, re->totvert, startface, re->totvlak);
|
|
||||||
|
|
||||||
/* the exception below is because displace code now is in init_render_mesh call,
|
/* the exception below is because displace code now is in init_render_mesh call,
|
||||||
I will look at means to have autosmooth enabled for all object types
|
I will look at means to have autosmooth enabled for all object types
|
||||||
and have it as general postprocess, like displace */
|
and have it as general postprocess, like displace */
|
||||||
@@ -3778,6 +3858,7 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i
|
|||||||
/* clumsy copying still */
|
/* clumsy copying still */
|
||||||
re->i.totvert= re->totvert;
|
re->i.totvert= re->totvert;
|
||||||
re->i.totface= re->totvlak;
|
re->i.totface= re->totvlak;
|
||||||
|
re->i.totstrand= re->totstrand;
|
||||||
re->i.tothalo= re->tothalo;
|
re->i.tothalo= re->tothalo;
|
||||||
re->i.totlamp= re->totlamp;
|
re->i.totlamp= re->totlamp;
|
||||||
re->stats_draw(&re->i);
|
re->stats_draw(&re->i);
|
||||||
@@ -3841,7 +3922,7 @@ void RE_Database_Free(Render *re)
|
|||||||
|
|
||||||
free_sss(re);
|
free_sss(re);
|
||||||
|
|
||||||
re->totvlak=re->totvert=re->totlamp=re->tothalo= 0;
|
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
|
||||||
re->i.convertdone= 0;
|
re->i.convertdone= 0;
|
||||||
|
|
||||||
if(re->scene)
|
if(re->scene)
|
||||||
@@ -4107,7 +4188,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
|
|||||||
/* XXX add test if dbase was filled already? */
|
/* XXX add test if dbase was filled already? */
|
||||||
|
|
||||||
re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
|
re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
|
||||||
re->totvlak=re->totvert=re->totlamp=re->tothalo= 0;
|
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
|
||||||
re->lights.first= re->lights.last= NULL;
|
re->lights.first= re->lights.last= NULL;
|
||||||
re->lampren.first= re->lampren.last= NULL;
|
re->lampren.first= re->lampren.last= NULL;
|
||||||
|
|
||||||
@@ -4223,7 +4304,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
|
|||||||
Object *obd= dob->ob;
|
Object *obd= dob->ob;
|
||||||
|
|
||||||
if (obd->restrictflag & OB_RESTRICT_RENDER) continue;
|
if (obd->restrictflag & OB_RESTRICT_RENDER) continue;
|
||||||
|
|
||||||
Mat4CpyMat4(obd->obmat, dob->mat);
|
Mat4CpyMat4(obd->obmat, dob->mat);
|
||||||
|
|
||||||
/* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */
|
/* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */
|
||||||
@@ -4311,6 +4392,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
|
|||||||
/* for now some clumsy copying still */
|
/* for now some clumsy copying still */
|
||||||
re->i.totvert= re->totvert;
|
re->i.totvert= re->totvert;
|
||||||
re->i.totface= re->totvlak;
|
re->i.totface= re->totvlak;
|
||||||
|
re->i.totstrand= re->totstrand;
|
||||||
re->i.tothalo= re->tothalo;
|
re->i.tothalo= re->tothalo;
|
||||||
re->i.totlamp= re->totlamp;
|
re->i.totlamp= re->totlamp;
|
||||||
re->stats_draw(&re->i);
|
re->stats_draw(&re->i);
|
||||||
@@ -4354,7 +4436,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!re->test_break())
|
if(!re->test_break())
|
||||||
project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0);
|
project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
|
||||||
|
|
||||||
/* SSS */
|
/* SSS */
|
||||||
if((re->r.mode & R_SSS) && !re->test_break())
|
if((re->r.mode & R_SSS) && !re->test_break())
|
||||||
@@ -4385,8 +4467,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset)
|
|||||||
/* XXX add test if dbase was filled already? */
|
/* XXX add test if dbase was filled already? */
|
||||||
|
|
||||||
re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
|
re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
|
||||||
re->totvlak=re->totvert=re->totlamp=re->tothalo= 0;
|
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
|
||||||
re->i.totface=re->i.totvert=re->i.totlamp=re->i.tothalo= 0;
|
re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0;
|
||||||
re->lights.first= re->lights.last= NULL;
|
re->lights.first= re->lights.last= NULL;
|
||||||
|
|
||||||
slurph_opt= 0;
|
slurph_opt= 0;
|
||||||
@@ -4464,14 +4546,14 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!re->test_break())
|
if(!re->test_break())
|
||||||
project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0);
|
project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
|
||||||
|
|
||||||
/* do this in end, particles for example need cfra */
|
/* do this in end, particles for example need cfra */
|
||||||
G.scene->r.cfra-=timeoffset;
|
G.scene->r.cfra-=timeoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* choose to use static, to prevent giving too many args to this call */
|
/* choose to use static, to prevent giving too many args to this call */
|
||||||
static void speedvector_project(Render *re, float *zco, VertRen *ver)
|
static void speedvector_project(Render *re, float *zco, float *co, float *ho)
|
||||||
{
|
{
|
||||||
static float pixelphix=0.0f, pixelphiy=0.0f, zmulx=0.0f, zmuly=0.0f;
|
static float pixelphix=0.0f, pixelphiy=0.0f, zmulx=0.0f, zmuly=0.0f;
|
||||||
static int pano= 0;
|
static int pano= 0;
|
||||||
@@ -4499,14 +4581,14 @@ static void speedvector_project(Render *re, float *zco, VertRen *ver)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* now map hocos to screenspace, uses very primitive clip still */
|
/* now map hocos to screenspace, uses very primitive clip still */
|
||||||
if(ver->ho[3]<0.1f) div= 10.0f;
|
if(ho[3]<0.1f) div= 10.0f;
|
||||||
else div= 1.0f/ver->ho[3];
|
else div= 1.0f/ho[3];
|
||||||
|
|
||||||
/* use cylinder projection */
|
/* use cylinder projection */
|
||||||
if(pano) {
|
if(pano) {
|
||||||
float vec[3], ang;
|
float vec[3], ang;
|
||||||
/* angle between (0,0,-1) and (ver->co) */
|
/* angle between (0,0,-1) and (co) */
|
||||||
VECCOPY(vec, ver->co);
|
VECCOPY(vec, co);
|
||||||
|
|
||||||
ang= saacos(-vec[2]/sqrt(vec[0]*vec[0] + vec[2]*vec[2]));
|
ang= saacos(-vec[2]/sqrt(vec[0]*vec[0] + vec[2]*vec[2]));
|
||||||
if(vec[0]<0.0f) ang= -ang;
|
if(vec[0]<0.0f) ang= -ang;
|
||||||
@@ -4517,57 +4599,84 @@ static void speedvector_project(Render *re, float *zco, VertRen *ver)
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
zco[0]= zmulx*(1.0f+ver->ho[0]*div);
|
zco[0]= zmulx*(1.0f+ho[0]*div);
|
||||||
zco[1]= zmuly*(1.0f+ver->ho[1]*div);
|
zco[1]= zmuly*(1.0f+ho[1]*div);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calculate_speedvectors(Render *re, float *vectors, int startvert, int endvert, int step)
|
static void calculate_speedvector(float *vectors, int step, float winsq, float winroot, float *co, float *ho, float *speed)
|
||||||
|
{
|
||||||
|
float zco[2], len;
|
||||||
|
|
||||||
|
speedvector_project(NULL, zco, co, ho);
|
||||||
|
|
||||||
|
zco[0]= vectors[0] - zco[0];
|
||||||
|
zco[1]= vectors[1] - zco[1];
|
||||||
|
|
||||||
|
/* enable nice masks for hardly moving stuff or float inaccuracy */
|
||||||
|
if(zco[0]<0.1f && zco[0]>-0.1f && zco[1]<0.1f && zco[1]>-0.1f ) {
|
||||||
|
zco[0]= 0.0f;
|
||||||
|
zco[1]= 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* maximize speed for image width, otherwise it never looks good */
|
||||||
|
len= zco[0]*zco[0] + zco[1]*zco[1];
|
||||||
|
if(len > winsq) {
|
||||||
|
len= winroot/sqrt(len);
|
||||||
|
zco[0]*= len;
|
||||||
|
zco[1]*= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* note; in main vecblur loop speedvec is negated again */
|
||||||
|
if(step) {
|
||||||
|
speed[2]= -zco[0];
|
||||||
|
speed[3]= -zco[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
speed[0]= zco[0];
|
||||||
|
speed[1]= zco[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void calculate_speedvectors(Render *re, ObjectRen *obren, float *vectors, int step)
|
||||||
{
|
{
|
||||||
VertRen *ver= NULL;
|
VertRen *ver= NULL;
|
||||||
float *speed, zco[2];
|
StrandRen *strand= NULL;
|
||||||
float len;
|
float *speed, ho[4];
|
||||||
float winsq= re->winx*re->winy, winroot= sqrt(winsq);
|
float winsq= re->winx*re->winy, winroot= sqrt(winsq);
|
||||||
int a;
|
int a, startvert, endvert, startstrand, endstrand;
|
||||||
|
|
||||||
|
startvert= obren->startvert;
|
||||||
|
endvert= obren->endvert;
|
||||||
|
startstrand= obren->startstrand;
|
||||||
|
endstrand= obren->endstrand;
|
||||||
|
|
||||||
/* set first vertex OK */
|
if(re->vertnodes) {
|
||||||
a= startvert-1;
|
/* set first vertex OK */
|
||||||
ver= re->vertnodes[a>>8].vert + (a & 255);
|
a= startvert-1;
|
||||||
|
ver= re->vertnodes[a>>8].vert + (a & 255);
|
||||||
for(a=startvert; a<endvert; a++, vectors+=2) {
|
|
||||||
if((a & 255)==0)
|
|
||||||
ver= re->vertnodes[a>>8].vert;
|
|
||||||
else
|
|
||||||
ver++;
|
|
||||||
|
|
||||||
speedvector_project(NULL, zco, ver);
|
for(a=startvert; a<endvert; a++, vectors+=2) {
|
||||||
|
if((a & 255)==0) ver= re->vertnodes[a>>8].vert;
|
||||||
zco[0]= vectors[0] - zco[0];
|
else ver++;
|
||||||
zco[1]= vectors[1] - zco[1];
|
|
||||||
|
speed= RE_vertren_get_winspeed(re, ver, 1);
|
||||||
/* enable nice masks for hardly moving stuff or float inaccuracy */
|
calculate_speedvector(vectors, step, winsq, winroot, ver->co, ver->ho, speed);
|
||||||
if(zco[0]<0.1f && zco[0]>-0.1f && zco[1]<0.1f && zco[1]>-0.1f ) {
|
|
||||||
zco[0]= 0.0f;
|
|
||||||
zco[1]= 0.0f;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(re->strandnodes) {
|
||||||
|
/* set first strand OK */
|
||||||
|
a= startstrand-1;
|
||||||
|
strand= re->strandnodes[a>>8].strand + (a & 255);
|
||||||
|
|
||||||
/* maximize speed for image width, otherwise it never looks good */
|
for(a=startstrand; a<endstrand; a++, vectors+=2) {
|
||||||
len= zco[0]*zco[0] + zco[1]*zco[1];
|
if((a & 255)==0) strand= re->strandnodes[a>>8].strand;
|
||||||
if(len > winsq) {
|
else strand++;
|
||||||
len= winroot/sqrt(len);
|
|
||||||
zco[0]*= len;
|
speed= RE_strandren_get_winspeed(re, strand, 1);
|
||||||
zco[1]*= len;
|
projectverto(strand->vert->co, re->winmat, ho);
|
||||||
}
|
calculate_speedvector(vectors, step, winsq, winroot, strand->vert->co, ho, speed);
|
||||||
|
|
||||||
speed= RE_vertren_get_winspeed(re, ver, 1);
|
|
||||||
/* note; in main vecblur loop speedvec is negated again */
|
|
||||||
if(step) {
|
|
||||||
speed[2]= -zco[0];
|
|
||||||
speed[3]= -zco[1];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
speed[0]= zco[0];
|
|
||||||
speed[1]= zco[1];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4652,26 +4761,45 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb)
|
|||||||
{
|
{
|
||||||
ObjectRen *obren, *obrenlb;
|
ObjectRen *obren, *obrenlb;
|
||||||
VertRen *ver;
|
VertRen *ver;
|
||||||
float *vec;
|
StrandRen *strand;
|
||||||
int a;
|
float *vec, ho[4];
|
||||||
|
int a, totvector;
|
||||||
|
|
||||||
for(obren= re->objecttable.first; obren; obren= obren->next) {
|
for(obren= re->objecttable.first; obren; obren= obren->next) {
|
||||||
obrenlb= MEM_dupallocN(obren);
|
obrenlb= MEM_dupallocN(obren);
|
||||||
BLI_addtail(lb, obrenlb);
|
BLI_addtail(lb, obrenlb);
|
||||||
if(obren->endvert>obren->startvert) {
|
|
||||||
vec= obrenlb->vectors= MEM_mallocN(2*sizeof(float)*(obren->endvert- obren->startvert), "vector array");
|
|
||||||
|
|
||||||
/* first vertex */
|
totvector= obren->endvert - obren->startvert;
|
||||||
a= obren->startvert-1;
|
totvector+= obren->endstrand - obren->startstrand;
|
||||||
ver= re->vertnodes[a>>8].vert + (a & 255);
|
|
||||||
|
|
||||||
for(a=obren->startvert; a<obren->endvert; a++, vec+=2) {
|
if(totvector > 0) {
|
||||||
if((a & 255)==0)
|
vec= obrenlb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array");
|
||||||
ver= re->vertnodes[a>>8].vert;
|
|
||||||
else
|
if(obren->endvert > obren->startvert) {
|
||||||
ver++;
|
/* first vertex */
|
||||||
|
a= obren->startvert-1;
|
||||||
speedvector_project(NULL, vec, ver);
|
ver= re->vertnodes[a>>8].vert + (a & 255);
|
||||||
|
|
||||||
|
for(a=obren->startvert; a<obren->endvert; a++, vec+=2) {
|
||||||
|
if((a & 255)==0) ver= re->vertnodes[a>>8].vert;
|
||||||
|
else ver++;
|
||||||
|
|
||||||
|
speedvector_project(NULL, vec, ver->co, ver->ho);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(obren->endstrand > obren->startstrand) {
|
||||||
|
/* first strand */
|
||||||
|
a= obren->startstrand-1;
|
||||||
|
strand= re->strandnodes[a>>8].strand + (a & 255);
|
||||||
|
|
||||||
|
for(a=obren->startstrand; a<obren->endstrand; a++, vec+=2) {
|
||||||
|
if((a & 255)==0) strand= re->strandnodes[a>>8].strand;
|
||||||
|
else strand++;
|
||||||
|
|
||||||
|
projectverto(strand->vert->co, re->winmat, ho);
|
||||||
|
speedvector_project(NULL, vec, strand->vert->co, ho);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4697,7 +4825,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
|
|||||||
re->i.infostr= "Calculating previous vectors";
|
re->i.infostr= "Calculating previous vectors";
|
||||||
re->r.mode |= R_SPEED;
|
re->r.mode |= R_SPEED;
|
||||||
|
|
||||||
speedvector_project(re, NULL, NULL); /* initializes projection code */
|
speedvector_project(re, NULL, NULL, NULL); /* initializes projection code */
|
||||||
|
|
||||||
/* creates entire dbase */
|
/* creates entire dbase */
|
||||||
database_fromscene_vectors(re, sce, -1);
|
database_fromscene_vectors(re, sce, -1);
|
||||||
@@ -4758,12 +4886,13 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
|
|||||||
load_fluidsimspeedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step, obren->ob);
|
load_fluidsimspeedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step, obren->ob);
|
||||||
} else {
|
} else {
|
||||||
/* check if both have same amounts of vertices */
|
/* check if both have same amounts of vertices */
|
||||||
if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert) {
|
if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert ||
|
||||||
|
obren->endstrand-obren->startstrand != oldobren->endstrand-oldobren->startstrand) {
|
||||||
printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2);
|
printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
calculate_speedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step);
|
calculate_speedvectors(re, obren, oldobren->vectors, step);
|
||||||
} // not fluidsim
|
} // not fluidsim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4780,7 +4909,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
|
|||||||
/* exported call to recalculate hoco for vertices, when winmat changed */
|
/* exported call to recalculate hoco for vertices, when winmat changed */
|
||||||
void RE_DataBase_ApplyWindow(Render *re)
|
void RE_DataBase_ApplyWindow(Render *re)
|
||||||
{
|
{
|
||||||
project_renderdata(re, projectverto, 0, 0);
|
project_renderdata(re, projectverto, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup for shaded view or bake, so only lamps and materials are initialized */
|
/* setup for shaded view or bake, so only lamps and materials are initialized */
|
||||||
@@ -4819,7 +4948,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
|
|||||||
if(type!=RE_BAKE_LIGHT)
|
if(type!=RE_BAKE_LIGHT)
|
||||||
re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
|
re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
|
||||||
|
|
||||||
re->totvlak=re->totvert=re->totlamp=re->tothalo= 0;
|
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
|
||||||
re->lights.first= re->lights.last= NULL;
|
re->lights.first= re->lights.last= NULL;
|
||||||
re->lampren.first= re->lampren.last= NULL;
|
re->lampren.first= re->lampren.last= NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,9 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
|
|||||||
envre->bloha= re->bloha;
|
envre->bloha= re->bloha;
|
||||||
envre->vlaknodeslen= re->vlaknodeslen;
|
envre->vlaknodeslen= re->vlaknodeslen;
|
||||||
envre->vlaknodes= re->vlaknodes;
|
envre->vlaknodes= re->vlaknodes;
|
||||||
|
envre->strandnodeslen= re->strandnodeslen;
|
||||||
|
envre->strandnodes= re->strandnodes;
|
||||||
|
envre->strandbuckets= re->strandbuckets;
|
||||||
envre->customdata_names= re->customdata_names;
|
envre->customdata_names= re->customdata_names;
|
||||||
envre->raytree= re->raytree;
|
envre->raytree= re->raytree;
|
||||||
|
|
||||||
@@ -176,6 +179,9 @@ static void envmap_free_render_copy(Render *envre)
|
|||||||
envre->bloha= NULL;
|
envre->bloha= NULL;
|
||||||
envre->vlaknodeslen= 0;
|
envre->vlaknodeslen= 0;
|
||||||
envre->vlaknodes= NULL;
|
envre->vlaknodes= NULL;
|
||||||
|
envre->strandnodeslen= 0;
|
||||||
|
envre->strandnodes= NULL;
|
||||||
|
envre->strandbuckets= NULL;
|
||||||
envre->customdata_names.first= envre->customdata_names.last= NULL;
|
envre->customdata_names.first= envre->customdata_names.last= NULL;
|
||||||
envre->raytree= NULL;
|
envre->raytree= NULL;
|
||||||
|
|
||||||
@@ -403,7 +409,7 @@ static void render_envmap(Render *re, EnvMap *env)
|
|||||||
|
|
||||||
env_rotate_scene(envre, tmat, 1);
|
env_rotate_scene(envre, tmat, 1);
|
||||||
init_render_world(envre);
|
init_render_world(envre);
|
||||||
project_renderdata(envre, projectverto, 0, 0);
|
project_renderdata(envre, projectverto, 0, 0, 1);
|
||||||
env_layerflags(envre, env->notlay);
|
env_layerflags(envre, env->notlay);
|
||||||
env_hideobject(envre, env->object);
|
env_hideobject(envre, env->object);
|
||||||
env_set_imats(envre);
|
env_set_imats(envre);
|
||||||
|
|||||||
@@ -171,8 +171,9 @@ void RE_FreeRenderResult(RenderResult *res)
|
|||||||
RenderLayer *rl= res->layers.first;
|
RenderLayer *rl= res->layers.first;
|
||||||
|
|
||||||
if(rl->rectf) MEM_freeN(rl->rectf);
|
if(rl->rectf) MEM_freeN(rl->rectf);
|
||||||
/* acolrect is optionally allocated in shade_tile, only free here since it can be used for drawing */
|
/* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */
|
||||||
if(rl->acolrect) MEM_freeN(rl->acolrect);
|
if(rl->acolrect) MEM_freeN(rl->acolrect);
|
||||||
|
if(rl->scolrect) MEM_freeN(rl->scolrect);
|
||||||
|
|
||||||
while(rl->passes.first) {
|
while(rl->passes.first) {
|
||||||
RenderPass *rpass= rl->passes.first;
|
RenderPass *rpass= rl->passes.first;
|
||||||
@@ -1250,6 +1251,7 @@ static void render_tile_processor(Render *re, int firsttile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
freeparts(re);
|
freeparts(re);
|
||||||
|
R.strandbuckets= NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculus for how much 1 pixel rendered should rotate the 3d geometry */
|
/* calculus for how much 1 pixel rendered should rotate the 3d geometry */
|
||||||
@@ -1307,7 +1309,7 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
|
|||||||
Mat4CpyMat4(R.winmat, re->winmat);
|
Mat4CpyMat4(R.winmat, re->winmat);
|
||||||
|
|
||||||
/* rotate database according to part coordinates */
|
/* rotate database according to part coordinates */
|
||||||
project_renderdata(re, projectverto, 1, -R.panodxp*phi);
|
project_renderdata(re, projectverto, 1, -R.panodxp*phi, 1);
|
||||||
R.panosi= sin(R.panodxp*phi);
|
R.panosi= sin(R.panodxp*phi);
|
||||||
R.panoco= cos(R.panodxp*phi);
|
R.panoco= cos(R.panodxp*phi);
|
||||||
}
|
}
|
||||||
@@ -1483,7 +1485,7 @@ static void threaded_tile_processor(Render *re)
|
|||||||
BLI_end_threads(&threads);
|
BLI_end_threads(&threads);
|
||||||
freeparts(re);
|
freeparts(re);
|
||||||
re->viewplane= viewplane; /* restore viewplane, modified by pano render */
|
re->viewplane= viewplane; /* restore viewplane, modified by pano render */
|
||||||
|
R.strandbuckets= NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* currently only called by preview renders and envmap */
|
/* currently only called by preview renders and envmap */
|
||||||
|
|||||||
@@ -887,7 +887,7 @@ void zbufshadeDA_tile(RenderPart *pa)
|
|||||||
if(R.flag & R_HALO)
|
if(R.flag & R_HALO)
|
||||||
if(rl->layflag & SCE_LAY_HALO)
|
if(rl->layflag & SCE_LAY_HALO)
|
||||||
halo_tile(pa, rl->rectf, rl->lay);
|
halo_tile(pa, rl->rectf, rl->lay);
|
||||||
|
|
||||||
/* transp layer */
|
/* transp layer */
|
||||||
if(R.flag & R_ZTRA) {
|
if(R.flag & R_ZTRA) {
|
||||||
if(rl->layflag & SCE_LAY_ZTRA) {
|
if(rl->layflag & SCE_LAY_ZTRA) {
|
||||||
@@ -904,7 +904,7 @@ void zbufshadeDA_tile(RenderPart *pa)
|
|||||||
/* zbuffer transp only returns ztramask if there's solid rendered */
|
/* zbuffer transp only returns ztramask if there's solid rendered */
|
||||||
if(ztramask)
|
if(ztramask)
|
||||||
solidmask= make_solid_mask(pa);
|
solidmask= make_solid_mask(pa);
|
||||||
|
|
||||||
if(ztramask && solidmask) {
|
if(ztramask && solidmask) {
|
||||||
unsigned short *sps= solidmask, *spz= ztramask;
|
unsigned short *sps= solidmask, *spz= ztramask;
|
||||||
unsigned short fullmask= (1<<R.osa)-1;
|
unsigned short fullmask= (1<<R.osa)-1;
|
||||||
@@ -929,6 +929,47 @@ void zbufshadeDA_tile(RenderPart *pa)
|
|||||||
if(ztramask) MEM_freeN(ztramask);
|
if(ztramask) MEM_freeN(ztramask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* strand rendering */
|
||||||
|
if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) {
|
||||||
|
float *fcol, *scol;
|
||||||
|
unsigned short *strandmask, *solidmask= NULL; /* 16 bits, MAX_OSA */
|
||||||
|
int x;
|
||||||
|
|
||||||
|
/* allocate, but not free here, for asynchronous display of this rect in main thread */
|
||||||
|
rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer");
|
||||||
|
|
||||||
|
/* swap for live updates, and it is used in zbuf.c!!! */
|
||||||
|
SWAP(float*, rl->scolrect, rl->rectf);
|
||||||
|
strandmask= zbuffer_strands_shade(&R, pa, rl, rl->rectf);
|
||||||
|
SWAP(float*, rl->scolrect, rl->rectf);
|
||||||
|
|
||||||
|
/* zbuffer strands only returns strandmask if there's solid rendered */
|
||||||
|
if(strandmask)
|
||||||
|
solidmask= make_solid_mask(pa);
|
||||||
|
|
||||||
|
if(strandmask && solidmask) {
|
||||||
|
unsigned short *sps= solidmask, *spz= strandmask;
|
||||||
|
unsigned short fullmask= (1<<R.osa)-1;
|
||||||
|
|
||||||
|
fcol= rl->rectf; scol= rl->scolrect;
|
||||||
|
for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4, sps++, spz++) {
|
||||||
|
if(*sps == fullmask)
|
||||||
|
addAlphaOverFloat(fcol, scol);
|
||||||
|
else
|
||||||
|
addAlphaOverFloatMask(fcol, scol, *sps, *spz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fcol= rl->rectf; scol= rl->scolrect;
|
||||||
|
for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4)
|
||||||
|
addAlphaOverFloat(fcol, scol);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(solidmask) MEM_freeN(solidmask);
|
||||||
|
if(strandmask) MEM_freeN(strandmask);
|
||||||
|
}
|
||||||
|
|
||||||
/* sky before edge */
|
/* sky before edge */
|
||||||
if(rl->layflag & SCE_LAY_SKY)
|
if(rl->layflag & SCE_LAY_SKY)
|
||||||
sky_tile(pa, rl->rectf);
|
sky_tile(pa, rl->rectf);
|
||||||
@@ -1081,6 +1122,24 @@ void zbufshade_tile(RenderPart *pa)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* strand rendering */
|
||||||
|
if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) {
|
||||||
|
float *fcol, *scol;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
/* allocate, but not free here, for asynchronous display of this rect in main thread */
|
||||||
|
rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer");
|
||||||
|
|
||||||
|
/* swap for live updates */
|
||||||
|
SWAP(float*, rl->scolrect, rl->rectf);
|
||||||
|
zbuffer_strands_shade(&R, pa, rl, rl->rectf);
|
||||||
|
SWAP(float*, rl->scolrect, rl->rectf);
|
||||||
|
|
||||||
|
fcol= rl->rectf; scol= rl->scolrect;
|
||||||
|
for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4)
|
||||||
|
addAlphaOverFloat(fcol, scol);
|
||||||
|
}
|
||||||
|
|
||||||
/* sky before edge */
|
/* sky before edge */
|
||||||
if(rl->layflag & SCE_LAY_SKY)
|
if(rl->layflag & SCE_LAY_SKY)
|
||||||
@@ -1594,7 +1653,7 @@ void add_halo_flare(Render *re)
|
|||||||
mode= R.r.mode;
|
mode= R.r.mode;
|
||||||
R.r.mode &= ~R_PANORAMA;
|
R.r.mode &= ~R_PANORAMA;
|
||||||
|
|
||||||
project_renderdata(&R, projectverto, 0, 0);
|
project_renderdata(&R, projectverto, 0, 0, 0);
|
||||||
|
|
||||||
for(a=0; a<R.tothalo; a++) {
|
for(a=0; a<R.tothalo; a++) {
|
||||||
if((a & 255)==0) har= R.bloha[a>>8];
|
if((a & 255)==0) har= R.bloha[a>>8];
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
#include "render_types.h"
|
#include "render_types.h"
|
||||||
#include "renderdatabase.h"
|
#include "renderdatabase.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
#include "strand.h"
|
||||||
#include "zbuf.h"
|
#include "zbuf.h"
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@@ -100,6 +101,8 @@
|
|||||||
#define RE_WINSPEED_ELEMS 4
|
#define RE_WINSPEED_ELEMS 4
|
||||||
#define RE_MTFACE_ELEMS 1
|
#define RE_MTFACE_ELEMS 1
|
||||||
#define RE_MCOL_ELEMS 4
|
#define RE_MCOL_ELEMS 4
|
||||||
|
#define RE_UV_ELEMS 2
|
||||||
|
#define RE_SURFNOR_ELEMS 3
|
||||||
|
|
||||||
float *RE_vertren_get_sticky(Render *re, VertRen *ver, int verify)
|
float *RE_vertren_get_sticky(Render *re, VertRen *ver, int verify)
|
||||||
{
|
{
|
||||||
@@ -368,6 +371,21 @@ MCol *RE_vlakren_get_mcol(Render *re, VlakRen *vlr, int n, char **name, int veri
|
|||||||
return node->mcol[index];
|
return node->mcol[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float *RE_vlakren_get_surfnor(Render *re, VlakRen *vlak, int verify)
|
||||||
|
{
|
||||||
|
float *surfnor;
|
||||||
|
int nr= vlak->index>>8;
|
||||||
|
|
||||||
|
surfnor= re->vlaknodes[nr].surfnor;
|
||||||
|
if(surfnor==NULL) {
|
||||||
|
if(verify)
|
||||||
|
surfnor= re->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
|
||||||
|
}
|
||||||
|
|
||||||
VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr)
|
VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr)
|
||||||
{
|
{
|
||||||
VlakRen *vlr1 = RE_findOrAddVlak(re, re->totvlak++);
|
VlakRen *vlr1 = RE_findOrAddVlak(re, re->totvlak++);
|
||||||
@@ -375,6 +393,7 @@ VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr)
|
|||||||
MCol *mcol, *mcol1;
|
MCol *mcol, *mcol1;
|
||||||
VlakTableNode *node = &re->vlaknodes[vlr->index>>8];
|
VlakTableNode *node = &re->vlaknodes[vlr->index>>8];
|
||||||
VlakTableNode *node1 = &re->vlaknodes[vlr1->index>>8];
|
VlakTableNode *node1 = &re->vlaknodes[vlr1->index>>8];
|
||||||
|
float *surfnor, *surfnor1;
|
||||||
int i, index = vlr1->index;
|
int i, index = vlr1->index;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
@@ -391,6 +410,12 @@ VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr)
|
|||||||
memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
|
memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
surfnor= RE_vlakren_get_surfnor(re, vlr, 0);
|
||||||
|
if(surfnor) {
|
||||||
|
surfnor1= RE_vlakren_get_surfnor(re, vlr1, 1);
|
||||||
|
VECCOPY(surfnor1, surfnor);
|
||||||
|
}
|
||||||
|
|
||||||
if (node->names && node1->names)
|
if (node->names && node1->names)
|
||||||
node1->names[vlr1->index&255] = node->names[vlr->index&255];
|
node1->names[vlr1->index&255] = node->names[vlr->index&255];
|
||||||
|
|
||||||
@@ -480,7 +505,183 @@ VlakRen *RE_findOrAddVlak(Render *re, int nr)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, int eve, int sfa, int efa)
|
float *RE_strandren_get_winspeed(Render *re, StrandRen *strand, int verify)
|
||||||
|
{
|
||||||
|
float *winspeed;
|
||||||
|
int nr= strand->index>>8;
|
||||||
|
|
||||||
|
winspeed= re->strandnodes[nr].winspeed;
|
||||||
|
if(winspeed==NULL) {
|
||||||
|
if(verify)
|
||||||
|
winspeed= re->strandnodes[nr].winspeed= MEM_callocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return winspeed + (strand->index & 255)*RE_WINSPEED_ELEMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
float *RE_strandren_get_surfnor(Render *re, StrandRen *strand, int verify)
|
||||||
|
{
|
||||||
|
float *surfnor;
|
||||||
|
int nr= strand->index>>8;
|
||||||
|
|
||||||
|
surfnor= re->strandnodes[nr].surfnor;
|
||||||
|
if(surfnor==NULL) {
|
||||||
|
if(verify)
|
||||||
|
surfnor= re->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
float *RE_strandren_get_uv(Render *re, StrandRen *strand, int n, char **name, int verify)
|
||||||
|
{
|
||||||
|
StrandTableNode *node;
|
||||||
|
int nr= strand->index>>8, strandindex= (strand->index&255);
|
||||||
|
int index= (n<<8) + strandindex;
|
||||||
|
|
||||||
|
node= &re->strandnodes[nr];
|
||||||
|
|
||||||
|
if(verify) {
|
||||||
|
if(n>=node->totuv) {
|
||||||
|
float **uv= node->uv;
|
||||||
|
int size= (n+1)*256;
|
||||||
|
|
||||||
|
node->uv= MEM_callocN(size*sizeof(MCol*), "Strand uv");
|
||||||
|
|
||||||
|
if(uv) {
|
||||||
|
size= node->totuv*256;
|
||||||
|
memcpy(node->uv, uv, size*sizeof(MCol*));
|
||||||
|
MEM_freeN(uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
node->totuv= n+1;
|
||||||
|
|
||||||
|
if (!node->names) {
|
||||||
|
size= sizeof(*node->names)*256;
|
||||||
|
node->names= MEM_callocN(size, "Strand names");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node->uv[index]==NULL) {
|
||||||
|
node->uv[index]= BLI_memarena_alloc(re->memArena,
|
||||||
|
sizeof(float)*RE_UV_ELEMS);
|
||||||
|
|
||||||
|
node->names[strandindex]= re->customdata_names.last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(n>=node->totuv || node->uv[index]==NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(name) *name= node->names[strandindex]->mtface[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->uv[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
MCol *RE_strandren_get_mcol(Render *re, StrandRen *strand, int n, char **name, int verify)
|
||||||
|
{
|
||||||
|
StrandTableNode *node;
|
||||||
|
int nr= strand->index>>8, strandindex= (strand->index&255);
|
||||||
|
int index= (n<<8) + strandindex;
|
||||||
|
|
||||||
|
node= &re->strandnodes[nr];
|
||||||
|
|
||||||
|
if(verify) {
|
||||||
|
if(n>=node->totmcol) {
|
||||||
|
MCol **mcol= node->mcol;
|
||||||
|
int size= (n+1)*256;
|
||||||
|
|
||||||
|
node->mcol= MEM_callocN(size*sizeof(MCol*), "Strand mcol");
|
||||||
|
|
||||||
|
if(mcol) {
|
||||||
|
size= node->totmcol*256;
|
||||||
|
memcpy(node->mcol, mcol, size*sizeof(MCol*));
|
||||||
|
MEM_freeN(mcol);
|
||||||
|
}
|
||||||
|
|
||||||
|
node->totmcol= n+1;
|
||||||
|
|
||||||
|
if (!node->names) {
|
||||||
|
size= sizeof(*node->names)*256;
|
||||||
|
node->names= MEM_callocN(size, "Strand names");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node->mcol[index]==NULL) {
|
||||||
|
node->mcol[index]= BLI_memarena_alloc(re->memArena,
|
||||||
|
sizeof(MCol)*RE_MCOL_ELEMS);
|
||||||
|
|
||||||
|
node->names[strandindex]= re->customdata_names.last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(n>=node->totmcol || node->mcol[index]==NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(name) *name= node->names[strandindex]->mcol[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->mcol[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
StrandRen *RE_findOrAddStrand(Render *re, int nr)
|
||||||
|
{
|
||||||
|
StrandTableNode *temp;
|
||||||
|
StrandRen *v;
|
||||||
|
int a;
|
||||||
|
|
||||||
|
if(nr<0) {
|
||||||
|
printf("error in findOrAddStrand: %d\n",nr);
|
||||||
|
return re->strandnodes[0].strand;
|
||||||
|
}
|
||||||
|
a= nr>>8;
|
||||||
|
|
||||||
|
if (a>=re->strandnodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
|
||||||
|
temp= re->strandnodes;
|
||||||
|
|
||||||
|
re->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(re->strandnodeslen+TABLEINITSIZE) , "strandnodes");
|
||||||
|
if(temp) memcpy(re->strandnodes, temp, re->strandnodeslen*sizeof(StrandTableNode));
|
||||||
|
memset(re->strandnodes+re->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
|
||||||
|
|
||||||
|
re->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
|
||||||
|
if(temp) MEM_freeN(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
v= re->strandnodes[a].strand;
|
||||||
|
|
||||||
|
if(v==NULL) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand");
|
||||||
|
re->strandnodes[a].strand= v;
|
||||||
|
|
||||||
|
for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
|
||||||
|
v[a].index= i;
|
||||||
|
}
|
||||||
|
v+= (nr & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
StrandBuffer *RE_addStrandBuffer(Render *re, Object *ob, int totvert)
|
||||||
|
{
|
||||||
|
StrandBuffer *strandbuf;
|
||||||
|
|
||||||
|
strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
|
||||||
|
strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
|
||||||
|
strandbuf->totvert= totvert;
|
||||||
|
strandbuf->ob= ob;
|
||||||
|
|
||||||
|
BLI_addtail(&re->strandbufs, strandbuf);
|
||||||
|
|
||||||
|
return strandbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est)
|
||||||
{
|
{
|
||||||
ObjectRen *obr= MEM_mallocN(sizeof(ObjectRen), "object render struct");
|
ObjectRen *obr= MEM_mallocN(sizeof(ObjectRen), "object render struct");
|
||||||
|
|
||||||
@@ -492,6 +693,8 @@ void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve,
|
|||||||
obr->endvert= eve;
|
obr->endvert= eve;
|
||||||
obr->startface= sfa;
|
obr->startface= sfa;
|
||||||
obr->endface= efa;
|
obr->endface= efa;
|
||||||
|
obr->startstrand= sst;
|
||||||
|
obr->endstrand= est;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_renderdata_vertnodes(VertTableNode *vertnodes)
|
void free_renderdata_vertnodes(VertTableNode *vertnodes)
|
||||||
@@ -533,6 +736,8 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
|
|||||||
MEM_freeN(vlaknodes[a].mtface);
|
MEM_freeN(vlaknodes[a].mtface);
|
||||||
if(vlaknodes[a].mcol)
|
if(vlaknodes[a].mcol)
|
||||||
MEM_freeN(vlaknodes[a].mcol);
|
MEM_freeN(vlaknodes[a].mcol);
|
||||||
|
if(vlaknodes[a].surfnor)
|
||||||
|
MEM_freeN(vlaknodes[a].surfnor);
|
||||||
if(vlaknodes[a].names)
|
if(vlaknodes[a].names)
|
||||||
MEM_freeN(vlaknodes[a].names);
|
MEM_freeN(vlaknodes[a].names);
|
||||||
}
|
}
|
||||||
@@ -540,10 +745,35 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
|
|||||||
MEM_freeN(vlaknodes);
|
MEM_freeN(vlaknodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free_renderdata_strandnodes(StrandTableNode *strandnodes)
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
|
||||||
|
if(strandnodes==NULL) return;
|
||||||
|
|
||||||
|
for(a=0; strandnodes[a].strand; a++) {
|
||||||
|
MEM_freeN(strandnodes[a].strand);
|
||||||
|
|
||||||
|
if(strandnodes[a].uv)
|
||||||
|
MEM_freeN(strandnodes[a].uv);
|
||||||
|
if(strandnodes[a].mcol)
|
||||||
|
MEM_freeN(strandnodes[a].mcol);
|
||||||
|
if(strandnodes[a].winspeed)
|
||||||
|
MEM_freeN(strandnodes[a].winspeed);
|
||||||
|
if(strandnodes[a].surfnor)
|
||||||
|
MEM_freeN(strandnodes[a].surfnor);
|
||||||
|
if(strandnodes[a].names)
|
||||||
|
MEM_freeN(strandnodes[a].names);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeN(strandnodes);
|
||||||
|
}
|
||||||
|
|
||||||
void free_renderdata_tables(Render *re)
|
void free_renderdata_tables(Render *re)
|
||||||
{
|
{
|
||||||
int a=0;
|
StrandBuffer *strandbuf;
|
||||||
CustomDataNames *cdn;
|
CustomDataNames *cdn;
|
||||||
|
int a=0;
|
||||||
|
|
||||||
if(re->bloha) {
|
if(re->bloha) {
|
||||||
for(a=0; re->bloha[a]; a++)
|
for(a=0; re->bloha[a]; a++)
|
||||||
@@ -566,6 +796,17 @@ void free_renderdata_tables(Render *re)
|
|||||||
re->vlaknodeslen= 0;
|
re->vlaknodeslen= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(re->strandnodes) {
|
||||||
|
free_renderdata_strandnodes(re->strandnodes);
|
||||||
|
re->strandnodes= NULL;
|
||||||
|
re->strandnodeslen= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(re->strandbuckets) {
|
||||||
|
free_buckets(re->strandbuckets);
|
||||||
|
re->strandbuckets= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
for(cdn=re->customdata_names.first; cdn; cdn=cdn->next) {
|
for(cdn=re->customdata_names.first; cdn; cdn=cdn->next) {
|
||||||
if(cdn->mtface)
|
if(cdn->mtface)
|
||||||
MEM_freeN(cdn->mtface);
|
MEM_freeN(cdn->mtface);
|
||||||
@@ -573,6 +814,10 @@ void free_renderdata_tables(Render *re)
|
|||||||
MEM_freeN(cdn->mcol);
|
MEM_freeN(cdn->mcol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(strandbuf=re->strandbufs.first; strandbuf; strandbuf=strandbuf->next)
|
||||||
|
if(strandbuf->vert) MEM_freeN(strandbuf->vert);
|
||||||
|
BLI_freelistN(&re->strandbufs);
|
||||||
|
|
||||||
BLI_freelistN(&re->customdata_names);
|
BLI_freelistN(&re->customdata_names);
|
||||||
BLI_freelistN(&re->objecttable);
|
BLI_freelistN(&re->objecttable);
|
||||||
}
|
}
|
||||||
@@ -906,14 +1151,14 @@ static int panotestclip(Render *re, int do_pano, float *v)
|
|||||||
- shadow buffering (shadbuf.c)
|
- shadow buffering (shadbuf.c)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs)
|
void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets)
|
||||||
{
|
{
|
||||||
VlakRen *vlr = NULL;
|
VlakRen *vlr = NULL;
|
||||||
VertRen *ver = NULL;
|
VertRen *ver = NULL;
|
||||||
HaloRen *har = NULL;
|
HaloRen *har = NULL;
|
||||||
float zn, vec[3], hoco[4];
|
float zn, vec[3], hoco[4];
|
||||||
int a;
|
int a;
|
||||||
|
|
||||||
if(do_pano) {
|
if(do_pano) {
|
||||||
float panophi= xoffs;
|
float panophi= xoffs;
|
||||||
|
|
||||||
@@ -1029,6 +1274,7 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4],
|
|||||||
vlr->flag &= ~R_VISIBLE;
|
vlr->flag &= ~R_VISIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project_strands(re, projectfunc, do_pano, do_buckets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ void makeshadowbuf(Render *re, LampRen *lar)
|
|||||||
/* temp, will be restored */
|
/* temp, will be restored */
|
||||||
MTC_Mat4SwapMat4(shb->persmat, re->winmat);
|
MTC_Mat4SwapMat4(shb->persmat, re->winmat);
|
||||||
|
|
||||||
project_renderdata(re, projectvert, 0, 0);
|
project_renderdata(re, projectvert, 0, 0, 0);
|
||||||
|
|
||||||
/* zbuffering */
|
/* zbuffering */
|
||||||
rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf");
|
rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf");
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#include "rendercore.h"
|
#include "rendercore.h"
|
||||||
#include "shadbuf.h"
|
#include "shadbuf.h"
|
||||||
#include "shading.h"
|
#include "shading.h"
|
||||||
|
#include "strand.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||||
@@ -300,6 +301,252 @@ void shade_input_copy_triangle(ShadeInput *shi, ShadeInput *from)
|
|||||||
memcpy(shi, from, sizeof(struct ShadeInputCopy));
|
memcpy(shi, from, sizeof(struct ShadeInputCopy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy data from strand to shadeinput */
|
||||||
|
void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spoint)
|
||||||
|
{
|
||||||
|
/* note, shi->mat is set in node shaders */
|
||||||
|
shi->mat= shi->mat_override? shi->mat_override: strand->buffer->ma;
|
||||||
|
|
||||||
|
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);
|
||||||
|
Normalize(shi->view);
|
||||||
|
|
||||||
|
shi->xs= (int)spoint->x;
|
||||||
|
shi->ys= (int)spoint->y;
|
||||||
|
|
||||||
|
if(shi->osatex || (R.r.mode & R_SHADOW)) {
|
||||||
|
VECCOPY(shi->dxco, spoint->dtco);
|
||||||
|
VECCOPY(shi->dyco, spoint->dsco);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dxview, dyview, not supported */
|
||||||
|
|
||||||
|
/* facenormal, simply viewco flipped */
|
||||||
|
VECCOPY(shi->facenor, spoint->nor);
|
||||||
|
VECCOPY(shi->orignor, shi->facenor);
|
||||||
|
|
||||||
|
/* shade_input_set_normals equivalent */
|
||||||
|
if(shi->mat->mode & MA_TANGENT_STR)
|
||||||
|
VECCOPY(shi->vn, spoint->tan)
|
||||||
|
else
|
||||||
|
VECCOPY(shi->vn, spoint->nor)
|
||||||
|
|
||||||
|
VECCOPY(shi->vno, shi->vn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert *svert, StrandPoint *spoint)
|
||||||
|
{
|
||||||
|
StrandBuffer *strandbuf= strand->buffer;
|
||||||
|
StrandVert *sv;
|
||||||
|
int mode= shi->mode; /* or-ed result for all nodes */
|
||||||
|
short texco= shi->mat->texco;
|
||||||
|
|
||||||
|
if((shi->mat->texco & TEXCO_REFL)) {
|
||||||
|
/* shi->dxview, shi->dyview, not supported */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shi->osatex && (texco & (TEXCO_NORM|TEXCO_REFL))) {
|
||||||
|
/* not supported */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode & (MA_TANGENT_V|MA_NORMAP_TANG)) {
|
||||||
|
VECCOPY(shi->tang, spoint->tan);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode & MA_STR_SURFDIFF) {
|
||||||
|
float *surfnor= RE_strandren_get_surfnor(&R, strand, 0);
|
||||||
|
|
||||||
|
if(surfnor)
|
||||||
|
VECCOPY(shi->surfnor, surfnor)
|
||||||
|
else
|
||||||
|
VECCOPY(shi->surfnor, shi->vn)
|
||||||
|
|
||||||
|
if(shi->mat->strand_surfnor > 0.0f) {
|
||||||
|
shi->surfdist= 0.0f;
|
||||||
|
for(sv=strand->vert; sv!=svert; sv++)
|
||||||
|
shi->surfdist+=VecLenf(sv->co, (sv+1)->co);
|
||||||
|
shi->surfdist += 0.5f*(spoint->strandco+1.0f)*VecLenf(sv->co, (sv+1)->co);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(R.r.mode & R_SPEED) {
|
||||||
|
float *speed;
|
||||||
|
|
||||||
|
speed= RE_strandren_get_winspeed(&R, strand, 0);
|
||||||
|
if(speed)
|
||||||
|
QUATCOPY(shi->winspeed, speed)
|
||||||
|
else
|
||||||
|
shi->winspeed[0]= shi->winspeed[1]= shi->winspeed[2]= shi->winspeed[3]= 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shade_input_set_shade_texco equivalent */
|
||||||
|
if(texco & NEED_UV) {
|
||||||
|
if(texco & TEXCO_ORCO) {
|
||||||
|
VECCOPY(shi->lo, strand->orco);
|
||||||
|
/* no shi->osatex, orco derivatives are zero */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texco & TEXCO_GLOB) {
|
||||||
|
VECCOPY(shi->gl, shi->co);
|
||||||
|
MTC_Mat4MulVecfl(R.viewinv, shi->gl);
|
||||||
|
|
||||||
|
if(shi->osatex) {
|
||||||
|
VECCOPY(shi->dxgl, shi->dxco);
|
||||||
|
MTC_Mat3MulVecfl(R.imat, shi->dxco);
|
||||||
|
VECCOPY(shi->dygl, shi->dyco);
|
||||||
|
MTC_Mat3MulVecfl(R.imat, shi->dyco);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texco & TEXCO_STRAND) {
|
||||||
|
shi->strand= spoint->strandco;
|
||||||
|
|
||||||
|
if(shi->osatex) {
|
||||||
|
shi->dxstrand= spoint->dtstrandco;
|
||||||
|
shi->dystrand= 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE))) {
|
||||||
|
MCol *mcol;
|
||||||
|
float *uv;
|
||||||
|
char *name;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
shi->totuv= 0;
|
||||||
|
shi->totcol= 0;
|
||||||
|
|
||||||
|
if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) {
|
||||||
|
for (i=0; (mcol=RE_strandren_get_mcol(&R, strand, i, &name, 0)); i++) {
|
||||||
|
ShadeInputCol *scol= &shi->col[i];
|
||||||
|
char *cp= (char*)mcol;
|
||||||
|
|
||||||
|
shi->totcol++;
|
||||||
|
scol->name= name;
|
||||||
|
|
||||||
|
scol->col[0]= cp[0]/255.0f;
|
||||||
|
scol->col[1]= cp[1]/255.0f;
|
||||||
|
scol->col[2]= cp[2]/255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shi->totcol) {
|
||||||
|
shi->vcol[0]= shi->col[0].col[0];
|
||||||
|
shi->vcol[1]= shi->col[0].col[1];
|
||||||
|
shi->vcol[2]= shi->col[0].col[2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
shi->vcol[0]= 0.0f;
|
||||||
|
shi->vcol[1]= 0.0f;
|
||||||
|
shi->vcol[2]= 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; (uv=RE_strandren_get_uv(&R, strand, i, &name, 0)); i++) {
|
||||||
|
ShadeInputUV *suv= &shi->uv[i];
|
||||||
|
|
||||||
|
shi->totuv++;
|
||||||
|
suv->name= name;
|
||||||
|
|
||||||
|
if(strandbuf->overrideuv == i) {
|
||||||
|
suv->uv[0]= -1.0f;
|
||||||
|
suv->uv[1]= spoint->strandco;
|
||||||
|
suv->uv[2]= 0.0f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
suv->uv[0]= -1.0f + 2.0f*uv[0];
|
||||||
|
suv->uv[1]= -1.0f + 2.0f*uv[1];
|
||||||
|
suv->uv[2]= 0.0f; /* texture.c assumes there are 3 coords */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shi->osatex) {
|
||||||
|
suv->dxuv[0]= 0.0f;
|
||||||
|
suv->dxuv[1]= 0.0f;
|
||||||
|
suv->dyuv[0]= 0.0f;
|
||||||
|
suv->dyuv[1]= 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((mode & MA_FACETEXTURE) && i==0) {
|
||||||
|
if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) {
|
||||||
|
shi->vcol[0]= 1.0f;
|
||||||
|
shi->vcol[1]= 1.0f;
|
||||||
|
shi->vcol[2]= 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shi->totuv == 0) {
|
||||||
|
ShadeInputUV *suv= &shi->uv[0];
|
||||||
|
|
||||||
|
suv->uv[0]= 0.0f;
|
||||||
|
suv->uv[1]= spoint->strandco;
|
||||||
|
suv->uv[2]= 0.0f; /* texture.c assumes there are 3 coords */
|
||||||
|
|
||||||
|
if(mode & MA_FACETEXTURE) {
|
||||||
|
/* no tface? set at 1.0f */
|
||||||
|
shi->vcol[0]= 1.0f;
|
||||||
|
shi->vcol[1]= 1.0f;
|
||||||
|
shi->vcol[2]= 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texco & TEXCO_NORM) {
|
||||||
|
shi->orn[0]= -shi->vn[0];
|
||||||
|
shi->orn[1]= -shi->vn[1];
|
||||||
|
shi->orn[2]= -shi->vn[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode & MA_RADIO) {
|
||||||
|
/* not supported */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texco & TEXCO_REFL) {
|
||||||
|
/* mirror reflection color textures (and envmap) */
|
||||||
|
calc_R_ref(shi); /* wrong location for normal maps! XXXXXXXXXXXXXX */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texco & TEXCO_STRESS) {
|
||||||
|
/* not supported */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texco & TEXCO_TANGENT) {
|
||||||
|
if((mode & MA_TANGENT_V)==0) {
|
||||||
|
/* just prevent surprises */
|
||||||
|
shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f;
|
||||||
|
|
||||||
|
/* this only avalailable for scanline renders */
|
||||||
|
if(shi->depth==0) {
|
||||||
|
if(texco & TEXCO_WINDOW) {
|
||||||
|
shi->winco[0]= -1.0f + 2.0f*spoint->x/(float)R.winx;
|
||||||
|
shi->winco[1]= -1.0f + 2.0f*spoint->y/(float)R.winy;
|
||||||
|
shi->winco[2]= 0.0f;
|
||||||
|
|
||||||
|
/* not supported */
|
||||||
|
if(shi->osatex) {
|
||||||
|
shi->dxwin[0]= 0.0f;
|
||||||
|
shi->dywin[1]= 0.0f;
|
||||||
|
shi->dxwin[0]= 0.0f;
|
||||||
|
shi->dywin[1]= 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texco & TEXCO_STICKY) {
|
||||||
|
/* not supported */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* scanline pixel coordinates */
|
/* scanline pixel coordinates */
|
||||||
/* requires set_triangle */
|
/* requires set_triangle */
|
||||||
@@ -571,6 +818,17 @@ void shade_input_set_shade_texco(ShadeInput *shi)
|
|||||||
else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
|
else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mode & MA_STR_SURFDIFF) {
|
||||||
|
float *surfnor= RE_vlakren_get_surfnor(&R, shi->vlr, 0);
|
||||||
|
|
||||||
|
if(surfnor)
|
||||||
|
VECCOPY(shi->surfnor, surfnor)
|
||||||
|
else
|
||||||
|
VECCOPY(shi->surfnor, shi->vn)
|
||||||
|
|
||||||
|
shi->surfdist= 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if(R.r.mode & R_SPEED) {
|
if(R.r.mode & R_SPEED) {
|
||||||
float *s1, *s2, *s3;
|
float *s1, *s2, *s3;
|
||||||
|
|||||||
@@ -1212,13 +1212,35 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int
|
|||||||
lacol[2]= lar->b;
|
lacol[2]= lar->b;
|
||||||
|
|
||||||
if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol);
|
if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol);
|
||||||
|
|
||||||
/* tangent case; calculate fake face normal, aligned with lampvector */
|
/* tangent case; calculate fake face normal, aligned with lampvector */
|
||||||
/* note, vnor==vn is used as tangent trigger for buffer shadow */
|
/* note, vnor==vn is used as tangent trigger for buffer shadow */
|
||||||
if(vlr->flag & R_TANGENT) {
|
if(vlr->flag & R_TANGENT) {
|
||||||
float cross[3];
|
float cross[3], nstrand[3], blend;
|
||||||
Crossf(cross, lv, vn);
|
|
||||||
Crossf(vnor, cross, vn);
|
if(ma->mode & MA_STR_SURFDIFF) {
|
||||||
|
Crossf(cross, shi->surfnor, vn);
|
||||||
|
Crossf(nstrand, vn, cross);
|
||||||
|
|
||||||
|
blend= INPR(nstrand, shi->surfnor);
|
||||||
|
CLAMP(blend, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
VecLerpf(vnor, nstrand, shi->surfnor, blend);
|
||||||
|
Normalize(vnor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Crossf(cross, lv, vn);
|
||||||
|
Crossf(vnor, cross, vn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ma->strand_surfnor > 0.0f) {
|
||||||
|
if(ma->strand_surfnor > shi->surfdist) {
|
||||||
|
blend= (ma->strand_surfnor - shi->surfdist)/ma->strand_surfnor;
|
||||||
|
VecLerpf(vnor, vnor, shi->surfnor, blend);
|
||||||
|
Normalize(vnor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
|
vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
|
||||||
vn= vnor;
|
vn= vnor;
|
||||||
}
|
}
|
||||||
|
|||||||
1138
source/blender/render/intern/source/strand.c
Normal file
1138
source/blender/render/intern/source/strand.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -39,8 +39,8 @@
|
|||||||
|
|
||||||
#include "BLI_arithb.h"
|
#include "BLI_arithb.h"
|
||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
#include "BLI_threads.h"
|
|
||||||
#include "BLI_jitter.h"
|
#include "BLI_jitter.h"
|
||||||
|
#include "BLI_threads.h"
|
||||||
|
|
||||||
#include "MTC_matrixops.h"
|
#include "MTC_matrixops.h"
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
@@ -69,6 +69,7 @@
|
|||||||
#include "shadbuf.h"
|
#include "shadbuf.h"
|
||||||
#include "shading.h"
|
#include "shading.h"
|
||||||
#include "sss.h"
|
#include "sss.h"
|
||||||
|
#include "strand.h"
|
||||||
|
|
||||||
/* own includes */
|
/* own includes */
|
||||||
#include "zbuf.h"
|
#include "zbuf.h"
|
||||||
@@ -861,7 +862,7 @@ static int clipline(float *v1, float *v2) /* return 0: do not draw */
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco)
|
void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco)
|
||||||
{
|
{
|
||||||
float div;
|
float div;
|
||||||
|
|
||||||
@@ -977,6 +978,34 @@ void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2)
|
||||||
|
{
|
||||||
|
float f1[4], f2[4];
|
||||||
|
int c1, c2;
|
||||||
|
|
||||||
|
c1= testclip(ho1);
|
||||||
|
c2= testclip(ho2);
|
||||||
|
|
||||||
|
if(c1 | c2) { /* not in the middle */
|
||||||
|
if(!(c1 & c2)) { /* not out completely */
|
||||||
|
QUATCOPY(f1, ho1);
|
||||||
|
QUATCOPY(f2, ho2);
|
||||||
|
|
||||||
|
if(clipline(f1, f2)) {
|
||||||
|
hoco_to_zco(zspan, f1, f1);
|
||||||
|
hoco_to_zco(zspan, f2, f2);
|
||||||
|
zspan->zbuflinefunc(zspan, zvlnr, f1, f2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hoco_to_zco(zspan, f1, ho1);
|
||||||
|
hoco_to_zco(zspan, f2, ho2);
|
||||||
|
|
||||||
|
zspan->zbuflinefunc(zspan, zvlnr, f1, f2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the z buffer, but invert z order, and add the face index to
|
* Fill the z buffer, but invert z order, and add the face index to
|
||||||
* the corresponing face buffer.
|
* the corresponing face buffer.
|
||||||
@@ -1312,7 +1341,105 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, floa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 2d scanconvert for tria, calls func for each x,y coordinate and gives UV barycentrics */
|
/* 2d scanconvert for tria, calls func for each x,y coordinate and gives UV barycentrics */
|
||||||
/* zspan should be initialized, has rect size and span buffers */
|
void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) )
|
||||||
|
{
|
||||||
|
float x0, y0, x1, y1, x2, y2, z0, z1, z2, z;
|
||||||
|
float u, v, uxd, uyd, vxd, vyd, uy0, vy0, zxd, zyd, zy0, xx1;
|
||||||
|
float *span1, *span2;
|
||||||
|
int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
|
||||||
|
|
||||||
|
/* init */
|
||||||
|
zbuf_init_span(zspan);
|
||||||
|
|
||||||
|
/* set spans */
|
||||||
|
zbuf_add_to_span(zspan, v1, v2);
|
||||||
|
zbuf_add_to_span(zspan, v2, v3);
|
||||||
|
zbuf_add_to_span(zspan, v3, v1);
|
||||||
|
|
||||||
|
/* clipped */
|
||||||
|
if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
|
||||||
|
|
||||||
|
if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
|
||||||
|
if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
|
||||||
|
|
||||||
|
// printf("my %d %d\n", my0, my2);
|
||||||
|
if(my2<my0) return;
|
||||||
|
|
||||||
|
/* ZBUF DX DY, in floats still */
|
||||||
|
x1= v1[0]- v2[0];
|
||||||
|
x2= v2[0]- v3[0];
|
||||||
|
y1= v1[1]- v2[1];
|
||||||
|
y2= v2[1]- v3[1];
|
||||||
|
z1= v1[2]- v2[2];
|
||||||
|
z2= v2[2]- v3[2];
|
||||||
|
|
||||||
|
x0= y1*z2-z1*y2;
|
||||||
|
y0= z1*x2-x1*z2;
|
||||||
|
z0= x1*y2-y1*x2;
|
||||||
|
|
||||||
|
if(z0==0.0f) return;
|
||||||
|
|
||||||
|
xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
|
||||||
|
zxd= -(double)x0/(double)z0;
|
||||||
|
zyd= -(double)y0/(double)z0;
|
||||||
|
zy0= ((double)my2)*zyd + (double)xx1;
|
||||||
|
|
||||||
|
z1= 1.0f; // (u1 - u2)
|
||||||
|
z2= 0.0f; // (u2 - u3)
|
||||||
|
|
||||||
|
x0= y1*z2-z1*y2;
|
||||||
|
y0= z1*x2-x1*z2;
|
||||||
|
|
||||||
|
xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f;
|
||||||
|
uxd= -(double)x0/(double)z0;
|
||||||
|
uyd= -(double)y0/(double)z0;
|
||||||
|
uy0= ((double)my2)*uyd + (double)xx1;
|
||||||
|
|
||||||
|
z1= -1.0f; // (v1 - v2)
|
||||||
|
z2= 1.0f; // (v2 - v3)
|
||||||
|
|
||||||
|
x0= y1*z2-z1*y2;
|
||||||
|
y0= z1*x2-x1*z2;
|
||||||
|
|
||||||
|
xx1= (x0*v1[0] + y0*v1[1])/z0;
|
||||||
|
vxd= -(double)x0/(double)z0;
|
||||||
|
vyd= -(double)y0/(double)z0;
|
||||||
|
vy0= ((double)my2)*vyd + (double)xx1;
|
||||||
|
|
||||||
|
/* correct span */
|
||||||
|
sn1= (my0 + my2)/2;
|
||||||
|
if(zspan->span1[sn1] < zspan->span2[sn1]) {
|
||||||
|
span1= zspan->span1+my2;
|
||||||
|
span2= zspan->span2+my2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
span1= zspan->span2+my2;
|
||||||
|
span2= zspan->span1+my2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(y=my2; y>=my0; y--, span1--, span2--) {
|
||||||
|
|
||||||
|
sn1= floor(*span1);
|
||||||
|
sn2= floor(*span2);
|
||||||
|
sn1++;
|
||||||
|
|
||||||
|
if(sn2>=rectx) sn2= rectx-1;
|
||||||
|
if(sn1<0) sn1= 0;
|
||||||
|
|
||||||
|
u= (double)sn1*uxd + uy0;
|
||||||
|
v= (double)sn1*vxd + vy0;
|
||||||
|
z= (double)sn1*zxd + zy0;
|
||||||
|
|
||||||
|
for(x= sn1; x<=sn2; x++, u+=uxd, v+=vxd, z+=zxd)
|
||||||
|
func(handle, x, y, u, v, z);
|
||||||
|
|
||||||
|
uy0 -= uyd;
|
||||||
|
vy0 -= vyd;
|
||||||
|
zy0 -= zyd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scanconvert for strand triangles, calls func for each x,y coordinate and gives UV barycentrics and z */
|
||||||
|
|
||||||
void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) )
|
void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) )
|
||||||
{
|
{
|
||||||
@@ -1957,7 +2084,10 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx,
|
|||||||
ZSpan zspan;
|
ZSpan zspan;
|
||||||
VlakRen *vlr= NULL;
|
VlakRen *vlr= NULL;
|
||||||
Material *ma= NULL;
|
Material *ma= NULL;
|
||||||
int a, ok=1, lay= -1;
|
StrandSegment sseg;
|
||||||
|
StrandRen *strand= NULL;
|
||||||
|
StrandVert *svert;
|
||||||
|
int a, b, ok=1, lay= -1;
|
||||||
|
|
||||||
if(lar->mode & LA_LAYER) lay= lar->lay;
|
if(lar->mode & LA_LAYER) lay= lar->lay;
|
||||||
|
|
||||||
@@ -2002,6 +2132,39 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shadow */
|
||||||
|
for(a=0; a<re->totstrand; a++) {
|
||||||
|
if((a & 255)==0) strand= re->strandnodes[a>>8].strand;
|
||||||
|
else strand++;
|
||||||
|
|
||||||
|
if(strand->clip)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sseg.buffer= strand->buffer;
|
||||||
|
sseg.sqadaptcos= sseg.buffer->adaptcos;
|
||||||
|
sseg.sqadaptcos *= sseg.sqadaptcos;
|
||||||
|
sseg.strand= strand;
|
||||||
|
svert= strand->vert;
|
||||||
|
|
||||||
|
/* note, these conditions are copied in shadowbuf_autoclip() */
|
||||||
|
if(sseg.buffer->ma!= ma) {
|
||||||
|
ma= sseg.buffer->ma;
|
||||||
|
ok= 1;
|
||||||
|
if((ma->mode & MA_SHADBUF)==0) ok= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ok && (sseg.buffer->lay & lay)) {
|
||||||
|
for(b=0; b<strand->totvert-1; b++, svert++) {
|
||||||
|
sseg.v[0]= (b > 0)? (svert-1): svert;
|
||||||
|
sseg.v[1]= svert;
|
||||||
|
sseg.v[2]= svert+1;
|
||||||
|
sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1;
|
||||||
|
|
||||||
|
render_strand_segment(re, NULL, &zspan, &sseg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* merge buffers */
|
/* merge buffers */
|
||||||
if(lar->buftype==LA_SHADBUF_HALFWAY) {
|
if(lar->buftype==LA_SHADBUF_HALFWAY) {
|
||||||
@@ -2019,7 +2182,6 @@ static void zbuffill_sss(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v
|
|||||||
double zxd, zyd, zy0, z;
|
double zxd, zyd, zy0, z;
|
||||||
float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2;
|
float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2;
|
||||||
int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
|
int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
zbuf_init_span(zspan);
|
zbuf_init_span(zspan);
|
||||||
|
|
||||||
@@ -2824,7 +2986,7 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un
|
|||||||
/* speed pointer NULL = sky, we clear */
|
/* speed pointer NULL = sky, we clear */
|
||||||
/* else if either alpha is full or no solid was filled in: copy speed */
|
/* else if either alpha is full or no solid was filled in: copy speed */
|
||||||
/* else fill in minimum speed */
|
/* else fill in minimum speed */
|
||||||
static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect)
|
void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect)
|
||||||
{
|
{
|
||||||
RenderPass *rpass;
|
RenderPass *rpass;
|
||||||
|
|
||||||
@@ -2852,7 +3014,6 @@ static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float al
|
|||||||
fp[2]= speed[2];
|
fp[2]= speed[2];
|
||||||
fp[3]= speed[3];
|
fp[3]= speed[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2877,7 +3038,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, int facenr)
|
|||||||
|
|
||||||
/* ONLY OSA! merge all shaderesult samples to one */
|
/* ONLY OSA! merge all shaderesult samples to one */
|
||||||
/* target should have been cleared */
|
/* target should have been cleared */
|
||||||
static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr)
|
void merge_transp_passes(RenderLayer *rl, ShadeResult *shr)
|
||||||
{
|
{
|
||||||
RenderPass *rpass;
|
RenderPass *rpass;
|
||||||
float weight= 1.0f/((float)R.osa);
|
float weight= 1.0f/((float)R.osa);
|
||||||
@@ -2961,7 +3122,7 @@ static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha)
|
void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha)
|
||||||
{
|
{
|
||||||
RenderPass *rpass;
|
RenderPass *rpass;
|
||||||
|
|
||||||
@@ -3113,11 +3274,11 @@ static void addvecmul(float *v1, float *v2, float fac)
|
|||||||
v1[2]= v1[2]+fac*v2[2];
|
v1[2]= v1[2]+fac*v2[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag)
|
int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag)
|
||||||
{
|
{
|
||||||
int a, sample, retval = R.osa;
|
int a, sample, osa = (R.osa? R.osa: 1), retval = osa;
|
||||||
|
|
||||||
for(a=0; a < R.osa; a++, samp_shr++) {
|
for(a=0; a < osa; a++, samp_shr++) {
|
||||||
ShadeInput *shi= ssamp->shi;
|
ShadeInput *shi= ssamp->shi;
|
||||||
ShadeResult *shr= ssamp->shr;
|
ShadeResult *shr= ssamp->shr;
|
||||||
|
|
||||||
@@ -3159,7 +3320,7 @@ static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassf
|
|||||||
addvecmul(samp_shr->refr, shr->refr, fac);
|
addvecmul(samp_shr->refr, shr->refr, fac);
|
||||||
|
|
||||||
if(addpassflag & SCE_PASS_RADIO)
|
if(addpassflag & SCE_PASS_RADIO)
|
||||||
addvecmul(samp_shr->refr, shr->rad, fac);
|
addvecmul(samp_shr->rad, shr->rad, fac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3169,7 +3330,7 @@ static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassf
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl)
|
void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf)
|
||||||
{
|
{
|
||||||
/* speed vector exception... if solid render was done, sky pixels are set to zero already */
|
/* speed vector exception... if solid render was done, sky pixels are set to zero already */
|
||||||
/* for all pixels with alpha zero, we re-initialize speed again then */
|
/* for all pixels with alpha zero, we re-initialize speed again then */
|
||||||
@@ -3178,7 +3339,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl)
|
|||||||
|
|
||||||
fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR);
|
fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR);
|
||||||
if(fp==NULL) return;
|
if(fp==NULL) return;
|
||||||
col= rl->acolrect+3;
|
col= rectf+3;
|
||||||
|
|
||||||
for(a= 4*pa->rectx*pa->recty -4; a>=0; a-=4) {
|
for(a= 4*pa->rectx*pa->recty -4; a>=0; a-=4) {
|
||||||
if(col[a]==0.0f) {
|
if(col[a]==0.0f) {
|
||||||
@@ -3222,7 +3383,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
|
|||||||
/* general shader info, passes */
|
/* general shader info, passes */
|
||||||
shade_sample_initialize(&ssamp, pa, rl);
|
shade_sample_initialize(&ssamp, pa, rl);
|
||||||
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
|
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
|
||||||
addzbuf= rl->passflag & SCE_PASS_Z;
|
if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first)
|
||||||
|
addzbuf= 1; /* strands layer needs the z-buffer */
|
||||||
|
else
|
||||||
|
addzbuf= rl->passflag & SCE_PASS_Z;
|
||||||
|
|
||||||
if(R.osa)
|
if(R.osa)
|
||||||
sampalpha= 1.0f/(float)R.osa;
|
sampalpha= 1.0f/(float)R.osa;
|
||||||
@@ -3251,7 +3415,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
|
|||||||
/* zero alpha pixels get speed vector max again */
|
/* zero alpha pixels get speed vector max again */
|
||||||
if(addpassflag & SCE_PASS_VECTOR)
|
if(addpassflag & SCE_PASS_VECTOR)
|
||||||
if(rl->layflag & SCE_LAY_SOLID)
|
if(rl->layflag & SCE_LAY_SOLID)
|
||||||
reset_sky_speedvectors(pa, rl);
|
reset_sky_speedvectors(pa, rl, rl->acolrect);
|
||||||
|
|
||||||
/* filtered render, for now we assume only 1 filter size */
|
/* filtered render, for now we assume only 1 filter size */
|
||||||
if(pa->crop) {
|
if(pa->crop) {
|
||||||
|
|||||||
@@ -3603,8 +3603,7 @@ static void object_panel_particle_children(Object *ob)
|
|||||||
uiNewPanelTabbed("Extras", "Particle");
|
uiNewPanelTabbed("Extras", "Particle");
|
||||||
if(uiNewPanel(curarea, block, "Children", "Particle", 1300, 0, 318, 204)==0) return;
|
if(uiNewPanel(curarea, block, "Children", "Particle", 1300, 0, 318, 204)==0) return;
|
||||||
|
|
||||||
uiDefButS(block, MENU, B_PART_ALLOC_CHILD, "Children from:%t|Faces%x2|Particles%x1|None%x0", butx,buty,butw/2,buth, &part->childtype, 14.0, 0.0, 0, 0, "Create child particles");
|
uiDefButS(block, MENU, B_PART_ALLOC_CHILD, "Children from:%t|Faces%x2|Particles%x1|None%x0", butx,buty,butw,buth, &part->childtype, 14.0, 0.0, 0, 0, "Create child particles");
|
||||||
uiDefButBitI(block, TOG, PART_CHILD_RENDER, B_PART_RECALC_CHILD, "Only Render", butx+butw/2,buty,butw/2,buth, &part->flag, 0, 0, 0, 0, "Create child particles only when rendering");
|
|
||||||
|
|
||||||
if(part->childtype==0) return;
|
if(part->childtype==0) return;
|
||||||
|
|
||||||
@@ -3615,26 +3614,32 @@ static void object_panel_particle_children(Object *ob)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
|
|
||||||
|
buty -= buth/2;
|
||||||
|
|
||||||
|
uiDefButI(block, NUM, B_PART_ALLOC_CHILD, "Amount:", butx,(buty-=buth),butw,buth, &part->child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent");
|
||||||
|
uiDefButI(block, NUM, B_DIFF, "Render Amount:", butx,(buty-=buth),butw,buth, &part->ren_child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent for rendering");
|
||||||
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES) {
|
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES) {
|
||||||
uiDefButI(block, NUM, B_PART_ALLOC_CHILD, "Amount:", butx,(buty-=2*buth),butw,buth, &part->child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent");
|
|
||||||
uiDefButF(block, NUMSLI, B_PART_DISTR_CHILD, "VParents:", butx,(buty-=buth),butw,buth, &part->parents, 0.0, 1.0, 1, 3, "Relative amount of virtual parents");
|
uiDefButF(block, NUMSLI, B_PART_DISTR_CHILD, "VParents:", butx,(buty-=buth),butw,buth, &part->parents, 0.0, 1.0, 1, 3, "Relative amount of virtual parents");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uiDefButI(block, NUM, B_PART_ALLOC_CHILD, "Amount:", butx,(buty-=2*buth),butw,buth, &part->child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent");
|
|
||||||
uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Rad:", butx,(buty-=buth),butw,buth, &part->childrad, 0.0, 10.0, 1, 3, "Radius of children around parent");
|
uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Rad:", butx,(buty-=buth),butw,buth, &part->childrad, 0.0, 10.0, 1, 3, "Radius of children around parent");
|
||||||
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Round:", butx,(buty-=buth),butw,buth, &part->childflat, 0.0, 1.0, 1, 3, "Roundness of children around parent");
|
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Round:", butx,(buty-=buth),butw,buth, &part->childflat, 0.0, 1.0, 1, 3, "Roundness of children around parent");
|
||||||
}
|
}
|
||||||
uiBlockEndAlign(block);
|
uiBlockEndAlign(block);
|
||||||
|
|
||||||
|
buty -= buth/2;
|
||||||
|
|
||||||
/* clump */
|
/* clump */
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Clump:", butx,(buty-=buth),butw,buth, &part->clumpfac, -1.0, 1.0, 1, 3, "Amount of clumpimg");
|
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Clump:", butx,(buty-=buth),butw,buth, &part->clumpfac, -1.0, 1.0, 1, 3, "Amount of clumpimg");
|
||||||
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Shape:", butx,(buty-=buth),butw,buth, &part->clumppow, -0.999, 0.999, 1, 3, "Shape of clumpimg");
|
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Shape:", butx,(buty-=buth),butw,buth, &part->clumppow, -0.999, 0.999, 1, 3, "Shape of clumpimg");
|
||||||
uiBlockEndAlign(block);
|
uiBlockEndAlign(block);
|
||||||
|
|
||||||
|
buty -= buth/2;
|
||||||
|
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButF(block, NUM, B_PART_REDRAW, "Size:", butx,(buty-=2*buth),butw/2,buth, &part->childsize, 0.01, 100, 10, 1, "A multiplier for the child particle size");
|
uiDefButF(block, NUM, B_PART_REDRAW, "Size:", butx,(buty-=buth),butw/2,buth, &part->childsize, 0.01, 100, 10, 1, "A multiplier for the child particle size");
|
||||||
uiDefButF(block, NUM, B_PART_REDRAW, "Rand:", butx+butw/2,buty,butw/2,buth, &part->childrandsize, 0.0, 1.0, 10, 1, "Random variation to the size of the child particles");
|
uiDefButF(block, NUM, B_PART_REDRAW, "Rand:", butx+butw/2,buty,butw/2,buth, &part->childrandsize, 0.0, 1.0, 10, 1, "Random variation to the size of the child particles");
|
||||||
if(part->childtype==PART_CHILD_FACES) {
|
if(part->childtype==PART_CHILD_FACES) {
|
||||||
uiDefButF(block, NUM, B_PART_REDRAW, "Spread:",butx,(buty-=buth),butw/2,buth, &part->childspread, -1.0, 1.0, 10, 1, "Spread children from the faces");
|
uiDefButF(block, NUM, B_PART_REDRAW, "Spread:",butx,(buty-=buth),butw/2,buth, &part->childspread, -1.0, 1.0, 10, 1, "Spread children from the faces");
|
||||||
@@ -3645,10 +3650,11 @@ static void object_panel_particle_children(Object *ob)
|
|||||||
butx=160;
|
butx=160;
|
||||||
buty=180;
|
buty=180;
|
||||||
|
|
||||||
|
|
||||||
uiDefButBitS(block, TOG, 1, B_PART_REDRAW, "Kink/Branch", butx,(buty-=buth),butw,buth, &kink_ui, 0, 0, 0, 0, "Show kink and branch options");
|
uiDefButBitS(block, TOG, 1, B_PART_REDRAW, "Kink/Branch", butx,(buty-=buth),butw,buth, &kink_ui, 0, 0, 0, 0, "Show kink and branch options");
|
||||||
|
|
||||||
if(kink_ui) {
|
if(kink_ui) {
|
||||||
|
buty -= buth/2;
|
||||||
|
|
||||||
/* kink */
|
/* kink */
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
if(part->kink) {
|
if(part->kink) {
|
||||||
@@ -3677,15 +3683,19 @@ static void object_panel_particle_children(Object *ob)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* rough */
|
/* rough */
|
||||||
|
buty -= buth/2;
|
||||||
|
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Rough1:", butx,(buty-=2*buth),butw,buth, &part->rough1, 0.0, 10.0, 1, 3, "Amount of location dependant rough");
|
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Rough1:", butx,(buty-=buth),butw,buth, &part->rough1, 0.0, 10.0, 1, 3, "Amount of location dependant rough");
|
||||||
uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Size1:", butx,(buty-=buth),butw,buth, &part->rough1_size, 0.01, 10.0, 1, 3, "Size of location dependant rough");
|
uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Size1:", butx,(buty-=buth),butw,buth, &part->rough1_size, 0.01, 10.0, 1, 3, "Size of location dependant rough");
|
||||||
uiBlockEndAlign(block);
|
uiBlockEndAlign(block);
|
||||||
|
buty -= buth/2;
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Rough2:", butx,(buty-=buth),butw,buth, &part->rough2, 0.0, 10.0, 1, 3, "Amount of random rough");
|
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Rough2:", butx,(buty-=buth),butw,buth, &part->rough2, 0.0, 10.0, 1, 3, "Amount of random rough");
|
||||||
uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Size2:", butx,(buty-=buth),butw,buth, &part->rough2_size, 0.01, 10.0, 1, 3, "Size of random rough");
|
uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Size2:", butx,(buty-=buth),butw,buth, &part->rough2_size, 0.01, 10.0, 1, 3, "Size of random rough");
|
||||||
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Thresh:", butx,(buty-=buth),butw,buth, &part->rough2_thres, 0.00, 1.0, 1, 3, "Amount of particles left untouched by random rough");
|
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Thresh:", butx,(buty-=buth),butw,buth, &part->rough2_thres, 0.00, 1.0, 1, 3, "Amount of particles left untouched by random rough");
|
||||||
uiBlockEndAlign(block);
|
uiBlockEndAlign(block);
|
||||||
|
buty -= buth/2;
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "RoughE:", butx,(buty-=buth),butw,buth, &part->rough_end, 0.0, 10.0, 1, 3, "Amount of end point rough");
|
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "RoughE:", butx,(buty-=buth),butw,buth, &part->rough_end, 0.0, 10.0, 1, 3, "Amount of end point rough");
|
||||||
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Shape:", butx,(buty-=buth),butw,buth, &part->rough_end_shape, 0.0, 10.0, 1, 3, "Shape of end point rough");
|
uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Shape:", butx,(buty-=buth),butw,buth, &part->rough_end_shape, 0.0, 10.0, 1, 3, "Shape of end point rough");
|
||||||
@@ -3861,7 +3871,7 @@ static void object_panel_particle_visual(Object *ob)
|
|||||||
uiDefBut(block, LABEL, 0, "Render:", butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
|
uiDefBut(block, LABEL, 0, "Render:", butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButS(block, NUM, B_PART_DISTR, "Material:", butx,(buty-=buth),butw-30,buth, &part->omat, 1.0, 16.0, 0, 0, "Specify material used for the particles");
|
uiDefButS(block, NUM, B_PART_DISTR, "Material:", butx,(buty-=buth),butw-30,buth, &part->omat, 1.0, 16.0, 0, 0, "Specify material used for the particles");
|
||||||
uiDefButBitS(block, TOG, PART_DRAW_MAT_COL, B_PART_REDRAW, "Col", butx+butw-30,buty,30,buth, &part->draw, 0, 0, 0, 0, "Draw particles using material's diffuse color");
|
uiDefButBitS(block, TOG, PART_DRAW_MAT_COL, B_PART_RECALC, "Col", butx+butw-30,buty,30,buth, &part->draw, 0, 0, 0, 0, "Draw particles using material's diffuse color");
|
||||||
uiDefButBitS(block, TOG, PART_DRAW_EMITTER, B_PART_REDRAW, "Emitter", butx,(buty-=buth),butw/2,buth, &part->draw, 0, 0, 0, 0, "Render emitter Object also");
|
uiDefButBitS(block, TOG, PART_DRAW_EMITTER, B_PART_REDRAW, "Emitter", butx,(buty-=buth),butw/2,buth, &part->draw, 0, 0, 0, 0, "Render emitter Object also");
|
||||||
uiDefButBitS(block, TOG, PART_DRAW_PARENT, B_PART_REDRAW, "Parents", butx+butw/2,buty,butw/2,buth, &part->draw, 0, 0, 0, 0, "Render parent particles");
|
uiDefButBitS(block, TOG, PART_DRAW_PARENT, B_PART_REDRAW, "Parents", butx+butw/2,buty,butw/2,buth, &part->draw, 0, 0, 0, 0, "Render parent particles");
|
||||||
uiDefButBitI(block, TOG, PART_UNBORN, B_PART_REDRAW, "Unborn", butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Show particles before they are emitted");
|
uiDefButBitI(block, TOG, PART_UNBORN, B_PART_REDRAW, "Unborn", butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Show particles before they are emitted");
|
||||||
@@ -3917,10 +3927,16 @@ static void object_panel_particle_visual(Object *ob)
|
|||||||
uiDefButBitI(block, TOG, PART_HAIR_BSPLINE, B_PART_RECALC, "B-Spline", butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Interpolate hair using B-Splines");
|
uiDefButBitI(block, TOG, PART_HAIR_BSPLINE, B_PART_RECALC, "B-Spline", butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Interpolate hair using B-Splines");
|
||||||
|
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButBitS(block, TOG, PART_DRAW_REN_ADAPT, B_PART_REDRAW, "Adaptive render", butx,buty-=buth,butw,buth, &part->draw, 0, 0, 0, 0, "Draw steps of the particle path");
|
uiDefButBitS(block, TOG, PART_DRAW_REN_STRAND, B_PART_REDRAW, "Strand render", butx,buty-=buth,butw,buth, &part->draw, 0, 0, 0, 0, "Use the strand primitive for rendering");
|
||||||
if(part->draw & PART_DRAW_REN_ADAPT) {
|
if(part->draw & PART_DRAW_REN_STRAND) {
|
||||||
uiDefButS(block, NUM, B_PART_REDRAW, "Angle:", butx,(buty-=buth),butw,buth, &part->adapt_angle, 0.0, 45.0, 0, 0, "How many degrees path has to curve to make another render segment");
|
uiDefButS(block, NUM, B_PART_REDRAW, "Angle:", butx,(buty-=buth),butw,buth, &part->adapt_angle, 0.0, 45.0, 0, 0, "How many degrees path has to curve to make another render segment");
|
||||||
uiDefButS(block, NUM, B_PART_REDRAW, "Pixel:", butx,(buty-=buth),butw,buth, &part->adapt_pix, 0.0, 50.0, 0, 0, "How many pixels path has to cover to make another render segment");
|
}
|
||||||
|
else {
|
||||||
|
uiDefButBitS(block, TOG, PART_DRAW_REN_ADAPT, B_PART_REDRAW, "Adaptive render", butx,buty-=buth,butw,buth, &part->draw, 0, 0, 0, 0, "Draw steps of the particle path");
|
||||||
|
if(part->draw & PART_DRAW_REN_ADAPT) {
|
||||||
|
uiDefButS(block, NUM, B_PART_REDRAW, "Angle:", butx,(buty-=buth),butw/2,buth, &part->adapt_angle, 0.0, 45.0, 0, 0, "How many degrees path has to curve to make another render segment");
|
||||||
|
uiDefButS(block, NUM, B_PART_REDRAW, "Pixel:", butx+butw/2,buty,(butw+1)/2,buth, &part->adapt_pix, 0.0, 50.0, 0, 0, "How many pixels path has to cover to make another render segment");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -1967,11 +1967,12 @@ static void render_panel_layers(void)
|
|||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButBitI(block, TOG, SCE_LAY_ALL_Z, B_NOP,"AllZ", 10, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Fill in Z values for all not-rendered faces, for masking");
|
uiDefButBitI(block, TOG, SCE_LAY_ALL_Z, B_NOP,"AllZ", 10, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Fill in Z values for all not-rendered faces, for masking");
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
uiDefButBitI(block, TOG, SCE_LAY_SOLID, B_NOP,"Solid", 50, 85, 60, 20, &srl->layflag, 0, 0, 0, 0, "Render Solid faces in this Layer");
|
uiDefButBitI(block, TOG, SCE_LAY_SOLID, B_NOP,"Solid", 50, 85, 45, 20, &srl->layflag, 0, 0, 0, 0, "Render Solid faces in this Layer");
|
||||||
uiDefButBitI(block, TOG, SCE_LAY_HALO, B_NOP,"Halo", 110, 85, 55, 20, &srl->layflag, 0, 0, 0, 0, "Render Halos in this Layer (on top of Solid)");
|
uiDefButBitI(block, TOG, SCE_LAY_HALO, B_NOP,"Halo", 95, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Halos in this Layer (on top of Solid)");
|
||||||
uiDefButBitI(block, TOG, SCE_LAY_ZTRA, B_NOP,"Ztra", 165, 85, 55, 20, &srl->layflag, 0, 0, 0, 0, "Render Z-Transparent faces in this Layer (On top of Solid and Halos)");
|
uiDefButBitI(block, TOG, SCE_LAY_ZTRA, B_NOP,"Ztra", 135, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Z-Transparent faces in this Layer (On top of Solid and Halos)");
|
||||||
uiDefButBitI(block, TOG, SCE_LAY_SKY, B_NOP,"Sky", 220, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Sky or backbuffer in this Layer");
|
uiDefButBitI(block, TOG, SCE_LAY_SKY, B_NOP,"Sky", 175, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Sky or backbuffer in this Layer");
|
||||||
uiDefButBitI(block, TOG, SCE_LAY_EDGE, B_NOP,"Edge", 260, 85, 50, 20, &srl->layflag, 0, 0, 0, 0, "Render Edge-enhance in this Layer (only works for Solid faces)");
|
uiDefButBitI(block, TOG, SCE_LAY_EDGE, B_NOP,"Edge", 215, 85, 45, 20, &srl->layflag, 0, 0, 0, 0, "Render Edge-enhance in this Layer (only works for Solid faces)");
|
||||||
|
uiDefButBitI(block, TOG, SCE_LAY_STRAND, B_NOP,"Strand",260, 85, 50, 20, &srl->layflag, 0, 0, 0, 0, "Render Strands in this Layer");
|
||||||
|
|
||||||
uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_SET_PASS, "Light:", 10, 65, 150, 20, &(srl->light_override), "Name of Group to use as Lamps instead");
|
uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_SET_PASS, "Light:", 10, 65, 150, 20, &(srl->light_override), "Name of Group to use as Lamps instead");
|
||||||
uiDefIDPoinBut(block, test_matpoin_but, ID_MA, B_SET_PASS, "Mat:", 160, 65, 150, 20, &(srl->mat_override), "Name of Material to use as Materials instead");
|
uiDefIDPoinBut(block, test_matpoin_but, ID_MA, B_SET_PASS, "Mat:", 160, 65, 150, 20, &(srl->mat_override), "Name of Material to use as Materials instead");
|
||||||
|
|||||||
@@ -3852,25 +3852,30 @@ static uiBlock *strand_menu(void *mat_v)
|
|||||||
{
|
{
|
||||||
Material *ma= mat_v;
|
Material *ma= mat_v;
|
||||||
uiBlock *block;
|
uiBlock *block;
|
||||||
|
|
||||||
block= uiNewBlock(&curarea->uiblocks, "strand menu", UI_EMBOSS, UI_HELV, curarea->win);
|
block= uiNewBlock(&curarea->uiblocks, "strand menu", UI_EMBOSS, UI_HELV, curarea->win);
|
||||||
|
|
||||||
/* use this for a fake extra empy space around the buttons */
|
/* use this for a fake extra empy space around the buttons */
|
||||||
uiDefBut(block, LABEL, 0, "", 0, 0, 250, 120, NULL, 0, 0, 0, 0, "");
|
uiDefBut(block, LABEL, 0, "", 0, 0, 250, 170, NULL, 0, 0, 0, 0, "");
|
||||||
|
|
||||||
|
uiBlockBeginAlign(block);
|
||||||
|
/* event return 0, to prevent menu to close */
|
||||||
|
|
||||||
|
uiDefButBitI(block, TOG, MA_TANGENT_STR, 0, "Use Tangent Shading", 10,140,230,20, &(ma->mode), 0, 0, 0, 0, "Uses direction of strands as normal for tangent-shading");
|
||||||
|
uiDefButBitI(block, TOG, MA_STR_SURFDIFF, 0, "Surface Diffuse", 10,120,115,20, &(ma->mode), 0, 0, 0, 0, "Make diffuse shading more similar to shading the surface");
|
||||||
|
uiDefButF(block, NUM, 0, "Dist", 125,120,115,20, &ma->strand_surfnor, 0.0f, 10.0f, 2, 0, "Distance in Blender units over which to blend in the surface normal");
|
||||||
|
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
/* event return 0, to prevent menu to close */
|
uiDefButBitI(block, TOG, MA_STR_B_UNITS, 0, "Use Blender Units", 10,95,230,20, &(ma->mode), 0, 0, 0, 0, "Use actual Blender units for widths instead of pixels");
|
||||||
uiDefButBitI(block, TOG, MA_TANGENT_STR, 0, "Use Tangent Shading", 10,90,115,20, &(ma->mode), 0, 0, 0, 0, "Uses direction of strands as normal for tangent-shading");
|
if(ma->mode & MA_STR_B_UNITS){
|
||||||
uiDefButBitI(block, TOG, MA_STR_B_UNITS, 0, "Use Blender Units", 125,90,115,20, &(ma->mode), 0, 0, 0, 0, "Use actual Blender units for widths instead of pixels");
|
uiDefButF(block, NUMSLI, 0, "Start ", 10, 75, 230,20, &ma->strand_sta, 0.01, 20.0, 2, 0, "Start size of strands in Blender units");
|
||||||
if(ma->mode & MA_STR_B_UNITS){
|
uiDefButF(block, NUMSLI, 0, "End ", 10, 55, 230,20, &ma->strand_end, 0.01, 10.0, 2, 0, "End size of strands in Blender units");
|
||||||
uiDefButF(block, NUMSLI, 0, "Start ", 10, 70, 230,20, &ma->strand_sta, 0.0001, 2.0, 2, 0, "Start size of strands in Blender units");
|
}
|
||||||
uiDefButF(block, NUMSLI, 0, "End ", 10, 50, 230,20, &ma->strand_end, 0.0001, 1.0, 2, 0, "End size of strands in Blender units");
|
else{
|
||||||
}
|
uiDefButF(block, NUMSLI, 0, "Start ", 10, 75, 230,20, &ma->strand_sta, 0.25, 20.0, 2, 0, "Start size of strands in pixels");
|
||||||
else{
|
uiDefButF(block, NUMSLI, 0, "End ", 10, 55, 230,20, &ma->strand_end, 0.25, 10.0, 2, 0, "End size of strands in pixels");
|
||||||
uiDefButF(block, NUMSLI, 0, "Start ", 10, 70, 230,20, &ma->strand_sta, 0.25, 20.0, 2, 0, "Start size of strands in pixels");
|
}
|
||||||
uiDefButF(block, NUMSLI, 0, "End ", 10, 50, 230,20, &ma->strand_end, 0.25, 10.0, 2, 0, "End size of strands in pixels");
|
uiDefButF(block, NUMSLI, 0, "Shape ", 10, 35, 230,20, &ma->strand_ease, -0.9, 0.9, 2, 0, "Shape of strands, positive value makes it rounder, negative makes it spiky");
|
||||||
}
|
|
||||||
uiDefButF(block, NUMSLI, 0, "Shape ", 10, 30, 230,20, &ma->strand_ease, -0.9, 0.9, 2, 0, "Shape of strands, positive value makes it rounder, negative makes it spiky");
|
|
||||||
uiDefBut(block, TEX, B_MATPRV, "UV:", 10,10,230,20, ma->strand_uvname, 0, 31, 0, 0, "Set name of UV layer to override");
|
uiDefBut(block, TEX, B_MATPRV, "UV:", 10,10,230,20, ma->strand_uvname, 0, 31, 0, 0, "Set name of UV layer to override");
|
||||||
|
|
||||||
uiBlockSetDirection(block, UI_TOP);
|
uiBlockSetDirection(block, UI_TOP);
|
||||||
|
|||||||
@@ -3030,7 +3030,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
|
|||||||
|
|
||||||
psys->flag|=PSYS_DRAWING;
|
psys->flag|=PSYS_DRAWING;
|
||||||
|
|
||||||
if(part->flag&PART_CHILD_RENDER || !psys->childcache)
|
if(!psys->childcache)
|
||||||
totchild=0;
|
totchild=0;
|
||||||
else
|
else
|
||||||
totchild=psys->totchild*part->disp/100;
|
totchild=psys->totchild*part->disp/100;
|
||||||
@@ -3200,16 +3200,18 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
pa_time=psys_get_child_time(psys,a-totpart,cfra);
|
ChildParticle *cpa= &psys->child[a-totpart];
|
||||||
|
|
||||||
|
pa_time=psys_get_child_time(psys,cpa,cfra);
|
||||||
|
|
||||||
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
|
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
|
||||||
calc_ipo(part->ipo, 100*pa_time);
|
calc_ipo(part->ipo, 100*pa_time);
|
||||||
execute_ipo((ID *)part, part->ipo);
|
execute_ipo((ID *)part, part->ipo);
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_size=psys_get_child_size(psys,a-totpart,cfra,0);
|
pa_size=psys_get_child_size(psys,cpa,cfra,0);
|
||||||
|
|
||||||
r_tilt=2.0f*psys->child[a-totpart].rand[2];
|
r_tilt=2.0f*cpa->rand[2];
|
||||||
if(path_nbr){
|
if(path_nbr){
|
||||||
cache=psys->childcache[a-totpart];
|
cache=psys->childcache[a-totpart];
|
||||||
k_max=(int)(cache->steps);
|
k_max=(int)(cache->steps);
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ void PE_free_particle_edit(ParticleSystem *psys)
|
|||||||
/************************************************/
|
/************************************************/
|
||||||
/* Edit Mode Helpers */
|
/* Edit Mode Helpers */
|
||||||
/************************************************/
|
/************************************************/
|
||||||
static int PE_can_edit(ParticleSystem *psys)
|
int PE_can_edit(ParticleSystem *psys)
|
||||||
{
|
{
|
||||||
return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
|
return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -894,11 +894,11 @@ void make_renderinfo_string(RenderStats *rs, char *str)
|
|||||||
else if(G.scene->r.scemode & R_SINGLE_LAYER)
|
else if(G.scene->r.scemode & R_SINGLE_LAYER)
|
||||||
spos+= sprintf(spos, "Single Layer | ");
|
spos+= sprintf(spos, "Single Layer | ");
|
||||||
|
|
||||||
if(rs->tothalo)
|
spos+= sprintf(spos, "Fra:%d Ve:%d Fa:%d ", (G.scene->r.cfra), rs->totvert, rs->totface);
|
||||||
spos+= sprintf(spos, "Fra:%d Ve:%d Fa:%d Ha:%d La:%d Mem:%.2fM (%.2fM) ", (G.scene->r.cfra), rs->totvert, rs->totface, rs->tothalo, rs->totlamp, megs_used_memory, mmap_used_memory);
|
if(rs->tothalo) spos+= sprintf(spos, "Ha:%d ", rs->tothalo);
|
||||||
else
|
if(rs->totstrand) spos+= sprintf(spos, "St:%d ", rs->totstrand);
|
||||||
spos+= sprintf(spos, "Fra:%d Ve:%d Fa:%d La:%d Mem:%.2fM (%.2fM) ", (G.scene->r.cfra), rs->totvert, rs->totface, rs->totlamp, megs_used_memory, mmap_used_memory);
|
spos+= sprintf(spos, "La:%d Mem:%.2fM (%.2fM) ", rs->totlamp, megs_used_memory, mmap_used_memory);
|
||||||
|
|
||||||
if(rs->curfield)
|
if(rs->curfield)
|
||||||
spos+= sprintf(spos, "Field %d ", rs->curfield);
|
spos+= sprintf(spos, "Field %d ", rs->curfield);
|
||||||
if(rs->curblur)
|
if(rs->curblur)
|
||||||
|
|||||||
@@ -3489,7 +3489,7 @@ void createTransData(TransInfo *t)
|
|||||||
createTransPose(t, base->object);
|
createTransPose(t, base->object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (G.f & G_PARTICLEEDIT) {
|
else if (G.f & G_PARTICLEEDIT && PE_can_edit(PE_get_current(ob))) {
|
||||||
createTransParticleVerts(t);
|
createTransParticleVerts(t);
|
||||||
|
|
||||||
if(t->data && t->flag & T_PROP_EDIT) {
|
if(t->data && t->flag & T_PROP_EDIT) {
|
||||||
|
|||||||
Reference in New Issue
Block a user