Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributors: Matt Ebb 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <math.h> 00032 #include <stdlib.h> 00033 #include <stdio.h> 00034 00035 #include "MEM_guardedalloc.h" 00036 00037 #include "BLI_math.h" 00038 #include "BLI_blenlib.h" 00039 #include "BLI_kdopbvh.h" 00040 #include "BLI_utildefines.h" 00041 00042 #include "BKE_DerivedMesh.h" 00043 #include "BKE_global.h" 00044 #include "BKE_lattice.h" 00045 #include "BKE_main.h" 00046 #include "BKE_object.h" 00047 #include "BKE_particle.h" 00048 #include "BKE_scene.h" 00049 #include "BKE_texture.h" 00050 #include "BKE_colortools.h" 00051 00052 #include "DNA_meshdata_types.h" 00053 #include "DNA_texture_types.h" 00054 #include "DNA_particle_types.h" 00055 00056 #include "render_types.h" 00057 #include "renderdatabase.h" 00058 #include "texture.h" 00059 #include "pointdensity.h" 00060 00061 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00062 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ 00063 /* only to be used here in this file, it's for speed */ 00064 extern struct Render R; 00065 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00066 00067 00068 static int point_data_used(PointDensity *pd) 00069 { 00070 int pd_bitflag = 0; 00071 00072 if (pd->source == TEX_PD_PSYS) { 00073 if ((pd->noise_influence == TEX_PD_NOISE_VEL) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) || (pd->color_source == TEX_PD_COLOR_PARTVEL) || (pd->color_source == TEX_PD_COLOR_PARTSPEED)) 00074 pd_bitflag |= POINT_DATA_VEL; 00075 if ((pd->noise_influence == TEX_PD_NOISE_AGE) || (pd->color_source == TEX_PD_COLOR_PARTAGE) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE)) 00076 pd_bitflag |= POINT_DATA_LIFE; 00077 } 00078 00079 return pd_bitflag; 00080 } 00081 00082 00083 /* additional data stored alongside the point density BVH, 00084 * accessible by point index number to retrieve other information 00085 * such as particle velocity or lifetime */ 00086 static void alloc_point_data(PointDensity *pd, int total_particles, int point_data_used) 00087 { 00088 int data_size = 0; 00089 00090 if (point_data_used & POINT_DATA_VEL) { 00091 /* store 3 channels of velocity data */ 00092 data_size += 3; 00093 } 00094 if (point_data_used & POINT_DATA_LIFE) { 00095 /* store 1 channel of lifetime data */ 00096 data_size += 1; 00097 } 00098 00099 if (data_size) 00100 pd->point_data = MEM_mallocN(sizeof(float)*data_size*total_particles, "particle point data"); 00101 } 00102 00103 static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, ParticleSystem *psys) 00104 { 00105 DerivedMesh* dm; 00106 ParticleKey state; 00107 ParticleSimulationData sim= {NULL}; 00108 ParticleData *pa=NULL; 00109 float cfra = BKE_curframe(re->scene); 00110 int i /*, childexists*/ /* UNUSED */; 00111 int total_particles, offset=0; 00112 int data_used = point_data_used(pd); 00113 float partco[3]; 00114 float obview[4][4]; 00115 00116 /* init everything */ 00117 if (!psys || !ob || !pd) return; 00118 00119 mult_m4_m4m4(obview, ob->obmat, re->viewinv); 00120 00121 /* Just to create a valid rendering context for particles */ 00122 psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, 0); 00123 00124 dm = mesh_create_derived_render(re->scene, ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); 00125 00126 if ( !psys_check_enabled(ob, psys)) { 00127 psys_render_restore(ob, psys); 00128 return; 00129 } 00130 00131 sim.scene= re->scene; 00132 sim.ob= ob; 00133 sim.psys= psys; 00134 00135 /* in case ob->imat isn't up-to-date */ 00136 invert_m4_m4(ob->imat, ob->obmat); 00137 00138 total_particles = psys->totpart+psys->totchild; 00139 psys->lattice=psys_get_lattice(&sim); 00140 00141 pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); 00142 alloc_point_data(pd, total_particles, data_used); 00143 pd->totpoints = total_particles; 00144 if (data_used & POINT_DATA_VEL) offset = pd->totpoints*3; 00145 00146 #if 0 /* UNUSED */ 00147 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) 00148 childexists = 1; 00149 #endif 00150 00151 for (i=0, pa=psys->particles; i < total_particles; i++, pa++) { 00152 00153 state.time = cfra; 00154 if(psys_get_particle_state(&sim, i, &state, 0)) { 00155 00156 copy_v3_v3(partco, state.co); 00157 00158 if (pd->psys_cache_space == TEX_PD_OBJECTSPACE) 00159 mul_m4_v3(ob->imat, partco); 00160 else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) { 00161 sub_v3_v3(partco, ob->loc); 00162 } else { 00163 /* TEX_PD_WORLDSPACE */ 00164 } 00165 00166 BLI_bvhtree_insert(pd->point_tree, i, partco, 1); 00167 00168 if (data_used & POINT_DATA_VEL) { 00169 pd->point_data[i*3 + 0] = state.vel[0]; 00170 pd->point_data[i*3 + 1] = state.vel[1]; 00171 pd->point_data[i*3 + 2] = state.vel[2]; 00172 } 00173 if (data_used & POINT_DATA_LIFE) { 00174 float pa_time; 00175 00176 if (i < psys->totpart) { 00177 pa_time = (cfra - pa->time)/pa->lifetime; 00178 } else { 00179 ChildParticle *cpa= (psys->child + i) - psys->totpart; 00180 float pa_birthtime, pa_dietime; 00181 00182 pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime); 00183 } 00184 00185 pd->point_data[offset + i] = pa_time; 00186 00187 } 00188 } 00189 } 00190 00191 BLI_bvhtree_balance(pd->point_tree); 00192 dm->release(dm); 00193 00194 if(psys->lattice){ 00195 end_latt_deform(psys->lattice); 00196 psys->lattice=0; 00197 } 00198 00199 psys_render_restore(ob, psys); 00200 } 00201 00202 00203 static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob) 00204 { 00205 int i; 00206 DerivedMesh *dm; 00207 MVert *mvert = NULL; 00208 00209 dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); 00210 mvert= dm->getVertArray(dm); /* local object space */ 00211 00212 pd->totpoints= dm->getNumVerts(dm); 00213 if (pd->totpoints == 0) return; 00214 00215 pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6); 00216 00217 for(i=0; i < pd->totpoints; i++, mvert++) { 00218 float co[3]; 00219 00220 copy_v3_v3(co, mvert->co); 00221 00222 switch(pd->ob_cache_space) { 00223 case TEX_PD_OBJECTSPACE: 00224 break; 00225 case TEX_PD_OBJECTLOC: 00226 mul_m4_v3(ob->obmat, co); 00227 sub_v3_v3(co, ob->loc); 00228 break; 00229 case TEX_PD_WORLDSPACE: 00230 default: 00231 mul_m4_v3(ob->obmat, co); 00232 break; 00233 } 00234 00235 BLI_bvhtree_insert(pd->point_tree, i, co, 1); 00236 } 00237 00238 BLI_bvhtree_balance(pd->point_tree); 00239 dm->release(dm); 00240 00241 } 00242 void cache_pointdensity(Render *re, Tex *tex) 00243 { 00244 PointDensity *pd = tex->pd; 00245 00246 if(!pd) 00247 return; 00248 00249 if (pd->point_tree) { 00250 BLI_bvhtree_free(pd->point_tree); 00251 pd->point_tree = NULL; 00252 } 00253 00254 if (pd->source == TEX_PD_PSYS) { 00255 Object *ob = pd->object; 00256 ParticleSystem *psys; 00257 00258 if (!ob || !pd->psys) return; 00259 00260 psys= BLI_findlink(&ob->particlesystem, pd->psys-1); 00261 if (!psys) return; 00262 00263 pointdensity_cache_psys(re, pd, ob, psys); 00264 } 00265 else if (pd->source == TEX_PD_OBJECT) { 00266 Object *ob = pd->object; 00267 if (ob && ob->type == OB_MESH) 00268 pointdensity_cache_object(re, pd, ob); 00269 } 00270 } 00271 00272 static void free_pointdensity(Render *UNUSED(re), Tex *tex) 00273 { 00274 PointDensity *pd = tex->pd; 00275 00276 if (!pd) return; 00277 00278 if (pd->point_tree) { 00279 BLI_bvhtree_free(pd->point_tree); 00280 pd->point_tree = NULL; 00281 } 00282 00283 if (pd->point_data) { 00284 MEM_freeN(pd->point_data); 00285 pd->point_data = NULL; 00286 } 00287 pd->totpoints = 0; 00288 } 00289 00290 00291 00292 void make_pointdensities(Render *re) 00293 { 00294 Tex *tex; 00295 00296 if(re->scene->r.scemode & R_PREVIEWBUTS) 00297 return; 00298 00299 re->i.infostr= "Caching Point Densities"; 00300 re->stats_draw(re->sdh, &re->i); 00301 00302 for (tex= re->main->tex.first; tex; tex= tex->id.next) { 00303 if(tex->id.us && tex->type==TEX_POINTDENSITY) { 00304 cache_pointdensity(re, tex); 00305 } 00306 } 00307 00308 re->i.infostr= NULL; 00309 re->stats_draw(re->sdh, &re->i); 00310 } 00311 00312 void free_pointdensities(Render *re) 00313 { 00314 Tex *tex; 00315 00316 if(re->scene->r.scemode & R_PREVIEWBUTS) 00317 return; 00318 00319 for (tex= re->main->tex.first; tex; tex= tex->id.next) { 00320 if(tex->id.us && tex->type==TEX_POINTDENSITY) { 00321 free_pointdensity(re, tex); 00322 } 00323 } 00324 } 00325 00326 typedef struct PointDensityRangeData 00327 { 00328 float *density; 00329 float squared_radius; 00330 float *point_data; 00331 float *vec; 00332 float softness; 00333 short falloff_type; 00334 short noise_influence; 00335 float *age; 00336 int point_data_used; 00337 int offset; 00338 struct CurveMapping *density_curve; 00339 float velscale; 00340 } PointDensityRangeData; 00341 00342 static void accum_density(void *userdata, int index, float squared_dist) 00343 { 00344 PointDensityRangeData *pdr = (PointDensityRangeData *)userdata; 00345 const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f; 00346 float density = 0.0f; 00347 00348 if (pdr->point_data_used & POINT_DATA_VEL) { 00349 pdr->vec[0] += pdr->point_data[index*3 + 0]; //* density; 00350 pdr->vec[1] += pdr->point_data[index*3 + 1]; //* density; 00351 pdr->vec[2] += pdr->point_data[index*3 + 2]; //* density; 00352 } 00353 if (pdr->point_data_used & POINT_DATA_LIFE) { 00354 *pdr->age += pdr->point_data[pdr->offset + index]; // * density; 00355 } 00356 00357 if (pdr->falloff_type == TEX_PD_FALLOFF_STD) 00358 density = dist; 00359 else if (pdr->falloff_type == TEX_PD_FALLOFF_SMOOTH) 00360 density = 3.0f*dist*dist - 2.0f*dist*dist*dist; 00361 else if (pdr->falloff_type == TEX_PD_FALLOFF_SOFT) 00362 density = pow(dist, pdr->softness); 00363 else if (pdr->falloff_type == TEX_PD_FALLOFF_CONSTANT) 00364 density = pdr->squared_radius; 00365 else if (pdr->falloff_type == TEX_PD_FALLOFF_ROOT) 00366 density = sqrt(dist); 00367 else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) { 00368 if (pdr->point_data_used & POINT_DATA_LIFE) 00369 density = dist*MIN2(pdr->point_data[pdr->offset + index], 1.0f); 00370 else 00371 density = dist; 00372 } 00373 else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) { 00374 if (pdr->point_data_used & POINT_DATA_VEL) 00375 density = dist*len_v3(pdr->point_data + index*3)*pdr->velscale; 00376 else 00377 density = dist; 00378 } 00379 00380 if (pdr->density_curve && dist != 0.0f) { 00381 density = curvemapping_evaluateF(pdr->density_curve, 0, density/dist)*dist; 00382 } 00383 00384 *pdr->density += density; 00385 } 00386 00387 00388 static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr, 00389 float *density, float *vec, float *age, struct CurveMapping *density_curve, float velscale) 00390 { 00391 pdr->squared_radius = pd->radius*pd->radius; 00392 pdr->density = density; 00393 pdr->point_data = pd->point_data; 00394 pdr->falloff_type = pd->falloff_type; 00395 pdr->vec = vec; 00396 pdr->age = age; 00397 pdr->softness = pd->falloff_softness; 00398 pdr->noise_influence = pd->noise_influence; 00399 pdr->point_data_used = point_data_used(pd); 00400 pdr->offset = (pdr->point_data_used & POINT_DATA_VEL)?pd->totpoints*3:0; 00401 pdr->density_curve = density_curve; 00402 pdr->velscale = velscale; 00403 } 00404 00405 00406 int pointdensitytex(Tex *tex, float *texvec, TexResult *texres) 00407 { 00408 int retval = TEX_INT; 00409 PointDensity *pd = tex->pd; 00410 PointDensityRangeData pdr; 00411 float density=0.0f, age=0.0f, time=0.0f; 00412 float vec[3] = {0.0f, 0.0f, 0.0f}, co[3]; 00413 float col[4]; 00414 float turb, noise_fac; 00415 int num=0; 00416 00417 texres->tin = 0.0f; 00418 00419 if ((!pd) || (!pd->point_tree)) 00420 return 0; 00421 00422 init_pointdensityrangedata(pd, &pdr, &density, vec, &age, 00423 (pd->flag&TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL), pd->falloff_speed_scale*0.001f); 00424 noise_fac = pd->noise_fac * 0.5f; /* better default */ 00425 00426 copy_v3_v3(co, texvec); 00427 00428 if (point_data_used(pd)) { 00429 /* does a BVH lookup to find accumulated density and additional point data * 00430 * stores particle velocity vector in 'vec', and particle lifetime in 'time' */ 00431 num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr); 00432 if (num > 0) { 00433 age /= num; 00434 mul_v3_fl(vec, 1.0f/num); 00435 } 00436 00437 /* reset */ 00438 density = vec[0] = vec[1] = vec[2] = 0.0f; 00439 } 00440 00441 if (pd->flag & TEX_PD_TURBULENCE) { 00442 00443 if (pd->noise_influence == TEX_PD_NOISE_AGE) { 00444 turb = BLI_gTurbulence(pd->noise_size, texvec[0]+age, texvec[1]+age, texvec[2]+age, pd->noise_depth, 0, pd->noise_basis); 00445 } 00446 else if (pd->noise_influence == TEX_PD_NOISE_TIME) { 00447 time = R.cfra / (float)R.r.efra; 00448 turb = BLI_gTurbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth, 0, pd->noise_basis); 00449 //turb = BLI_turbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth); 00450 } 00451 else { 00452 turb = BLI_gTurbulence(pd->noise_size, texvec[0]+vec[0], texvec[1]+vec[1], texvec[2]+vec[2], pd->noise_depth, 0, pd->noise_basis); 00453 } 00454 00455 turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */ 00456 00457 /* now we have an offset coordinate to use for the density lookup */ 00458 co[0] = texvec[0] + noise_fac * turb; 00459 co[1] = texvec[1] + noise_fac * turb; 00460 co[2] = texvec[2] + noise_fac * turb; 00461 } 00462 00463 /* BVH query with the potentially perturbed coordinates */ 00464 num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr); 00465 if (num > 0) { 00466 age /= num; 00467 mul_v3_fl(vec, 1.0f/num); 00468 } 00469 00470 texres->tin = density; 00471 BRICONT; 00472 00473 if (pd->color_source == TEX_PD_COLOR_CONSTANT) 00474 return retval; 00475 00476 retval |= TEX_RGB; 00477 00478 switch (pd->color_source) { 00479 case TEX_PD_COLOR_PARTAGE: 00480 if (pd->coba) { 00481 if (do_colorband(pd->coba, age, col)) { 00482 texres->talpha= 1; 00483 copy_v3_v3(&texres->tr, col); 00484 texres->tin *= col[3]; 00485 texres->ta = texres->tin; 00486 } 00487 } 00488 break; 00489 case TEX_PD_COLOR_PARTSPEED: 00490 { 00491 float speed = len_v3(vec) * pd->speed_scale; 00492 00493 if (pd->coba) { 00494 if (do_colorband(pd->coba, speed, col)) { 00495 texres->talpha= 1; 00496 copy_v3_v3(&texres->tr, col); 00497 texres->tin *= col[3]; 00498 texres->ta = texres->tin; 00499 } 00500 } 00501 break; 00502 } 00503 case TEX_PD_COLOR_PARTVEL: 00504 texres->talpha= 1; 00505 mul_v3_fl(vec, pd->speed_scale); 00506 copy_v3_v3(&texres->tr, vec); 00507 texres->ta = texres->tin; 00508 break; 00509 case TEX_PD_COLOR_CONSTANT: 00510 default: 00511 texres->tr = texres->tg = texres->tb = texres->ta = 1.0f; 00512 break; 00513 } 00514 BRICONTRGB; 00515 00516 return retval; 00517 00518 /* 00519 if (texres->nor!=NULL) { 00520 texres->nor[0] = texres->nor[1] = texres->nor[2] = 0.0f; 00521 } 00522 */ 00523 }