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: 2004/2005/2006 Blender Foundation, full recode 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <math.h> 00032 #include <stdlib.h> 00033 #include <stdio.h> 00034 #include <string.h> 00035 #include <limits.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "BLI_math.h" 00040 #include "BLI_blenlib.h" 00041 #include "BLI_utildefines.h" 00042 #include "BLI_rand.h" 00043 #include "BLI_memarena.h" 00044 #include "BLI_ghash.h" 00045 00046 #include "DNA_armature_types.h" 00047 #include "DNA_camera_types.h" 00048 #include "DNA_material_types.h" 00049 #include "DNA_curve_types.h" 00050 #include "DNA_effect_types.h" 00051 #include "DNA_group_types.h" 00052 #include "DNA_lamp_types.h" 00053 #include "DNA_image_types.h" 00054 #include "DNA_lattice_types.h" 00055 #include "DNA_mesh_types.h" 00056 #include "DNA_meshdata_types.h" 00057 #include "DNA_meta_types.h" 00058 #include "DNA_modifier_types.h" 00059 #include "DNA_node_types.h" 00060 #include "DNA_object_types.h" 00061 #include "DNA_object_force.h" 00062 #include "DNA_object_fluidsim.h" 00063 #include "DNA_particle_types.h" 00064 #include "DNA_scene_types.h" 00065 #include "DNA_texture_types.h" 00066 #include "DNA_view3d_types.h" 00067 00068 #include "BKE_anim.h" 00069 #include "BKE_armature.h" 00070 #include "BKE_action.h" 00071 #include "BKE_curve.h" 00072 #include "BKE_customdata.h" 00073 #include "BKE_colortools.h" 00074 #include "BKE_constraint.h" 00075 #include "BKE_displist.h" 00076 #include "BKE_deform.h" 00077 #include "BKE_DerivedMesh.h" 00078 #include "BKE_effect.h" 00079 #include "BKE_global.h" 00080 #include "BKE_group.h" 00081 #include "BKE_key.h" 00082 #include "BKE_ipo.h" 00083 #include "BKE_image.h" 00084 #include "BKE_lattice.h" 00085 #include "BKE_library.h" 00086 #include "BKE_material.h" 00087 #include "BKE_main.h" 00088 #include "BKE_mball.h" 00089 #include "BKE_mesh.h" 00090 #include "BKE_modifier.h" 00091 #include "BKE_node.h" 00092 #include "BKE_object.h" 00093 #include "BKE_particle.h" 00094 #include "BKE_scene.h" 00095 #include "BKE_subsurf.h" 00096 #include "BKE_texture.h" 00097 00098 #include "BKE_world.h" 00099 00100 #include "PIL_time.h" 00101 #include "IMB_imbuf_types.h" 00102 00103 #include "envmap.h" 00104 #include "occlusion.h" 00105 #include "pointdensity.h" 00106 #include "voxeldata.h" 00107 #include "render_types.h" 00108 #include "rendercore.h" 00109 #include "renderdatabase.h" 00110 #include "renderpipeline.h" 00111 #include "shadbuf.h" 00112 #include "shading.h" 00113 #include "strand.h" 00114 #include "texture.h" 00115 #include "volume_precache.h" 00116 #include "sss.h" 00117 #include "strand.h" 00118 #include "zbuf.h" 00119 #include "sunsky.h" 00120 00121 00122 /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */ 00123 /* or for checking vertex normal flips */ 00124 #define FLT_EPSILON10 1.19209290e-06F 00125 00126 /* ------------------------------------------------------------------------- */ 00127 00128 /* Stuff for stars. This sits here because it uses gl-things. Part of 00129 this code may move down to the converter. */ 00130 /* ------------------------------------------------------------------------- */ 00131 /* this is a bad beast, since it is misused by the 3d view drawing as well. */ 00132 00133 static HaloRen *initstar(Render *re, ObjectRen *obr, float *vec, float hasize) 00134 { 00135 HaloRen *har; 00136 float hoco[4]; 00137 00138 projectverto(vec, re->winmat, hoco); 00139 00140 har= RE_findOrAddHalo(obr, obr->tothalo++); 00141 00142 /* projectvert is done in function zbufvlaggen again, because of parts */ 00143 copy_v3_v3(har->co, vec); 00144 har->hasize= hasize; 00145 00146 har->zd= 0.0; 00147 00148 return har; 00149 } 00150 00151 /* there must be a 'fixed' amount of stars generated between 00152 * near and far 00153 * all stars must by preference lie on the far and solely 00154 * differ in clarity/color 00155 */ 00156 00157 void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void), 00158 void (*vertexfunc)(float*), void (*termfunc)(void)) 00159 { 00160 extern unsigned char hash[512]; 00161 ObjectRen *obr= NULL; 00162 World *wrld= NULL; 00163 HaloRen *har; 00164 Scene *scene; 00165 Object *camera; 00166 Camera *cam; 00167 double dblrand, hlfrand; 00168 float vec[4], fx, fy, fz; 00169 float fac, starmindist, clipend; 00170 float mat[4][4], stargrid, maxrand, maxjit, force, alpha; 00171 int x, y, z, sx, sy, sz, ex, ey, ez, done = 0; 00172 unsigned int totstar= 0; 00173 00174 if(initfunc) { 00175 scene= scenev3d; 00176 wrld= scene->world; 00177 } 00178 else { 00179 scene= re->scene; 00180 wrld= &(re->wrld); 00181 } 00182 00183 stargrid = wrld->stardist; /* distance between stars */ 00184 maxrand = 2.0; /* amount a star can be shifted (in grid units) */ 00185 maxjit = (wrld->starcolnoise); /* amount a color is being shifted */ 00186 00187 /* size of stars */ 00188 force = ( wrld->starsize ); 00189 00190 /* minimal free space (starting at camera) */ 00191 starmindist= wrld->starmindist; 00192 00193 if (stargrid <= 0.10f) return; 00194 00195 if (re) re->flag |= R_HALO; 00196 else stargrid *= 1.0f; /* then it draws fewer */ 00197 00198 if(re) invert_m4_m4(mat, re->viewmat); 00199 else unit_m4(mat); 00200 00201 /* BOUNDING BOX CALCULATION 00202 * bbox goes from z = loc_near_var | loc_far_var, 00203 * x = -z | +z, 00204 * y = -z | +z 00205 */ 00206 00207 camera= re ? RE_GetCamera(re) : scene->camera; 00208 00209 if(camera==NULL || camera->type != OB_CAMERA) 00210 return; 00211 00212 cam = camera->data; 00213 clipend = cam->clipend; 00214 00215 /* convert to grid coordinates */ 00216 00217 sx = ((mat[3][0] - clipend) / stargrid) - maxrand; 00218 sy = ((mat[3][1] - clipend) / stargrid) - maxrand; 00219 sz = ((mat[3][2] - clipend) / stargrid) - maxrand; 00220 00221 ex = ((mat[3][0] + clipend) / stargrid) + maxrand; 00222 ey = ((mat[3][1] + clipend) / stargrid) + maxrand; 00223 ez = ((mat[3][2] + clipend) / stargrid) + maxrand; 00224 00225 dblrand = maxrand * stargrid; 00226 hlfrand = 2.0 * dblrand; 00227 00228 if (initfunc) { 00229 initfunc(); 00230 } 00231 00232 if(re) /* add render object for stars */ 00233 obr= RE_addRenderObject(re, NULL, NULL, 0, 0, 0); 00234 00235 for (x = sx, fx = sx * stargrid; x <= ex; x++, fx += stargrid) { 00236 for (y = sy, fy = sy * stargrid; y <= ey ; y++, fy += stargrid) { 00237 for (z = sz, fz = sz * stargrid; z <= ez; z++, fz += stargrid) { 00238 00239 BLI_srand((hash[z & 0xff] << 24) + (hash[y & 0xff] << 16) + (hash[x & 0xff] << 8)); 00240 vec[0] = fx + (hlfrand * BLI_drand()) - dblrand; 00241 vec[1] = fy + (hlfrand * BLI_drand()) - dblrand; 00242 vec[2] = fz + (hlfrand * BLI_drand()) - dblrand; 00243 vec[3] = 1.0; 00244 00245 if (vertexfunc) { 00246 if(done & 1) vertexfunc(vec); 00247 done++; 00248 } 00249 else { 00250 mul_m4_v3(re->viewmat, vec); 00251 00252 /* in vec are global coordinates 00253 * calculate distance to camera 00254 * and using that, define the alpha 00255 */ 00256 00257 { 00258 float tx, ty, tz; 00259 00260 tx = vec[0]; 00261 ty = vec[1]; 00262 tz = vec[2]; 00263 00264 alpha = sqrt(tx * tx + ty * ty + tz * tz); 00265 00266 if (alpha >= clipend) alpha = 0.0; 00267 else if (alpha <= starmindist) alpha = 0.0; 00268 else if (alpha <= 2.0f * starmindist) { 00269 alpha = (alpha - starmindist) / starmindist; 00270 } else { 00271 alpha -= 2.0f * starmindist; 00272 alpha /= (clipend - 2.0f * starmindist); 00273 alpha = 1.0f - alpha; 00274 } 00275 } 00276 00277 00278 if (alpha != 0.0f) { 00279 fac = force * BLI_drand(); 00280 00281 har = initstar(re, obr, vec, fac); 00282 00283 if (har) { 00284 har->alfa = sqrt(sqrt(alpha)); 00285 har->add= 255; 00286 har->r = har->g = har->b = 1.0; 00287 if (maxjit) { 00288 har->r += ((maxjit * BLI_drand()) ) - maxjit; 00289 har->g += ((maxjit * BLI_drand()) ) - maxjit; 00290 har->b += ((maxjit * BLI_drand()) ) - maxjit; 00291 } 00292 har->hard = 32; 00293 har->lay= -1; 00294 har->type |= HA_ONLYSKY; 00295 done++; 00296 } 00297 } 00298 } 00299 00300 /* break out of the loop if generating stars takes too long */ 00301 if(re && !(totstar % 1000000)) { 00302 if(re->test_break(re->tbh)) { 00303 x= ex + 1; 00304 y= ey + 1; 00305 z= ez + 1; 00306 } 00307 } 00308 00309 totstar++; 00310 } 00311 /* do not call blender_test_break() here, since it is used in UI as well, confusing the callback system */ 00312 /* main cause is G.afbreek of course, a global again... (ton) */ 00313 } 00314 } 00315 if (termfunc) termfunc(); 00316 00317 if(obr) 00318 re->tothalo += obr->tothalo; 00319 } 00320 00321 00322 /* ------------------------------------------------------------------------- */ 00323 /* tool functions/defines for ad hoc simplification and possible future 00324 cleanup */ 00325 /* ------------------------------------------------------------------------- */ 00326 00327 #define UVTOINDEX(u,v) (startvlak + (u) * sizev + (v)) 00328 /* 00329 00330 NOTE THAT U/V COORDINATES ARE SOMETIMES SWAPPED !! 00331 00332 ^ ()----p4----p3----() 00333 | | | | | 00334 u | | F1 | F2 | 00335 | | | | 00336 ()----p1----p2----() 00337 v -> 00338 */ 00339 00340 /* ------------------------------------------------------------------------- */ 00341 00342 static void split_v_renderfaces(ObjectRen *obr, int startvlak, int UNUSED(startvert), int UNUSED(usize), int vsize, int uIndex, int UNUSED(cyclu), int cyclv) 00343 { 00344 int vLen = vsize-1+(!!cyclv); 00345 int v; 00346 00347 for (v=0; v<vLen; v++) { 00348 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v); 00349 VertRen *vert = RE_vertren_copy(obr, vlr->v2); 00350 00351 if (cyclv) { 00352 vlr->v2 = vert; 00353 00354 if (v==vLen-1) { 00355 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0); 00356 vlr->v1 = vert; 00357 } else { 00358 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1); 00359 vlr->v1 = vert; 00360 } 00361 } else { 00362 vlr->v2 = vert; 00363 00364 if (v<vLen-1) { 00365 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1); 00366 vlr->v1 = vert; 00367 } 00368 00369 if (v==0) { 00370 vlr->v1 = RE_vertren_copy(obr, vlr->v1); 00371 } 00372 } 00373 } 00374 } 00375 00376 /* ------------------------------------------------------------------------- */ 00377 /* Stress, tangents and normals */ 00378 /* ------------------------------------------------------------------------- */ 00379 00380 static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2) 00381 { 00382 float len= len_v3v3(v1->co, v2->co)/len_v3v3(v1->orco, v2->orco); 00383 float *acc; 00384 00385 acc= accum + 2*v1->index; 00386 acc[0]+= len; 00387 acc[1]+= 1.0f; 00388 00389 acc= accum + 2*v2->index; 00390 acc[0]+= len; 00391 acc[1]+= 1.0f; 00392 } 00393 00394 static void calc_edge_stress(Render *UNUSED(re), ObjectRen *obr, Mesh *me) 00395 { 00396 float loc[3], size[3], *accum, *acc, *accumoffs, *stress; 00397 int a; 00398 00399 if(obr->totvert==0) return; 00400 00401 mesh_get_texspace(me, loc, NULL, size); 00402 00403 accum= MEM_callocN(2*sizeof(float)*obr->totvert, "temp accum for stress"); 00404 00405 /* de-normalize orco */ 00406 for(a=0; a<obr->totvert; a++) { 00407 VertRen *ver= RE_findOrAddVert(obr, a); 00408 if(ver->orco) { 00409 ver->orco[0]= ver->orco[0]*size[0] +loc[0]; 00410 ver->orco[1]= ver->orco[1]*size[1] +loc[1]; 00411 ver->orco[2]= ver->orco[2]*size[2] +loc[2]; 00412 } 00413 } 00414 00415 /* add stress values */ 00416 accumoffs= accum; /* so we can use vertex index */ 00417 for(a=0; a<obr->totvlak; a++) { 00418 VlakRen *vlr= RE_findOrAddVlak(obr, a); 00419 00420 if(vlr->v1->orco && vlr->v4) { 00421 calc_edge_stress_add(accumoffs, vlr->v1, vlr->v2); 00422 calc_edge_stress_add(accumoffs, vlr->v2, vlr->v3); 00423 calc_edge_stress_add(accumoffs, vlr->v3, vlr->v1); 00424 if(vlr->v4) { 00425 calc_edge_stress_add(accumoffs, vlr->v3, vlr->v4); 00426 calc_edge_stress_add(accumoffs, vlr->v4, vlr->v1); 00427 calc_edge_stress_add(accumoffs, vlr->v2, vlr->v4); 00428 } 00429 } 00430 } 00431 00432 for(a=0; a<obr->totvert; a++) { 00433 VertRen *ver= RE_findOrAddVert(obr, a); 00434 if(ver->orco) { 00435 /* find stress value */ 00436 acc= accumoffs + 2*ver->index; 00437 if(acc[1]!=0.0f) 00438 acc[0]/= acc[1]; 00439 stress= RE_vertren_get_stress(obr, ver, 1); 00440 *stress= *acc; 00441 00442 /* restore orcos */ 00443 ver->orco[0] = (ver->orco[0]-loc[0])/size[0]; 00444 ver->orco[1] = (ver->orco[1]-loc[1])/size[1]; 00445 ver->orco[2] = (ver->orco[2]-loc[2])/size[2]; 00446 } 00447 } 00448 00449 MEM_freeN(accum); 00450 } 00451 00452 /* gets tangent from tface or orco */ 00453 static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemArena *arena, VlakRen *vlr, int do_nmap_tangent, int do_tangent) 00454 { 00455 MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); 00456 VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4; 00457 float tang[3], *tav; 00458 float *uv1, *uv2, *uv3, *uv4; 00459 float uv[4][2]; 00460 00461 if(tface) { 00462 uv1= tface->uv[0]; 00463 uv2= tface->uv[1]; 00464 uv3= tface->uv[2]; 00465 uv4= tface->uv[3]; 00466 } 00467 else if(v1->orco) { 00468 uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; 00469 map_to_sphere( &uv[0][0], &uv[0][1],v1->orco[0], v1->orco[1], v1->orco[2]); 00470 map_to_sphere( &uv[1][0], &uv[1][1],v2->orco[0], v2->orco[1], v2->orco[2]); 00471 map_to_sphere( &uv[2][0], &uv[2][1],v3->orco[0], v3->orco[1], v3->orco[2]); 00472 if(v4) 00473 map_to_sphere( &uv[3][0], &uv[3][1],v4->orco[0], v4->orco[1], v4->orco[2]); 00474 } 00475 else return; 00476 00477 tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, vlr->n, tang); 00478 00479 if(do_tangent) { 00480 tav= RE_vertren_get_tangent(obr, v1, 1); 00481 add_v3_v3(tav, tang); 00482 tav= RE_vertren_get_tangent(obr, v2, 1); 00483 add_v3_v3(tav, tang); 00484 tav= RE_vertren_get_tangent(obr, v3, 1); 00485 add_v3_v3(tav, tang); 00486 } 00487 00488 if(do_nmap_tangent) { 00489 sum_or_add_vertex_tangent(arena, &vtangents[v1->index], tang, uv1); 00490 sum_or_add_vertex_tangent(arena, &vtangents[v2->index], tang, uv2); 00491 sum_or_add_vertex_tangent(arena, &vtangents[v3->index], tang, uv3); 00492 } 00493 00494 if(v4) { 00495 tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang); 00496 00497 if(do_tangent) { 00498 tav= RE_vertren_get_tangent(obr, v1, 1); 00499 add_v3_v3(tav, tang); 00500 tav= RE_vertren_get_tangent(obr, v3, 1); 00501 add_v3_v3(tav, tang); 00502 tav= RE_vertren_get_tangent(obr, v4, 1); 00503 add_v3_v3(tav, tang); 00504 } 00505 00506 if(do_nmap_tangent) { 00507 sum_or_add_vertex_tangent(arena, &vtangents[v1->index], tang, uv1); 00508 sum_or_add_vertex_tangent(arena, &vtangents[v3->index], tang, uv3); 00509 sum_or_add_vertex_tangent(arena, &vtangents[v4->index], tang, uv4); 00510 } 00511 } 00512 } 00513 00514 00515 00516 /**************************************************************** 00517 ************ tangent space generation interface ***************** 00518 ****************************************************************/ 00519 00520 typedef struct 00521 { 00522 ObjectRen *obr; 00523 00524 } SRenderMeshToTangent; 00525 00526 // interface 00527 #include "mikktspace.h" 00528 00529 static int GetNumFaces(const SMikkTSpaceContext * pContext) 00530 { 00531 SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; 00532 return pMesh->obr->totvlak; 00533 } 00534 00535 static int GetNumVertsOfFace(const SMikkTSpaceContext * pContext, const int face_num) 00536 { 00537 SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; 00538 VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); 00539 return vlr->v4!=NULL ? 4 : 3; 00540 } 00541 00542 static void GetPosition(const SMikkTSpaceContext * pContext, float fPos[], const int face_num, const int vert_index) 00543 { 00544 //assert(vert_index>=0 && vert_index<4); 00545 SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; 00546 VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); 00547 const float *co= (&vlr->v1)[vert_index]->co; 00548 copy_v3_v3(fPos, co); 00549 } 00550 00551 static void GetTextureCoordinate(const SMikkTSpaceContext * pContext, float fUV[], const int face_num, const int vert_index) 00552 { 00553 //assert(vert_index>=0 && vert_index<4); 00554 SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; 00555 VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); 00556 MTFace *tface= RE_vlakren_get_tface(pMesh->obr, vlr, pMesh->obr->actmtface, NULL, 0); 00557 const float *coord; 00558 00559 if(tface != NULL) { 00560 coord= tface->uv[vert_index]; 00561 fUV[0]= coord[0]; fUV[1]= coord[1]; 00562 } 00563 else if((coord= (&vlr->v1)[vert_index]->orco)) { 00564 map_to_sphere(&fUV[0], &fUV[1], coord[0], coord[1], coord[2]); 00565 } 00566 else { /* else we get un-initialized value, 0.0 ok default? */ 00567 fUV[0]= fUV[1]= 0.0f; 00568 } 00569 } 00570 00571 static void GetNormal(const SMikkTSpaceContext * pContext, float fNorm[], const int face_num, const int vert_index) 00572 { 00573 //assert(vert_index>=0 && vert_index<4); 00574 SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; 00575 VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); 00576 const float *n= (&vlr->v1)[vert_index]->n; 00577 copy_v3_v3(fNorm, n); 00578 } 00579 static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert) 00580 { 00581 //assert(vert_index>=0 && vert_index<4); 00582 SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; 00583 VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); 00584 float * ftang= RE_vlakren_get_nmap_tangent(pMesh->obr, vlr, 1); 00585 if(ftang!=NULL) { 00586 copy_v3_v3(&ftang[iVert*4+0], fvTangent); 00587 ftang[iVert*4+3]=fSign; 00588 } 00589 } 00590 00591 static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, int do_tangent, int do_nmap_tangent) 00592 { 00593 MemArena *arena= NULL; 00594 VertexTangent **vtangents= NULL; 00595 int a; 00596 00597 if(do_nmap_tangent) { 00598 arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "nmap tangent arena"); 00599 BLI_memarena_use_calloc(arena); 00600 00601 vtangents= MEM_callocN(sizeof(VertexTangent*)*obr->totvert, "VertexTangent"); 00602 } 00603 00604 /* clear all vertex normals */ 00605 for(a=0; a<obr->totvert; a++) { 00606 VertRen *ver= RE_findOrAddVert(obr, a); 00607 ver->n[0]=ver->n[1]=ver->n[2]= 0.0f; 00608 } 00609 00610 /* calculate cos of angles and point-masses, use as weight factor to 00611 add face normal to vertex */ 00612 for(a=0; a<obr->totvlak; a++) { 00613 VlakRen *vlr= RE_findOrAddVlak(obr, a); 00614 if(vlr->flag & ME_SMOOTH) { 00615 float *n4= (vlr->v4)? vlr->v4->n: NULL; 00616 float *c4= (vlr->v4)? vlr->v4->co: NULL; 00617 00618 accumulate_vertex_normals(vlr->v1->n, vlr->v2->n, vlr->v3->n, n4, 00619 vlr->n, vlr->v1->co, vlr->v2->co, vlr->v3->co, c4); 00620 } 00621 if(do_nmap_tangent || do_tangent) { 00622 /* tangents still need to be calculated for flat faces too */ 00623 /* weighting removed, they are not vertexnormals */ 00624 calc_tangent_vector(obr, vtangents, arena, vlr, do_nmap_tangent, do_tangent); 00625 } 00626 } 00627 00628 /* do solid faces */ 00629 for(a=0; a<obr->totvlak; a++) { 00630 VlakRen *vlr= RE_findOrAddVlak(obr, a); 00631 00632 if((vlr->flag & ME_SMOOTH)==0) { 00633 if(is_zero_v3(vlr->v1->n)) copy_v3_v3(vlr->v1->n, vlr->n); 00634 if(is_zero_v3(vlr->v2->n)) copy_v3_v3(vlr->v2->n, vlr->n); 00635 if(is_zero_v3(vlr->v3->n)) copy_v3_v3(vlr->v3->n, vlr->n); 00636 if(vlr->v4 && is_zero_v3(vlr->v4->n)) copy_v3_v3(vlr->v4->n, vlr->n); 00637 } 00638 00639 if(do_nmap_tangent) { 00640 VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4; 00641 MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); 00642 00643 if(tface) { 00644 int k=0; 00645 float *vtang, *ftang= RE_vlakren_get_nmap_tangent(obr, vlr, 1); 00646 00647 vtang= find_vertex_tangent(vtangents[v1->index], tface->uv[0]); 00648 copy_v3_v3(ftang, vtang); 00649 normalize_v3(ftang); 00650 vtang= find_vertex_tangent(vtangents[v2->index], tface->uv[1]); 00651 copy_v3_v3(ftang+4, vtang); 00652 normalize_v3(ftang+4); 00653 vtang= find_vertex_tangent(vtangents[v3->index], tface->uv[2]); 00654 copy_v3_v3(ftang+8, vtang); 00655 normalize_v3(ftang+8); 00656 if(v4) { 00657 vtang= find_vertex_tangent(vtangents[v4->index], tface->uv[3]); 00658 copy_v3_v3(ftang+12, vtang); 00659 normalize_v3(ftang+12); 00660 } 00661 for(k=0; k<4; k++) ftang[4*k+3]=1; 00662 } 00663 } 00664 } 00665 00666 /* normalize vertex normals */ 00667 for(a=0; a<obr->totvert; a++) { 00668 VertRen *ver= RE_findOrAddVert(obr, a); 00669 normalize_v3(ver->n); 00670 if(do_tangent) { 00671 float *tav= RE_vertren_get_tangent(obr, ver, 0); 00672 if (tav) { 00673 /* orthonorm. */ 00674 float tdn = tav[0]*ver->n[0] + tav[1]*ver->n[1] + tav[2]*ver->n[2]; 00675 tav[0] -= ver->n[0]*tdn; 00676 tav[1] -= ver->n[1]*tdn; 00677 tav[2] -= ver->n[2]*tdn; 00678 normalize_v3(tav); 00679 } 00680 } 00681 } 00682 00683 if(do_nmap_tangent!=0) 00684 { 00685 SRenderMeshToTangent mesh2tangent; 00686 SMikkTSpaceContext sContext; 00687 SMikkTSpaceInterface sInterface; 00688 memset(&mesh2tangent, 0, sizeof(SRenderMeshToTangent)); 00689 memset(&sContext, 0, sizeof(SMikkTSpaceContext)); 00690 memset(&sInterface, 0, sizeof(SMikkTSpaceInterface)); 00691 00692 mesh2tangent.obr = obr; 00693 00694 sContext.m_pUserData = &mesh2tangent; 00695 sContext.m_pInterface = &sInterface; 00696 sInterface.m_getNumFaces = GetNumFaces; 00697 sInterface.m_getNumVerticesOfFace = GetNumVertsOfFace; 00698 sInterface.m_getPosition = GetPosition; 00699 sInterface.m_getTexCoord = GetTextureCoordinate; 00700 sInterface.m_getNormal = GetNormal; 00701 sInterface.m_setTSpaceBasic = SetTSpace; 00702 00703 genTangSpaceDefault(&sContext); 00704 } 00705 00706 if(arena) 00707 BLI_memarena_free(arena); 00708 if(vtangents) 00709 MEM_freeN(vtangents); 00710 } 00711 00712 /* ------------------------------------------------------------------------- */ 00713 /* Autosmoothing: */ 00714 /* ------------------------------------------------------------------------- */ 00715 00716 typedef struct ASvert { 00717 int totface; 00718 ListBase faces; 00719 } ASvert; 00720 00721 typedef struct ASface { 00722 struct ASface *next, *prev; 00723 VlakRen *vlr[4]; 00724 VertRen *nver[4]; 00725 } ASface; 00726 00727 static void as_addvert(ASvert *asv, VertRen *v1, VlakRen *vlr) 00728 { 00729 ASface *asf; 00730 int a; 00731 00732 if(v1 == NULL) return; 00733 00734 if(asv->faces.first==NULL) { 00735 asf= MEM_callocN(sizeof(ASface), "asface"); 00736 BLI_addtail(&asv->faces, asf); 00737 } 00738 00739 asf= asv->faces.last; 00740 for(a=0; a<4; a++) { 00741 if(asf->vlr[a]==NULL) { 00742 asf->vlr[a]= vlr; 00743 asv->totface++; 00744 break; 00745 } 00746 } 00747 00748 /* new face struct */ 00749 if(a==4) { 00750 asf= MEM_callocN(sizeof(ASface), "asface"); 00751 BLI_addtail(&asv->faces, asf); 00752 asf->vlr[0]= vlr; 00753 asv->totface++; 00754 } 00755 } 00756 00757 static int as_testvertex(VlakRen *vlr, VertRen *UNUSED(ver), ASvert *asv, float thresh) 00758 { 00759 /* return 1: vertex needs a copy */ 00760 ASface *asf; 00761 float inp; 00762 int a; 00763 00764 if(vlr==0) return 0; 00765 00766 asf= asv->faces.first; 00767 while(asf) { 00768 for(a=0; a<4; a++) { 00769 if(asf->vlr[a] && asf->vlr[a]!=vlr) { 00770 inp= fabs( vlr->n[0]*asf->vlr[a]->n[0] + vlr->n[1]*asf->vlr[a]->n[1] + vlr->n[2]*asf->vlr[a]->n[2] ); 00771 if(inp < thresh) return 1; 00772 } 00773 } 00774 asf= asf->next; 00775 } 00776 00777 return 0; 00778 } 00779 00780 static VertRen *as_findvertex(VlakRen *vlr, VertRen *UNUSED(ver), ASvert *asv, float thresh) 00781 { 00782 /* return when new vertex already was made */ 00783 ASface *asf; 00784 float inp; 00785 int a; 00786 00787 asf= asv->faces.first; 00788 while(asf) { 00789 for(a=0; a<4; a++) { 00790 if(asf->vlr[a] && asf->vlr[a]!=vlr) { 00791 /* this face already made a copy for this vertex! */ 00792 if(asf->nver[a]) { 00793 inp= fabs( vlr->n[0]*asf->vlr[a]->n[0] + vlr->n[1]*asf->vlr[a]->n[1] + vlr->n[2]*asf->vlr[a]->n[2] ); 00794 if(inp >= thresh) { 00795 return asf->nver[a]; 00796 } 00797 } 00798 } 00799 } 00800 asf= asf->next; 00801 } 00802 00803 return NULL; 00804 } 00805 00806 /* note; autosmooth happens in object space still, after applying autosmooth we rotate */ 00807 /* note2; actually, when original mesh and displist are equal sized, face normals are from original mesh */ 00808 static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[][4], int degr) 00809 { 00810 ASvert *asv, *asverts; 00811 ASface *asf; 00812 VertRen *ver, *v1; 00813 VlakRen *vlr; 00814 float thresh; 00815 int a, b, totvert; 00816 00817 if(obr->totvert==0) return; 00818 asverts= MEM_callocN(sizeof(ASvert)*obr->totvert, "all smooth verts"); 00819 00820 thresh= cosf(DEG2RADF((0.5f + (float)degr))); 00821 00822 /* step zero: give faces normals of original mesh, if this is provided */ 00823 00824 00825 /* step one: construct listbase of all vertices and pointers to faces */ 00826 for(a=0; a<obr->totvlak; a++) { 00827 vlr= RE_findOrAddVlak(obr, a); 00828 /* skip wire faces */ 00829 if(vlr->v2 != vlr->v3) { 00830 as_addvert(asverts+vlr->v1->index, vlr->v1, vlr); 00831 as_addvert(asverts+vlr->v2->index, vlr->v2, vlr); 00832 as_addvert(asverts+vlr->v3->index, vlr->v3, vlr); 00833 if(vlr->v4) 00834 as_addvert(asverts+vlr->v4->index, vlr->v4, vlr); 00835 } 00836 } 00837 00838 totvert= obr->totvert; 00839 /* we now test all vertices, when faces have a normal too much different: they get a new vertex */ 00840 for(a=0, asv=asverts; a<totvert; a++, asv++) { 00841 if(asv && asv->totface>1) { 00842 ver= RE_findOrAddVert(obr, a); 00843 00844 asf= asv->faces.first; 00845 while(asf) { 00846 for(b=0; b<4; b++) { 00847 00848 /* is there a reason to make a new vertex? */ 00849 vlr= asf->vlr[b]; 00850 if( as_testvertex(vlr, ver, asv, thresh) ) { 00851 00852 /* already made a new vertex within threshold? */ 00853 v1= as_findvertex(vlr, ver, asv, thresh); 00854 if(v1==NULL) { 00855 /* make a new vertex */ 00856 v1= RE_vertren_copy(obr, ver); 00857 } 00858 asf->nver[b]= v1; 00859 if(vlr->v1==ver) vlr->v1= v1; 00860 if(vlr->v2==ver) vlr->v2= v1; 00861 if(vlr->v3==ver) vlr->v3= v1; 00862 if(vlr->v4==ver) vlr->v4= v1; 00863 } 00864 } 00865 asf= asf->next; 00866 } 00867 } 00868 } 00869 00870 /* free */ 00871 for(a=0; a<totvert; a++) { 00872 BLI_freelistN(&asverts[a].faces); 00873 } 00874 MEM_freeN(asverts); 00875 00876 /* rotate vertices and calculate normal of faces */ 00877 for(a=0; a<obr->totvert; a++) { 00878 ver= RE_findOrAddVert(obr, a); 00879 mul_m4_v3(mat, ver->co); 00880 } 00881 for(a=0; a<obr->totvlak; a++) { 00882 vlr= RE_findOrAddVlak(obr, a); 00883 00884 /* skip wire faces */ 00885 if(vlr->v2 != vlr->v3) { 00886 if(vlr->v4) 00887 normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 00888 else 00889 normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); 00890 } 00891 } 00892 } 00893 00894 /* ------------------------------------------------------------------------- */ 00895 /* Orco hash and Materials */ 00896 /* ------------------------------------------------------------------------- */ 00897 00898 static float *get_object_orco(Render *re, Object *ob) 00899 { 00900 float *orco; 00901 00902 if (!re->orco_hash) 00903 re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "get_object_orco gh"); 00904 00905 orco = BLI_ghash_lookup(re->orco_hash, ob); 00906 00907 if (!orco) { 00908 if (ELEM(ob->type, OB_CURVE, OB_FONT)) { 00909 orco = make_orco_curve(re->scene, ob); 00910 } else if (ob->type==OB_SURF) { 00911 orco = make_orco_surf(ob); 00912 } 00913 00914 if (orco) 00915 BLI_ghash_insert(re->orco_hash, ob, orco); 00916 } 00917 00918 return orco; 00919 } 00920 00921 static void set_object_orco(Render *re, void *ob, float *orco) 00922 { 00923 if (!re->orco_hash) 00924 re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "set_object_orco gh"); 00925 00926 BLI_ghash_insert(re->orco_hash, ob, orco); 00927 } 00928 00929 static void free_mesh_orco_hash(Render *re) 00930 { 00931 if (re->orco_hash) { 00932 BLI_ghash_free(re->orco_hash, NULL, (GHashValFreeFP)MEM_freeN); 00933 re->orco_hash = NULL; 00934 } 00935 } 00936 00937 static void check_material_mapto(Material *ma) 00938 { 00939 int a; 00940 ma->mapto_textured = 0; 00941 00942 /* cache which inputs are actually textured. 00943 * this can avoid a bit of time spent iterating through all the texture slots, map inputs and map tos 00944 * every time a property which may or may not be textured is accessed */ 00945 00946 for(a=0; a<MAX_MTEX; a++) { 00947 if(ma->mtex[a] && ma->mtex[a]->tex) { 00948 /* currently used only in volume render, so we'll check for those flags */ 00949 if(ma->mtex[a]->mapto & MAP_DENSITY) ma->mapto_textured |= MAP_DENSITY; 00950 if(ma->mtex[a]->mapto & MAP_EMISSION) ma->mapto_textured |= MAP_EMISSION; 00951 if(ma->mtex[a]->mapto & MAP_EMISSION_COL) ma->mapto_textured |= MAP_EMISSION_COL; 00952 if(ma->mtex[a]->mapto & MAP_SCATTERING) ma->mapto_textured |= MAP_SCATTERING; 00953 if(ma->mtex[a]->mapto & MAP_TRANSMISSION_COL) ma->mapto_textured |= MAP_TRANSMISSION_COL; 00954 if(ma->mtex[a]->mapto & MAP_REFLECTION) ma->mapto_textured |= MAP_REFLECTION; 00955 if(ma->mtex[a]->mapto & MAP_REFLECTION_COL) ma->mapto_textured |= MAP_REFLECTION_COL; 00956 } 00957 } 00958 } 00959 static void flag_render_node_material(Render *re, bNodeTree *ntree) 00960 { 00961 bNode *node; 00962 00963 for(node=ntree->nodes.first; node; node= node->next) { 00964 if(node->id) { 00965 if(GS(node->id->name)==ID_MA) { 00966 Material *ma= (Material *)node->id; 00967 00968 if((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) 00969 re->flag |= R_ZTRA; 00970 00971 ma->flag |= MA_IS_USED; 00972 } 00973 else if(node->type==NODE_GROUP) 00974 flag_render_node_material(re, (bNodeTree *)node->id); 00975 } 00976 } 00977 } 00978 00979 static Material *give_render_material(Render *re, Object *ob, short nr) 00980 { 00981 extern Material defmaterial; /* material.c */ 00982 Material *ma; 00983 00984 ma= give_current_material(ob, nr); 00985 if(ma==NULL) 00986 ma= &defmaterial; 00987 00988 if(re->r.mode & R_SPEED) ma->texco |= NEED_UV; 00989 00990 if(ma->material_type == MA_TYPE_VOLUME) { 00991 ma->mode |= MA_TRANSP; 00992 ma->mode &= ~MA_SHADBUF; 00993 } 00994 if((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) 00995 re->flag |= R_ZTRA; 00996 00997 /* for light groups and SSS */ 00998 ma->flag |= MA_IS_USED; 00999 01000 if(ma->nodetree && ma->use_nodes) 01001 flag_render_node_material(re, ma->nodetree); 01002 01003 check_material_mapto(ma); 01004 01005 return ma; 01006 } 01007 01008 /* ------------------------------------------------------------------------- */ 01009 /* Particles */ 01010 /* ------------------------------------------------------------------------- */ 01011 typedef struct ParticleStrandData 01012 { 01013 struct MCol *mcol; 01014 float *orco, *uvco, *surfnor; 01015 float time, adapt_angle, adapt_pix, size; 01016 int totuv, totcol; 01017 int first, line, adapt, override_uv; 01018 } 01019 ParticleStrandData; 01020 /* future thread problem... */ 01021 static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, ParticleStrandData *sd, const float vec[3], const float vec1[3]) 01022 { 01023 static VertRen *v1= NULL, *v2= NULL; 01024 VlakRen *vlr= NULL; 01025 float nor[3], cross[3], crosslen, w, dx, dy, width; 01026 static float anor[3], avec[3]; 01027 int flag, i; 01028 static int second=0; 01029 01030 sub_v3_v3v3(nor, vec, vec1); 01031 normalize_v3(nor); // nor needed as tangent 01032 cross_v3_v3v3(cross, vec, nor); 01033 01034 /* turn cross in pixelsize */ 01035 w= vec[2]*re->winmat[2][3] + re->winmat[3][3]; 01036 dx= re->winx*cross[0]*re->winmat[0][0]; 01037 dy= re->winy*cross[1]*re->winmat[1][1]; 01038 w= sqrt(dx*dx + dy*dy)/w; 01039 01040 if(w!=0.0f) { 01041 float fac; 01042 if(ma->strand_ease!=0.0f) { 01043 if(ma->strand_ease<0.0f) 01044 fac= pow(sd->time, 1.0f+ma->strand_ease); 01045 else 01046 fac= pow(sd->time, 1.0f/(1.0f-ma->strand_ease)); 01047 } 01048 else fac= sd->time; 01049 01050 width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end); 01051 01052 /* use actual Blender units for strand width and fall back to minimum width */ 01053 if(ma->mode & MA_STR_B_UNITS){ 01054 crosslen= len_v3(cross); 01055 w= 2.0f*crosslen*ma->strand_min/w; 01056 01057 if(width < w) 01058 width= w; 01059 01060 /*cross is the radius of the strand so we want it to be half of full width */ 01061 mul_v3_fl(cross,0.5f/crosslen); 01062 } 01063 else 01064 width/=w; 01065 01066 mul_v3_fl(cross, width); 01067 } 01068 01069 if(ma->mode & MA_TANGENT_STR) 01070 flag= R_SMOOTH|R_TANGENT; 01071 else 01072 flag= R_SMOOTH; 01073 01074 /* only 1 pixel wide strands filled in as quads now, otherwise zbuf errors */ 01075 if(ma->strand_sta==1.0f) 01076 flag |= R_STRAND; 01077 01078 /* single face line */ 01079 if(sd->line) { 01080 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 01081 vlr->flag= flag; 01082 vlr->v1= RE_findOrAddVert(obr, obr->totvert++); 01083 vlr->v2= RE_findOrAddVert(obr, obr->totvert++); 01084 vlr->v3= RE_findOrAddVert(obr, obr->totvert++); 01085 vlr->v4= RE_findOrAddVert(obr, obr->totvert++); 01086 01087 copy_v3_v3(vlr->v1->co, vec); 01088 add_v3_v3(vlr->v1->co, cross); 01089 copy_v3_v3(vlr->v1->n, nor); 01090 vlr->v1->orco= sd->orco; 01091 vlr->v1->accum= -1.0f; // accum abuse for strand texco 01092 01093 copy_v3_v3(vlr->v2->co, vec); 01094 sub_v3_v3v3(vlr->v2->co, vlr->v2->co, cross); 01095 copy_v3_v3(vlr->v2->n, nor); 01096 vlr->v2->orco= sd->orco; 01097 vlr->v2->accum= vlr->v1->accum; 01098 01099 copy_v3_v3(vlr->v4->co, vec1); 01100 add_v3_v3(vlr->v4->co, cross); 01101 copy_v3_v3(vlr->v4->n, nor); 01102 vlr->v4->orco= sd->orco; 01103 vlr->v4->accum= 1.0f; // accum abuse for strand texco 01104 01105 copy_v3_v3(vlr->v3->co, vec1); 01106 sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross); 01107 copy_v3_v3(vlr->v3->n, nor); 01108 vlr->v3->orco= sd->orco; 01109 vlr->v3->accum= vlr->v4->accum; 01110 01111 normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 01112 01113 vlr->mat= ma; 01114 vlr->ec= ME_V2V3; 01115 01116 if(sd->surfnor) { 01117 float *snor= RE_vlakren_get_surfnor(obr, vlr, 1); 01118 copy_v3_v3(snor, sd->surfnor); 01119 } 01120 01121 if(sd->uvco){ 01122 for(i=0; i<sd->totuv; i++){ 01123 MTFace *mtf; 01124 mtf=RE_vlakren_get_tface(obr,vlr,i,NULL,1); 01125 mtf->uv[0][0]=mtf->uv[1][0]= 01126 mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0]; 01127 mtf->uv[0][1]=mtf->uv[1][1]= 01128 mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1]; 01129 } 01130 if(sd->override_uv>=0){ 01131 MTFace *mtf; 01132 mtf=RE_vlakren_get_tface(obr,vlr,sd->override_uv,NULL,0); 01133 01134 mtf->uv[0][0]=mtf->uv[3][0]=0.0f; 01135 mtf->uv[1][0]=mtf->uv[2][0]=1.0f; 01136 01137 mtf->uv[0][1]=mtf->uv[1][1]=0.0f; 01138 mtf->uv[2][1]=mtf->uv[3][1]=1.0f; 01139 } 01140 } 01141 if(sd->mcol){ 01142 for(i=0; i<sd->totcol; i++){ 01143 MCol *mc; 01144 mc=RE_vlakren_get_mcol(obr,vlr,i,NULL,1); 01145 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i]; 01146 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i]; 01147 } 01148 } 01149 } 01150 /* first two vertices of a strand */ 01151 else if(sd->first) { 01152 if(sd->adapt){ 01153 copy_v3_v3(anor, nor); 01154 copy_v3_v3(avec, vec); 01155 second=1; 01156 } 01157 01158 v1= RE_findOrAddVert(obr, obr->totvert++); 01159 v2= RE_findOrAddVert(obr, obr->totvert++); 01160 01161 copy_v3_v3(v1->co, vec); 01162 add_v3_v3(v1->co, cross); 01163 copy_v3_v3(v1->n, nor); 01164 v1->orco= sd->orco; 01165 v1->accum= -1.0f; // accum abuse for strand texco 01166 01167 copy_v3_v3(v2->co, vec); 01168 sub_v3_v3v3(v2->co, v2->co, cross); 01169 copy_v3_v3(v2->n, nor); 01170 v2->orco= sd->orco; 01171 v2->accum= v1->accum; 01172 } 01173 /* more vertices & faces to strand */ 01174 else { 01175 if(sd->adapt==0 || second){ 01176 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 01177 vlr->flag= flag; 01178 vlr->v1= v1; 01179 vlr->v2= v2; 01180 vlr->v3= RE_findOrAddVert(obr, obr->totvert++); 01181 vlr->v4= RE_findOrAddVert(obr, obr->totvert++); 01182 01183 v1= vlr->v4; // cycle 01184 v2= vlr->v3; // cycle 01185 01186 01187 if(sd->adapt){ 01188 second=0; 01189 copy_v3_v3(anor,nor); 01190 copy_v3_v3(avec,vec); 01191 } 01192 01193 } 01194 else if(sd->adapt){ 01195 float dvec[3],pvec[3]; 01196 sub_v3_v3v3(dvec,avec,vec); 01197 project_v3_v3v3(pvec,dvec,vec); 01198 sub_v3_v3v3(dvec,dvec,pvec); 01199 01200 w= vec[2]*re->winmat[2][3] + re->winmat[3][3]; 01201 dx= re->winx*dvec[0]*re->winmat[0][0]/w; 01202 dy= re->winy*dvec[1]*re->winmat[1][1]/w; 01203 w= sqrt(dx*dx + dy*dy); 01204 if(dot_v3v3(anor,nor)<sd->adapt_angle && w>sd->adapt_pix){ 01205 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 01206 vlr->flag= flag; 01207 vlr->v1= v1; 01208 vlr->v2= v2; 01209 vlr->v3= RE_findOrAddVert(obr, obr->totvert++); 01210 vlr->v4= RE_findOrAddVert(obr, obr->totvert++); 01211 01212 v1= vlr->v4; // cycle 01213 v2= vlr->v3; // cycle 01214 01215 copy_v3_v3(anor,nor); 01216 copy_v3_v3(avec,vec); 01217 } 01218 else{ 01219 vlr= RE_findOrAddVlak(obr, obr->totvlak-1); 01220 } 01221 } 01222 01223 copy_v3_v3(vlr->v4->co, vec); 01224 add_v3_v3(vlr->v4->co, cross); 01225 copy_v3_v3(vlr->v4->n, nor); 01226 vlr->v4->orco= sd->orco; 01227 vlr->v4->accum= -1.0f + 2.0f*sd->time; // accum abuse for strand texco 01228 01229 copy_v3_v3(vlr->v3->co, vec); 01230 sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross); 01231 copy_v3_v3(vlr->v3->n, nor); 01232 vlr->v3->orco= sd->orco; 01233 vlr->v3->accum= vlr->v4->accum; 01234 01235 normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 01236 01237 vlr->mat= ma; 01238 vlr->ec= ME_V2V3; 01239 01240 if(sd->surfnor) { 01241 float *snor= RE_vlakren_get_surfnor(obr, vlr, 1); 01242 copy_v3_v3(snor, sd->surfnor); 01243 } 01244 01245 if(sd->uvco){ 01246 for(i=0; i<sd->totuv; i++){ 01247 MTFace *mtf; 01248 mtf=RE_vlakren_get_tface(obr,vlr,i,NULL,1); 01249 mtf->uv[0][0]=mtf->uv[1][0]= 01250 mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0]; 01251 mtf->uv[0][1]=mtf->uv[1][1]= 01252 mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1]; 01253 } 01254 if(sd->override_uv>=0){ 01255 MTFace *mtf; 01256 mtf=RE_vlakren_get_tface(obr,vlr,sd->override_uv,NULL,0); 01257 01258 mtf->uv[0][0]=mtf->uv[3][0]=0.0f; 01259 mtf->uv[1][0]=mtf->uv[2][0]=1.0f; 01260 01261 mtf->uv[0][1]=mtf->uv[1][1]=(vlr->v1->accum+1.0f)/2.0f; 01262 mtf->uv[2][1]=mtf->uv[3][1]=(vlr->v3->accum+1.0f)/2.0f; 01263 } 01264 } 01265 if(sd->mcol){ 01266 for(i=0; i<sd->totcol; i++){ 01267 MCol *mc; 01268 mc=RE_vlakren_get_mcol(obr,vlr,i,NULL,1); 01269 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i]; 01270 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i]; 01271 } 01272 } 01273 } 01274 } 01275 01276 static void static_particle_wire(ObjectRen *obr, Material *ma, const float vec[3], const float vec1[3], int first, int line) 01277 { 01278 VlakRen *vlr; 01279 static VertRen *v1; 01280 01281 if(line) { 01282 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 01283 vlr->v1= RE_findOrAddVert(obr, obr->totvert++); 01284 vlr->v2= RE_findOrAddVert(obr, obr->totvert++); 01285 vlr->v3= vlr->v2; 01286 vlr->v4= NULL; 01287 01288 copy_v3_v3(vlr->v1->co, vec); 01289 copy_v3_v3(vlr->v2->co, vec1); 01290 01291 sub_v3_v3v3(vlr->n, vec, vec1); 01292 normalize_v3(vlr->n); 01293 copy_v3_v3(vlr->v1->n, vlr->n); 01294 copy_v3_v3(vlr->v2->n, vlr->n); 01295 01296 vlr->mat= ma; 01297 vlr->ec= ME_V1V2; 01298 01299 } 01300 else if(first) { 01301 v1= RE_findOrAddVert(obr, obr->totvert++); 01302 copy_v3_v3(v1->co, vec); 01303 } 01304 else { 01305 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 01306 vlr->v1= v1; 01307 vlr->v2= RE_findOrAddVert(obr, obr->totvert++); 01308 vlr->v3= vlr->v2; 01309 vlr->v4= NULL; 01310 01311 v1= vlr->v2; // cycle 01312 copy_v3_v3(v1->co, vec); 01313 01314 sub_v3_v3v3(vlr->n, vec, vec1); 01315 normalize_v3(vlr->n); 01316 copy_v3_v3(v1->n, vlr->n); 01317 01318 vlr->mat= ma; 01319 vlr->ec= ME_V1V2; 01320 } 01321 01322 } 01323 01324 static void particle_curve(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, float *loc, float *loc1, int seed, float *pa_co) 01325 { 01326 HaloRen *har=0; 01327 01328 if(ma->material_type == MA_TYPE_WIRE) 01329 static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line); 01330 else if(ma->material_type == MA_TYPE_HALO) { 01331 har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed, pa_co); 01332 if(har) har->lay= obr->ob->lay; 01333 } 01334 else 01335 static_particle_strand(re, obr, ma, sd, loc, loc1); 01336 } 01337 static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, ParticleBillboardData *bb) 01338 { 01339 VlakRen *vlr; 01340 MTFace *mtf; 01341 float xvec[3], yvec[3], zvec[3], bb_center[3]; 01342 /* Number of tiles */ 01343 int totsplit = bb->uv_split * bb->uv_split; 01344 int tile, x, y; 01345 /* Tile offsets */ 01346 float uvx = 0.0f, uvy = 0.0f, uvdx = 1.0f, uvdy = 1.0f, time = 0.0f; 01347 01348 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 01349 vlr->v1= RE_findOrAddVert(obr, obr->totvert++); 01350 vlr->v2= RE_findOrAddVert(obr, obr->totvert++); 01351 vlr->v3= RE_findOrAddVert(obr, obr->totvert++); 01352 vlr->v4= RE_findOrAddVert(obr, obr->totvert++); 01353 01354 psys_make_billboard(bb, xvec, yvec, zvec, bb_center); 01355 01356 add_v3_v3v3(vlr->v1->co, bb_center, xvec); 01357 add_v3_v3(vlr->v1->co, yvec); 01358 mul_m4_v3(re->viewmat, vlr->v1->co); 01359 01360 sub_v3_v3v3(vlr->v2->co, bb_center, xvec); 01361 add_v3_v3(vlr->v2->co, yvec); 01362 mul_m4_v3(re->viewmat, vlr->v2->co); 01363 01364 sub_v3_v3v3(vlr->v3->co, bb_center, xvec); 01365 sub_v3_v3v3(vlr->v3->co, vlr->v3->co, yvec); 01366 mul_m4_v3(re->viewmat, vlr->v3->co); 01367 01368 add_v3_v3v3(vlr->v4->co, bb_center, xvec); 01369 sub_v3_v3(vlr->v4->co, yvec); 01370 mul_m4_v3(re->viewmat, vlr->v4->co); 01371 01372 normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 01373 copy_v3_v3(vlr->v1->n,vlr->n); 01374 copy_v3_v3(vlr->v2->n,vlr->n); 01375 copy_v3_v3(vlr->v3->n,vlr->n); 01376 copy_v3_v3(vlr->v4->n,vlr->n); 01377 01378 vlr->mat= ma; 01379 vlr->ec= ME_V2V3; 01380 01381 if(bb->uv_split > 1){ 01382 uvdx = uvdy = 1.0f / (float)bb->uv_split; 01383 01384 if(ELEM(bb->anim, PART_BB_ANIM_AGE, PART_BB_ANIM_FRAME)) { 01385 if(bb->anim == PART_BB_ANIM_FRAME) 01386 time = ((int)(bb->time * bb->lifetime) % totsplit)/(float)totsplit; 01387 else 01388 time = bb->time; 01389 } 01390 else if(bb->anim == PART_BB_ANIM_ANGLE) { 01391 if(bb->align == PART_BB_VIEW) { 01392 time = (float)fmod((bb->tilt + 1.0f) / 2.0f, 1.0); 01393 } 01394 else { 01395 float axis1[3] = {0.0f,0.0f,0.0f}; 01396 float axis2[3] = {0.0f,0.0f,0.0f}; 01397 01398 axis1[(bb->align + 1) % 3] = 1.0f; 01399 axis2[(bb->align + 2) % 3] = 1.0f; 01400 01401 if(bb->lock == 0) { 01402 zvec[bb->align] = 0.0f; 01403 normalize_v3(zvec); 01404 } 01405 01406 time = saacos(dot_v3v3(zvec, axis1)) / (float)M_PI; 01407 01408 if(dot_v3v3(zvec, axis2) < 0.0f) 01409 time = 1.0f - time / 2.0f; 01410 else 01411 time /= 2.0f; 01412 } 01413 } 01414 01415 if(bb->split_offset == PART_BB_OFF_LINEAR) 01416 time = (float)fmod(time + (float)bb->num / (float)totsplit, 1.0f); 01417 else if(bb->split_offset==PART_BB_OFF_RANDOM) 01418 time = (float)fmod(time + bb->random, 1.0f); 01419 01420 /* Find the coordinates in tile space (integer), then convert to UV 01421 * space (float). Note that Y is flipped. */ 01422 tile = (int)((time + FLT_EPSILON10) * totsplit); 01423 x = tile % bb->uv_split; 01424 y = tile / bb->uv_split; 01425 y = (bb->uv_split - 1) - y; 01426 uvx = uvdx * x; 01427 uvy = uvdy * y; 01428 } 01429 01430 /* normal UVs */ 01431 if(bb->uv[0] >= 0){ 01432 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[0], NULL, 1); 01433 mtf->uv[0][0] = 1.0f; 01434 mtf->uv[0][1] = 1.0f; 01435 mtf->uv[1][0] = 0.0f; 01436 mtf->uv[1][1] = 1.0f; 01437 mtf->uv[2][0] = 0.0f; 01438 mtf->uv[2][1] = 0.0f; 01439 mtf->uv[3][0] = 1.0f; 01440 mtf->uv[3][1] = 0.0f; 01441 } 01442 01443 /* time-index UVs */ 01444 if(bb->uv[1] >= 0){ 01445 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[1], NULL, 1); 01446 mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = bb->time; 01447 mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = (float)bb->num/(float)bb->totnum; 01448 } 01449 01450 /* split UVs */ 01451 if(bb->uv_split > 1 && bb->uv[2] >= 0){ 01452 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[2], NULL, 1); 01453 mtf->uv[0][0] = uvx + uvdx; 01454 mtf->uv[0][1] = uvy + uvdy; 01455 mtf->uv[1][0] = uvx; 01456 mtf->uv[1][1] = uvy + uvdy; 01457 mtf->uv[2][0] = uvx; 01458 mtf->uv[2][1] = uvy; 01459 mtf->uv[3][0] = uvx + uvdx; 01460 mtf->uv[3][1] = uvy; 01461 } 01462 } 01463 static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, ParticleBillboardData *bb, ParticleKey *state, int seed, float hasize, float *pa_co) 01464 { 01465 float loc[3], loc0[3], loc1[3], vel[3]; 01466 01467 copy_v3_v3(loc, state->co); 01468 01469 if(ren_as != PART_DRAW_BB) 01470 mul_m4_v3(re->viewmat, loc); 01471 01472 switch(ren_as) { 01473 case PART_DRAW_LINE: 01474 sd->line = 1; 01475 sd->time = 0.0f; 01476 sd->size = hasize; 01477 01478 copy_v3_v3(vel, state->vel); 01479 mul_mat3_m4_v3(re->viewmat, vel); 01480 normalize_v3(vel); 01481 01482 if(part->draw & PART_DRAW_VEL_LENGTH) 01483 mul_v3_fl(vel, len_v3(state->vel)); 01484 01485 madd_v3_v3v3fl(loc0, loc, vel, -part->draw_line[0]); 01486 madd_v3_v3v3fl(loc1, loc, vel, part->draw_line[1]); 01487 01488 particle_curve(re, obr, dm, ma, sd, loc0, loc1, seed, pa_co); 01489 01490 break; 01491 01492 case PART_DRAW_BB: 01493 01494 copy_v3_v3(bb->vec, loc); 01495 copy_v3_v3(bb->vel, state->vel); 01496 01497 particle_billboard(re, obr, ma, bb); 01498 01499 break; 01500 01501 default: 01502 { 01503 HaloRen *har=0; 01504 01505 har = RE_inithalo_particle(re, obr, dm, ma, loc, NULL, sd->orco, sd->uvco, hasize, 0.0, seed, pa_co); 01506 01507 if(har) har->lay= obr->ob->lay; 01508 01509 break; 01510 } 01511 } 01512 } 01513 static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int num, ParticleStrandData *sd) 01514 { 01515 int i; 01516 01517 /* get uvco */ 01518 if(sd->uvco && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) { 01519 for(i=0; i<sd->totuv; i++) { 01520 if(num != DMCACHE_NOTFOUND) { 01521 MFace *mface = dm->getFaceData(dm, num, CD_MFACE); 01522 MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i); 01523 mtface += num; 01524 01525 psys_interpolate_uvs(mtface, mface->v4, fuv, sd->uvco + 2 * i); 01526 } 01527 else { 01528 sd->uvco[2*i] = 0.0f; 01529 sd->uvco[2*i + 1] = 0.0f; 01530 } 01531 } 01532 } 01533 01534 /* get mcol */ 01535 if(sd->mcol && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) { 01536 for(i=0; i<sd->totcol; i++) { 01537 if(num != DMCACHE_NOTFOUND) { 01538 MFace *mface = dm->getFaceData(dm, num, CD_MFACE); 01539 MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i); 01540 mc += num * 4; 01541 01542 psys_interpolate_mcol(mc, mface->v4, fuv, sd->mcol + i); 01543 } 01544 else 01545 memset(&sd->mcol[i], 0, sizeof(MCol)); 01546 } 01547 } 01548 } 01549 static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset) 01550 { 01551 Object *ob= obr->ob; 01552 // Object *tob=0; 01553 Material *ma=0; 01554 ParticleSystemModifierData *psmd; 01555 ParticleSystem *tpsys=0; 01556 ParticleSettings *part, *tpart=0; 01557 ParticleData *pars, *pa=0,*tpa=0; 01558 ParticleKey *states=0; 01559 ParticleKey state; 01560 ParticleCacheKey *cache=0; 01561 ParticleBillboardData bb; 01562 ParticleSimulationData sim = {0}; 01563 ParticleStrandData sd; 01564 StrandBuffer *strandbuf=0; 01565 StrandVert *svert=0; 01566 StrandBound *sbound= 0; 01567 StrandRen *strand=0; 01568 RNG *rng= 0; 01569 float loc[3],loc1[3],loc0[3],mat[4][4],nmat[3][3],co[3],nor[3],duplimat[4][4]; 01570 float strandlen=0.0f, curlen=0.0f; 01571 float hasize, pa_size, r_tilt, r_length; 01572 float pa_time, pa_birthtime, pa_dietime; 01573 float random, simplify[2], pa_co[3]; 01574 const float cfra= BKE_curframe(re->scene); 01575 int i, a, k, max_k=0, totpart, dosimplify = 0, dosurfacecache = 0, use_duplimat = 0; 01576 int totchild=0; 01577 int seed, path_nbr=0, orco1=0, num; 01578 int totface, *origindex = 0; 01579 char **uv_name=0; 01580 01581 /* 1. check that everything is ok & updated */ 01582 if(psys==NULL) 01583 return 0; 01584 01585 part=psys->part; 01586 pars=psys->particles; 01587 01588 if(part==NULL || pars==NULL || !psys_check_enabled(ob, psys)) 01589 return 0; 01590 01591 if(part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT) 01592 return 1; 01593 01594 /* 2. start initialising things */ 01595 01596 /* last possibility to bail out! */ 01597 psmd = psys_get_modifier(ob,psys); 01598 if(!(psmd->modifier.mode & eModifierMode_Render)) 01599 return 0; 01600 01601 sim.scene= re->scene; 01602 sim.ob= ob; 01603 sim.psys= psys; 01604 sim.psmd= psmd; 01605 01606 if(part->phystype==PART_PHYS_KEYED) 01607 psys_count_keyed_targets(&sim); 01608 01609 totchild=psys->totchild; 01610 01611 /* can happen for disconnected/global hair */ 01612 if(part->type==PART_HAIR && !psys->childcache) 01613 totchild= 0; 01614 01615 if(G.rendering == 0) { /* preview render */ 01616 totchild = (int)((float)totchild * (float)part->disp / 100.0f); 01617 } 01618 01619 psys->flag |= PSYS_DRAWING; 01620 01621 rng= rng_new(psys->seed); 01622 01623 totpart=psys->totpart; 01624 01625 memset(&sd, 0, sizeof(ParticleStrandData)); 01626 sd.override_uv = -1; 01627 01628 /* 2.1 setup material stff */ 01629 ma= give_render_material(re, ob, part->omat); 01630 01631 #if 0 // XXX old animation system 01632 if(ma->ipo){ 01633 calc_ipo(ma->ipo, cfra); 01634 execute_ipo((ID *)ma, ma->ipo); 01635 } 01636 #endif // XXX old animation system 01637 01638 hasize = ma->hasize; 01639 seed = ma->seed1; 01640 01641 re->flag |= R_HALO; 01642 01643 RE_set_customdata_names(obr, &psmd->dm->faceData); 01644 sd.totuv = CustomData_number_of_layers(&psmd->dm->faceData, CD_MTFACE); 01645 sd.totcol = CustomData_number_of_layers(&psmd->dm->faceData, CD_MCOL); 01646 01647 if(ma->texco & TEXCO_UV && sd.totuv) { 01648 sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs"); 01649 01650 if(ma->strand_uvname[0]) { 01651 sd.override_uv = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, ma->strand_uvname); 01652 sd.override_uv -= CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE); 01653 } 01654 } 01655 else 01656 sd.uvco = NULL; 01657 01658 if(sd.totcol) 01659 sd.mcol = MEM_callocN(sd.totcol * sizeof(MCol), "particle_mcols"); 01660 01661 /* 2.2 setup billboards */ 01662 if(part->ren_as == PART_DRAW_BB) { 01663 int first_uv = CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE); 01664 01665 bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[0]); 01666 if(bb.uv[0] < 0) 01667 bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm->faceData, CD_MTFACE); 01668 01669 bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[1]); 01670 01671 bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[2]); 01672 01673 if(first_uv >= 0) { 01674 bb.uv[0] -= first_uv; 01675 bb.uv[1] -= first_uv; 01676 bb.uv[2] -= first_uv; 01677 } 01678 01679 bb.align = part->bb_align; 01680 bb.anim = part->bb_anim; 01681 bb.lock = part->draw & PART_DRAW_BB_LOCK; 01682 bb.ob = (part->bb_ob ? part->bb_ob : RE_GetCamera(re)); 01683 bb.split_offset = part->bb_split_offset; 01684 bb.totnum = totpart+totchild; 01685 bb.uv_split = part->bb_uv_split; 01686 } 01687 01688 /* 2.5 setup matrices */ 01689 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 01690 invert_m4_m4(ob->imat, mat); /* need to be that way, for imat texture */ 01691 copy_m3_m4(nmat, ob->imat); 01692 transpose_m3(nmat); 01693 01694 if(psys->flag & PSYS_USE_IMAT) { 01695 /* psys->imat is the original emitter's inverse matrix, ob->obmat is the duplicated object's matrix */ 01696 mult_m4_m4m4(duplimat, ob->obmat, psys->imat); 01697 use_duplimat = 1; 01698 } 01699 01700 /* 2.6 setup strand rendering */ 01701 if(part->ren_as == PART_DRAW_PATH && psys->pathcache){ 01702 path_nbr=(int)pow(2.0,(double) part->ren_step); 01703 01704 if(path_nbr) { 01705 if(!ELEM(ma->material_type, MA_TYPE_HALO, MA_TYPE_WIRE)) { 01706 sd.orco = MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos"); 01707 set_object_orco(re, psys, sd.orco); 01708 } 01709 } 01710 01711 if(part->draw & PART_DRAW_REN_ADAPT) { 01712 sd.adapt = 1; 01713 sd.adapt_pix = (float)part->adapt_pix; 01714 sd.adapt_angle = cosf(DEG2RADF((float)part->adapt_angle)); 01715 } 01716 01717 if (part->draw & PART_DRAW_REN_STRAND) { 01718 strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1)); 01719 strandbuf->ma= ma; 01720 strandbuf->lay= ob->lay; 01721 copy_m4_m4(strandbuf->winmat, re->winmat); 01722 strandbuf->winx= re->winx; 01723 strandbuf->winy= re->winy; 01724 strandbuf->maxdepth= 2; 01725 strandbuf->adaptcos= cosf(DEG2RADF((float)part->adapt_angle)); 01726 strandbuf->overrideuv= sd.override_uv; 01727 strandbuf->minwidth= ma->strand_min; 01728 01729 if(ma->strand_widthfade == 0.0f) 01730 strandbuf->widthfade= 0.0f; 01731 else if(ma->strand_widthfade >= 1.0f) 01732 strandbuf->widthfade= 2.0f - ma->strand_widthfade; 01733 else 01734 strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f); 01735 01736 if(part->flag & PART_HAIR_BSPLINE) 01737 strandbuf->flag |= R_STRAND_BSPLINE; 01738 if(ma->mode & MA_STR_B_UNITS) 01739 strandbuf->flag |= R_STRAND_B_UNITS; 01740 01741 svert= strandbuf->vert; 01742 01743 if(re->r.mode & R_SPEED) 01744 dosurfacecache= 1; 01745 else if((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) 01746 if(ma->amb != 0.0f) 01747 dosurfacecache= 1; 01748 01749 totface= psmd->dm->getNumFaces(psmd->dm); 01750 origindex= psmd->dm->getFaceDataArray(psmd->dm, CD_ORIGINDEX); 01751 for(a=0; a<totface; a++) 01752 strandbuf->totbound= MAX2(strandbuf->totbound, (origindex)? origindex[a]: a); 01753 01754 strandbuf->totbound++; 01755 strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound"); 01756 sbound= strandbuf->bound; 01757 sbound->start= sbound->end= 0; 01758 } 01759 } 01760 01761 if(sd.orco == 0) { 01762 sd.orco = MEM_mallocN(3 * sizeof(float), "particle orco"); 01763 orco1 = 1; 01764 } 01765 01766 if(path_nbr == 0) 01767 psys->lattice = psys_get_lattice(&sim); 01768 01769 /* 3. start creating renderable things */ 01770 for(a=0,pa=pars; a<totpart+totchild; a++, pa++, seed++) { 01771 random = rng_getFloat(rng); 01772 /* setup per particle individual stuff */ 01773 if(a<totpart){ 01774 if(pa->flag & PARS_UNEXIST) continue; 01775 01776 pa_time=(cfra-pa->time)/pa->lifetime; 01777 pa_birthtime = pa->time; 01778 pa_dietime = pa->dietime; 01779 01780 hasize = ma->hasize; 01781 01782 /* get orco */ 01783 if(tpsys && part->phystype==PART_PHYS_NO){ 01784 tpa=tpsys->particles+pa->num; 01785 psys_particle_on_emitter(psmd,tpart->from,tpa->num,pa->num_dmcache,tpa->fuv,tpa->foffset,co,nor,0,0,sd.orco,0); 01786 } 01787 else 01788 psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,sd.orco,0); 01789 01790 /* get uvco & mcol */ 01791 num= pa->num_dmcache; 01792 01793 if(num == DMCACHE_NOTFOUND) 01794 if(pa->num < psmd->dm->getNumFaces(psmd->dm)) 01795 num= pa->num; 01796 01797 get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd); 01798 01799 pa_size = pa->size; 01800 01801 r_tilt = 2.0f*(PSYS_FRAND(a) - 0.5f); 01802 r_length = PSYS_FRAND(a+1); 01803 01804 if(path_nbr) { 01805 cache = psys->pathcache[a]; 01806 max_k = (int)cache->steps; 01807 } 01808 01809 if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue; 01810 } 01811 else { 01812 ChildParticle *cpa= psys->child+a-totpart; 01813 01814 if(path_nbr) { 01815 cache = psys->childcache[a-totpart]; 01816 01817 if(cache->steps < 0) 01818 continue; 01819 01820 max_k = (int)cache->steps; 01821 } 01822 01823 pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime); 01824 pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time); 01825 01826 r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f); 01827 r_length = PSYS_FRAND(a + 22); 01828 01829 num = cpa->num; 01830 01831 /* get orco */ 01832 if(part->childtype == PART_CHILD_FACES) { 01833 psys_particle_on_emitter(psmd, 01834 PART_FROM_FACE, cpa->num,DMCACHE_ISCHILD, 01835 cpa->fuv,cpa->foffset,co,nor,0,0,sd.orco,0); 01836 } 01837 else { 01838 ParticleData *par = psys->particles + cpa->parent; 01839 psys_particle_on_emitter(psmd, part->from, 01840 par->num,DMCACHE_ISCHILD,par->fuv, 01841 par->foffset,co,nor,0,0,sd.orco,0); 01842 } 01843 01844 /* get uvco & mcol */ 01845 if(part->childtype==PART_CHILD_FACES) { 01846 get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm, cpa->fuv, cpa->num, &sd); 01847 } 01848 else { 01849 ParticleData *parent = psys->particles + cpa->parent; 01850 num = parent->num_dmcache; 01851 01852 if(num == DMCACHE_NOTFOUND) 01853 if(parent->num < psmd->dm->getNumFaces(psmd->dm)) 01854 num = parent->num; 01855 01856 get_particle_uvco_mcol(part->from, psmd->dm, parent->fuv, num, &sd); 01857 } 01858 01859 dosimplify = psys_render_simplify_params(psys, cpa, simplify); 01860 01861 if(strandbuf) { 01862 int orignum= (origindex)? origindex[cpa->num]: cpa->num; 01863 01864 if(orignum > sbound - strandbuf->bound) { 01865 sbound= strandbuf->bound + orignum; 01866 sbound->start= sbound->end= obr->totstrand; 01867 } 01868 } 01869 } 01870 01871 /* TEXCO_PARTICLE */ 01872 pa_co[0] = pa_time; 01873 pa_co[1] = 0.f; 01874 pa_co[2] = 0.f; 01875 01876 /* surface normal shading setup */ 01877 if(ma->mode_l & MA_STR_SURFDIFF) { 01878 mul_m3_v3(nmat, nor); 01879 sd.surfnor= nor; 01880 } 01881 else 01882 sd.surfnor= NULL; 01883 01884 /* strand render setup */ 01885 if(strandbuf) { 01886 strand= RE_findOrAddStrand(obr, obr->totstrand++); 01887 strand->buffer= strandbuf; 01888 strand->vert= svert; 01889 copy_v3_v3(strand->orco, sd.orco); 01890 01891 if(dosimplify) { 01892 float *ssimplify= RE_strandren_get_simplify(obr, strand, 1); 01893 ssimplify[0]= simplify[0]; 01894 ssimplify[1]= simplify[1]; 01895 } 01896 01897 if(sd.surfnor) { 01898 float *snor= RE_strandren_get_surfnor(obr, strand, 1); 01899 copy_v3_v3(snor, sd.surfnor); 01900 } 01901 01902 if(dosurfacecache && num >= 0) { 01903 int *facenum= RE_strandren_get_face(obr, strand, 1); 01904 *facenum= num; 01905 } 01906 01907 if(sd.uvco) { 01908 for(i=0; i<sd.totuv; i++) { 01909 if(i != sd.override_uv) { 01910 float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1); 01911 01912 uv[0]= sd.uvco[2*i]; 01913 uv[1]= sd.uvco[2*i+1]; 01914 } 01915 } 01916 } 01917 if(sd.mcol) { 01918 for(i=0; i<sd.totcol; i++) { 01919 MCol *mc= RE_strandren_get_mcol(obr, strand, i, NULL, 1); 01920 *mc = sd.mcol[i]; 01921 } 01922 } 01923 01924 sbound->end++; 01925 } 01926 01927 /* strandco computation setup */ 01928 if(path_nbr) { 01929 strandlen= 0.0f; 01930 curlen= 0.0f; 01931 for(k=1; k<=path_nbr; k++) 01932 if(k<=max_k) 01933 strandlen += len_v3v3((cache+k-1)->co, (cache+k)->co); 01934 } 01935 01936 if(path_nbr) { 01937 /* render strands */ 01938 for(k=0; k<=path_nbr; k++){ 01939 float time; 01940 01941 if(k<=max_k){ 01942 copy_v3_v3(state.co,(cache+k)->co); 01943 copy_v3_v3(state.vel,(cache+k)->vel); 01944 } 01945 else 01946 continue; 01947 01948 if(k > 0) 01949 curlen += len_v3v3((cache+k-1)->co, (cache+k)->co); 01950 time= curlen/strandlen; 01951 01952 copy_v3_v3(loc,state.co); 01953 mul_m4_v3(re->viewmat,loc); 01954 01955 if(strandbuf) { 01956 copy_v3_v3(svert->co, loc); 01957 svert->strandco= -1.0f + 2.0f*time; 01958 svert++; 01959 strand->totvert++; 01960 } 01961 else{ 01962 sd.size = hasize; 01963 01964 if(k==1){ 01965 sd.first = 1; 01966 sd.time = 0.0f; 01967 sub_v3_v3v3(loc0,loc1,loc); 01968 add_v3_v3v3(loc0,loc1,loc0); 01969 01970 particle_curve(re, obr, psmd->dm, ma, &sd, loc1, loc0, seed, pa_co); 01971 } 01972 01973 sd.first = 0; 01974 sd.time = time; 01975 01976 if(k) 01977 particle_curve(re, obr, psmd->dm, ma, &sd, loc, loc1, seed, pa_co); 01978 01979 copy_v3_v3(loc1,loc); 01980 } 01981 } 01982 01983 } 01984 else { 01985 /* render normal particles */ 01986 if(part->trail_count > 1) { 01987 float length = part->path_end * (1.0f - part->randlength * r_length); 01988 int trail_count = part->trail_count * (1.0f - part->randlength * r_length); 01989 float ct = (part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time; 01990 float dt = length / (trail_count ? (float)trail_count : 1.0f); 01991 01992 /* make sure we have pointcache in memory before getting particle on path */ 01993 psys_make_temp_pointcache(ob, psys); 01994 01995 for(i=0; i < trail_count; i++, ct -= dt) { 01996 if(part->draw & PART_ABS_PATH_TIME) { 01997 if(ct < pa_birthtime || ct > pa_dietime) 01998 continue; 01999 } 02000 else if(ct < 0.0f || ct > 1.0f) 02001 continue; 02002 02003 state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct; 02004 psys_get_particle_on_path(&sim,a,&state,1); 02005 02006 if(psys->parent) 02007 mul_m4_v3(psys->parent->obmat, state.co); 02008 02009 if(use_duplimat) 02010 mul_m4_v4(duplimat, state.co); 02011 02012 if(part->ren_as == PART_DRAW_BB) { 02013 bb.random = random; 02014 bb.offset[0] = part->bb_offset[0]; 02015 bb.offset[1] = part->bb_offset[1]; 02016 bb.size[0] = part->bb_size[0] * pa_size; 02017 if (part->bb_align==PART_BB_VEL) { 02018 float pa_vel = len_v3(state.vel); 02019 float head = part->bb_vel_head*pa_vel; 02020 float tail = part->bb_vel_tail*pa_vel; 02021 bb.size[1] = part->bb_size[1]*pa_size + head + tail; 02022 /* use offset to adjust the particle center. this is relative to size, so need to divide! */ 02023 if (bb.size[1] > 0.0f) 02024 bb.offset[1] += (head-tail) / bb.size[1]; 02025 } 02026 else 02027 bb.size[1] = part->bb_size[1] * pa_size; 02028 bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt); 02029 bb.time = ct; 02030 bb.num = a; 02031 } 02032 02033 pa_co[0] = (part->draw & PART_ABS_PATH_TIME) ? (ct-pa_birthtime)/(pa_dietime-pa_birthtime) : ct; 02034 pa_co[1] = (float)i/(float)(trail_count-1); 02035 02036 particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize, pa_co); 02037 } 02038 } 02039 else { 02040 state.time=cfra; 02041 if(psys_get_particle_state(&sim,a,&state,0)==0) 02042 continue; 02043 02044 if(psys->parent) 02045 mul_m4_v3(psys->parent->obmat, state.co); 02046 02047 if(use_duplimat) 02048 mul_m4_v3(duplimat, state.co); 02049 02050 if(part->ren_as == PART_DRAW_BB) { 02051 bb.random = random; 02052 bb.offset[0] = part->bb_offset[0]; 02053 bb.offset[1] = part->bb_offset[1]; 02054 bb.size[0] = part->bb_size[0] * pa_size; 02055 if (part->bb_align==PART_BB_VEL) { 02056 float pa_vel = len_v3(state.vel); 02057 float head = part->bb_vel_head*pa_vel; 02058 float tail = part->bb_vel_tail*pa_vel; 02059 bb.size[1] = part->bb_size[1]*pa_size + head + tail; 02060 /* use offset to adjust the particle center. this is relative to size, so need to divide! */ 02061 if (bb.size[1] > 0.0f) 02062 bb.offset[1] += (head-tail) / bb.size[1]; 02063 } 02064 else 02065 bb.size[1] = part->bb_size[1] * pa_size; 02066 bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt); 02067 bb.time = pa_time; 02068 bb.num = a; 02069 bb.lifetime = pa_dietime-pa_birthtime; 02070 } 02071 02072 particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize, pa_co); 02073 } 02074 } 02075 02076 if(orco1==0) 02077 sd.orco+=3; 02078 02079 if(re->test_break(re->tbh)) 02080 break; 02081 } 02082 02083 if(dosurfacecache) 02084 strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset); 02085 02086 /* 4. clean up */ 02087 #if 0 // XXX old animation system 02088 if(ma) do_mat_ipo(re->scene, ma); 02089 #endif // XXX old animation system 02090 02091 if(orco1) 02092 MEM_freeN(sd.orco); 02093 02094 if(sd.uvco) 02095 MEM_freeN(sd.uvco); 02096 02097 if(sd.mcol) 02098 MEM_freeN(sd.mcol); 02099 02100 if(uv_name) 02101 MEM_freeN(uv_name); 02102 02103 if(states) 02104 MEM_freeN(states); 02105 02106 rng_free(rng); 02107 02108 psys->flag &= ~PSYS_DRAWING; 02109 02110 if(psys->lattice){ 02111 end_latt_deform(psys->lattice); 02112 psys->lattice= NULL; 02113 } 02114 02115 if(path_nbr && (ma->mode_l & MA_TANGENT_STR)==0) 02116 calc_vertexnormals(re, obr, 0, 0); 02117 02118 return 1; 02119 } 02120 02121 /* ------------------------------------------------------------------------- */ 02122 /* Halo's */ 02123 /* ------------------------------------------------------------------------- */ 02124 02125 static void make_render_halos(Render *re, ObjectRen *obr, Mesh *UNUSED(me), int totvert, MVert *mvert, Material *ma, float *orco) 02126 { 02127 Object *ob= obr->ob; 02128 HaloRen *har; 02129 float xn, yn, zn, nor[3], view[3]; 02130 float vec[3], hasize, mat[4][4], imat[3][3]; 02131 int a, ok, seed= ma->seed1; 02132 02133 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 02134 copy_m3_m4(imat, ob->imat); 02135 02136 re->flag |= R_HALO; 02137 02138 for(a=0; a<totvert; a++, mvert++) { 02139 ok= 1; 02140 02141 if(ok) { 02142 hasize= ma->hasize; 02143 02144 copy_v3_v3(vec, mvert->co); 02145 mul_m4_v3(mat, vec); 02146 02147 if(ma->mode & MA_HALOPUNO) { 02148 xn= mvert->no[0]; 02149 yn= mvert->no[1]; 02150 zn= mvert->no[2]; 02151 02152 /* transpose ! */ 02153 nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; 02154 nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; 02155 nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; 02156 normalize_v3(nor); 02157 02158 copy_v3_v3(view, vec); 02159 normalize_v3(view); 02160 02161 zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2]; 02162 if(zn>=0.0f) hasize= 0.0f; 02163 else hasize*= zn*zn*zn*zn; 02164 } 02165 02166 if(orco) har= RE_inithalo(re, obr, ma, vec, NULL, orco, hasize, 0.0, seed); 02167 else har= RE_inithalo(re, obr, ma, vec, NULL, mvert->co, hasize, 0.0, seed); 02168 if(har) har->lay= ob->lay; 02169 } 02170 if(orco) orco+= 3; 02171 seed++; 02172 } 02173 } 02174 02175 static int verghalo(const void *a1, const void *a2) 02176 { 02177 const HaloRen *har1= *(const HaloRen**)a1; 02178 const HaloRen *har2= *(const HaloRen**)a2; 02179 02180 if(har1->zs < har2->zs) return 1; 02181 else if(har1->zs > har2->zs) return -1; 02182 return 0; 02183 } 02184 02185 static void sort_halos(Render *re, int totsort) 02186 { 02187 ObjectRen *obr; 02188 HaloRen *har= NULL, **haso; 02189 int a; 02190 02191 if(re->tothalo==0) return; 02192 02193 re->sortedhalos= MEM_callocN(sizeof(HaloRen*)*re->tothalo, "sorthalos"); 02194 haso= re->sortedhalos; 02195 02196 for(obr=re->objecttable.first; obr; obr=obr->next) { 02197 for(a=0; a<obr->tothalo; a++) { 02198 if((a & 255)==0) har= obr->bloha[a>>8]; 02199 else har++; 02200 02201 *(haso++)= har; 02202 } 02203 } 02204 02205 qsort(re->sortedhalos, totsort, sizeof(HaloRen*), verghalo); 02206 } 02207 02208 /* ------------------------------------------------------------------------- */ 02209 /* Displacement Mapping */ 02210 /* ------------------------------------------------------------------------- */ 02211 02212 static short test_for_displace(Render *re, Object *ob) 02213 { 02214 /* return 1 when this object uses displacement textures. */ 02215 Material *ma; 02216 int i; 02217 02218 for (i=1; i<=ob->totcol; i++) { 02219 ma=give_render_material(re, ob, i); 02220 /* ma->mapto is ORed total of all mapto channels */ 02221 if(ma && (ma->mapto & MAP_DISPLACE)) return 1; 02222 } 02223 return 0; 02224 } 02225 02226 static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, VertRen *vr, int vindex, float *scale, float mat[][4], float imat[][3]) 02227 { 02228 MTFace *tface; 02229 short texco= shi->mat->texco; 02230 float sample=0, displace[3]; 02231 char *name; 02232 int i; 02233 02234 /* shi->co is current render coord, just make sure at least some vector is here */ 02235 copy_v3_v3(shi->co, vr->co); 02236 /* vertex normal is used for textures type 'col' and 'var' */ 02237 copy_v3_v3(shi->vn, vr->n); 02238 02239 if(mat) 02240 mul_m4_v3(mat, shi->co); 02241 02242 if(imat) { 02243 shi->vn[0]= imat[0][0]*vr->n[0]+imat[0][1]*vr->n[1]+imat[0][2]*vr->n[2]; 02244 shi->vn[1]= imat[1][0]*vr->n[0]+imat[1][1]*vr->n[1]+imat[1][2]*vr->n[2]; 02245 shi->vn[2]= imat[2][0]*vr->n[0]+imat[2][1]*vr->n[1]+imat[2][2]*vr->n[2]; 02246 } 02247 02248 if (texco & TEXCO_UV) { 02249 shi->totuv= 0; 02250 shi->actuv= obr->actmtface; 02251 02252 for (i=0; (tface=RE_vlakren_get_tface(obr, shi->vlr, i, &name, 0)); i++) { 02253 ShadeInputUV *suv= &shi->uv[i]; 02254 02255 /* shi.uv needs scale correction from tface uv */ 02256 suv->uv[0]= 2*tface->uv[vindex][0]-1.0f; 02257 suv->uv[1]= 2*tface->uv[vindex][1]-1.0f; 02258 suv->uv[2]= 0.0f; 02259 suv->name= name; 02260 shi->totuv++; 02261 } 02262 } 02263 02264 /* set all rendercoords, 'texco' is an ORed value for all textures needed */ 02265 if ((texco & TEXCO_ORCO) && (vr->orco)) { 02266 copy_v3_v3(shi->lo, vr->orco); 02267 } 02268 if (texco & TEXCO_STICKY) { 02269 float *sticky= RE_vertren_get_sticky(obr, vr, 0); 02270 if(sticky) { 02271 shi->sticky[0]= sticky[0]; 02272 shi->sticky[1]= sticky[1]; 02273 shi->sticky[2]= 0.0f; 02274 } 02275 } 02276 if (texco & TEXCO_GLOB) { 02277 copy_v3_v3(shi->gl, shi->co); 02278 mul_m4_v3(re->viewinv, shi->gl); 02279 } 02280 if (texco & TEXCO_NORM) { 02281 copy_v3_v3(shi->orn, shi->vn); 02282 } 02283 if(texco & TEXCO_REFL) { 02284 /* not (yet?) */ 02285 } 02286 if(texco & TEXCO_STRESS) { 02287 float *s= RE_vertren_get_stress(obr, vr, 0); 02288 02289 if(s) { 02290 shi->stress= *s; 02291 if(shi->stress<1.0f) shi->stress-= 1.0f; 02292 else shi->stress= (shi->stress-1.0f)/shi->stress; 02293 } 02294 else 02295 shi->stress= 0.0f; 02296 } 02297 02298 shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0; 02299 02300 do_material_tex(shi, re); 02301 02302 //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2], 02303 //vr->co[0], vr->co[1], vr->co[2]); 02304 02305 displace[0]= shi->displace[0] * scale[0]; 02306 displace[1]= shi->displace[1] * scale[1]; 02307 displace[2]= shi->displace[2] * scale[2]; 02308 02309 if(mat) 02310 mul_m3_v3(imat, displace); 02311 02312 /* 0.5 could become button once? */ 02313 vr->co[0] += displace[0]; 02314 vr->co[1] += displace[1]; 02315 vr->co[2] += displace[2]; 02316 02317 //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]); 02318 02319 /* we just don't do this vertex again, bad luck for other face using same vertex with 02320 different material... */ 02321 vr->flag |= 1; 02322 02323 /* Pass sample back so displace_face can decide which way to split the quad */ 02324 sample = shi->displace[0]*shi->displace[0]; 02325 sample += shi->displace[1]*shi->displace[1]; 02326 sample += shi->displace[2]*shi->displace[2]; 02327 02328 vr->accum=sample; 02329 /* Should be sqrt(sample), but I'm only looking for "bigger". Save the cycles. */ 02330 return; 02331 } 02332 02333 static void displace_render_face(Render *re, ObjectRen *obr, VlakRen *vlr, float *scale, float mat[][4], float imat[][3]) 02334 { 02335 ShadeInput shi; 02336 02337 /* Warning, This is not that nice, and possibly a bit slow, 02338 however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ 02339 memset(&shi, 0, sizeof(ShadeInput)); 02340 /* end warning! - Campbell */ 02341 02342 /* set up shadeinput struct for multitex() */ 02343 02344 /* memset above means we dont need this */ 02345 /*shi.osatex= 0;*/ /* signal not to use dx[] and dy[] texture AA vectors */ 02346 02347 shi.obr= obr; 02348 shi.vlr= vlr; /* current render face */ 02349 shi.mat= vlr->mat; /* current input material */ 02350 shi.thread= 0; 02351 02352 /* TODO, assign these, displacement with new bumpmap is skipped without - campbell */ 02353 #if 0 02354 /* order is not known ? */ 02355 shi.v1= vlr->v1; 02356 shi.v2= vlr->v2; 02357 shi.v3= vlr->v3; 02358 #endif 02359 02360 /* Displace the verts, flag is set when done */ 02361 if (!vlr->v1->flag) 02362 displace_render_vert(re, obr, &shi, vlr->v1,0, scale, mat, imat); 02363 02364 if (!vlr->v2->flag) 02365 displace_render_vert(re, obr, &shi, vlr->v2, 1, scale, mat, imat); 02366 02367 if (!vlr->v3->flag) 02368 displace_render_vert(re, obr, &shi, vlr->v3, 2, scale, mat, imat); 02369 02370 if (vlr->v4) { 02371 if (!vlr->v4->flag) 02372 displace_render_vert(re, obr, &shi, vlr->v4, 3, scale, mat, imat); 02373 02374 /* closest in displace value. This will help smooth edges. */ 02375 if ( fabs(vlr->v1->accum - vlr->v3->accum) > fabs(vlr->v2->accum - vlr->v4->accum)) 02376 vlr->flag |= R_DIVIDE_24; 02377 else vlr->flag &= ~R_DIVIDE_24; 02378 } 02379 02380 /* Recalculate the face normal - if flipped before, flip now */ 02381 if(vlr->v4) { 02382 normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 02383 } 02384 else { 02385 normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); 02386 } 02387 } 02388 02389 static void do_displacement(Render *re, ObjectRen *obr, float mat[][4], float imat[][3]) 02390 { 02391 VertRen *vr; 02392 VlakRen *vlr; 02393 // float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30}; 02394 float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn 02395 int i; //, texflag=0; 02396 Object *obt; 02397 02398 /* Object Size with parenting */ 02399 obt=obr->ob; 02400 while(obt){ 02401 mul_v3_v3v3(temp, obt->size, obt->dscale); 02402 scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2]; 02403 obt=obt->parent; 02404 } 02405 02406 /* Clear all flags */ 02407 for(i=0; i<obr->totvert; i++){ 02408 vr= RE_findOrAddVert(obr, i); 02409 vr->flag= 0; 02410 } 02411 02412 for(i=0; i<obr->totvlak; i++){ 02413 vlr=RE_findOrAddVlak(obr, i); 02414 displace_render_face(re, obr, vlr, scale, mat, imat); 02415 } 02416 02417 /* Recalc vertex normals */ 02418 calc_vertexnormals(re, obr, 0, 0); 02419 } 02420 02421 /* ------------------------------------------------------------------------- */ 02422 /* Metaball */ 02423 /* ------------------------------------------------------------------------- */ 02424 02425 static void init_render_mball(Render *re, ObjectRen *obr) 02426 { 02427 Object *ob= obr->ob; 02428 DispList *dl; 02429 VertRen *ver; 02430 VlakRen *vlr, *vlr1; 02431 Material *ma; 02432 float *data, *nors, *orco=NULL, mat[4][4], imat[3][3], xn, yn, zn; 02433 int a, need_orco, vlakindex, *index; 02434 ListBase dispbase= {NULL, NULL}; 02435 02436 if (ob!=find_basis_mball(re->scene, ob)) 02437 return; 02438 02439 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 02440 invert_m4_m4(ob->imat, mat); 02441 copy_m3_m4(imat, ob->imat); 02442 02443 ma= give_render_material(re, ob, 1); 02444 02445 need_orco= 0; 02446 if(ma->texco & TEXCO_ORCO) { 02447 need_orco= 1; 02448 } 02449 02450 makeDispListMBall_forRender(re->scene, ob, &dispbase); 02451 dl= dispbase.first; 02452 if(dl==0) return; 02453 02454 data= dl->verts; 02455 nors= dl->nors; 02456 if(need_orco) { 02457 orco= get_object_orco(re, ob); 02458 02459 if (!orco) { 02460 /* orco hasn't been found in cache - create new one and add to cache */ 02461 orco= make_orco_mball(ob, &dispbase); 02462 set_object_orco(re, ob, orco); 02463 } 02464 } 02465 02466 for(a=0; a<dl->nr; a++, data+=3, nors+=3) { 02467 02468 ver= RE_findOrAddVert(obr, obr->totvert++); 02469 copy_v3_v3(ver->co, data); 02470 mul_m4_v3(mat, ver->co); 02471 02472 /* render normals are inverted */ 02473 xn= -nors[0]; 02474 yn= -nors[1]; 02475 zn= -nors[2]; 02476 02477 /* transpose ! */ 02478 ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; 02479 ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; 02480 ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; 02481 normalize_v3(ver->n); 02482 //if(ob->transflag & OB_NEG_SCALE) negate_v3(ver->n); 02483 02484 if(need_orco) { 02485 ver->orco= orco; 02486 orco+=3; 02487 } 02488 } 02489 02490 index= dl->index; 02491 for(a=0; a<dl->parts; a++, index+=4) { 02492 02493 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 02494 vlr->v1= RE_findOrAddVert(obr, index[0]); 02495 vlr->v2= RE_findOrAddVert(obr, index[1]); 02496 vlr->v3= RE_findOrAddVert(obr, index[2]); 02497 vlr->v4= 0; 02498 02499 if(ob->transflag & OB_NEG_SCALE) 02500 normal_tri_v3( vlr->n,vlr->v1->co, vlr->v2->co, vlr->v3->co); 02501 else 02502 normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); 02503 02504 vlr->mat= ma; 02505 vlr->flag= ME_SMOOTH; 02506 vlr->ec= 0; 02507 02508 /* mball -too bad- always has triangles, because quads can be non-planar */ 02509 if(index[3] && index[3]!=index[2]) { 02510 vlr1= RE_findOrAddVlak(obr, obr->totvlak++); 02511 vlakindex= vlr1->index; 02512 *vlr1= *vlr; 02513 vlr1->index= vlakindex; 02514 vlr1->v2= vlr1->v3; 02515 vlr1->v3= RE_findOrAddVert(obr, index[3]); 02516 if(ob->transflag & OB_NEG_SCALE) 02517 normal_tri_v3( vlr1->n,vlr1->v1->co, vlr1->v2->co, vlr1->v3->co); 02518 else 02519 normal_tri_v3( vlr1->n,vlr1->v3->co, vlr1->v2->co, vlr1->v1->co); 02520 } 02521 } 02522 02523 /* enforce display lists remade */ 02524 freedisplist(&dispbase); 02525 } 02526 02527 /* ------------------------------------------------------------------------- */ 02528 /* Surfaces and Curves */ 02529 /* ------------------------------------------------------------------------- */ 02530 02531 /* returns amount of vertices added for orco */ 02532 static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, float *orco, float mat[4][4]) 02533 { 02534 VertRen *v1, *v2, *v3, *v4, *ver; 02535 VlakRen *vlr, *vlr1, *vlr2, *vlr3; 02536 float *data, n1[3]; 02537 int u, v, orcoret= 0; 02538 int p1, p2, p3, p4, a; 02539 int sizeu, nsizeu, sizev, nsizev; 02540 int startvert, startvlak; 02541 02542 startvert= obr->totvert; 02543 nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr; 02544 02545 data= dl->verts; 02546 for (u = 0; u < sizeu; u++) { 02547 v1 = RE_findOrAddVert(obr, obr->totvert++); /* save this for possible V wrapping */ 02548 copy_v3_v3(v1->co, data); data += 3; 02549 if(orco) { 02550 v1->orco= orco; orco+= 3; orcoret++; 02551 } 02552 mul_m4_v3(mat, v1->co); 02553 02554 for (v = 1; v < sizev; v++) { 02555 ver= RE_findOrAddVert(obr, obr->totvert++); 02556 copy_v3_v3(ver->co, data); data += 3; 02557 if(orco) { 02558 ver->orco= orco; orco+= 3; orcoret++; 02559 } 02560 mul_m4_v3(mat, ver->co); 02561 } 02562 /* if V-cyclic, add extra vertices at end of the row */ 02563 if (dl->flag & DL_CYCL_U) { 02564 ver= RE_findOrAddVert(obr, obr->totvert++); 02565 copy_v3_v3(ver->co, v1->co); 02566 if(orco) { 02567 ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0); 02568 } 02569 } 02570 } 02571 02572 /* Done before next loop to get corner vert */ 02573 if (dl->flag & DL_CYCL_U) nsizev++; 02574 if (dl->flag & DL_CYCL_V) nsizeu++; 02575 02576 /* if U cyclic, add extra row at end of column */ 02577 if (dl->flag & DL_CYCL_V) { 02578 for (v = 0; v < nsizev; v++) { 02579 v1= RE_findOrAddVert(obr, startvert + v); 02580 ver= RE_findOrAddVert(obr, obr->totvert++); 02581 copy_v3_v3(ver->co, v1->co); 02582 if(orco) { 02583 ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v); 02584 } 02585 } 02586 } 02587 02588 sizeu = nsizeu; 02589 sizev = nsizev; 02590 02591 startvlak= obr->totvlak; 02592 02593 for(u = 0; u < sizeu - 1; u++) { 02594 p1 = startvert + u * sizev; /* walk through face list */ 02595 p2 = p1 + 1; 02596 p3 = p2 + sizev; 02597 p4 = p3 - 1; 02598 02599 for(v = 0; v < sizev - 1; v++) { 02600 v1= RE_findOrAddVert(obr, p1); 02601 v2= RE_findOrAddVert(obr, p2); 02602 v3= RE_findOrAddVert(obr, p3); 02603 v4= RE_findOrAddVert(obr, p4); 02604 02605 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 02606 vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4; 02607 02608 normal_quad_v3( n1,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 02609 02610 copy_v3_v3(vlr->n, n1); 02611 02612 vlr->mat= matar[ dl->col]; 02613 vlr->ec= ME_V1V2+ME_V2V3; 02614 vlr->flag= dl->rt; 02615 02616 add_v3_v3(v1->n, n1); 02617 add_v3_v3(v2->n, n1); 02618 add_v3_v3(v3->n, n1); 02619 add_v3_v3(v4->n, n1); 02620 02621 p1++; p2++; p3++; p4++; 02622 } 02623 } 02624 /* fix normals for U resp. V cyclic faces */ 02625 sizeu--; sizev--; /* dec size for face array */ 02626 if (dl->flag & DL_CYCL_V) { 02627 02628 for (v = 0; v < sizev; v++) 02629 { 02630 /* optimize! :*/ 02631 vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, v)); 02632 vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, v)); 02633 add_v3_v3(vlr1->v1->n, vlr->n); 02634 add_v3_v3(vlr1->v2->n, vlr->n); 02635 add_v3_v3(vlr->v3->n, vlr1->n); 02636 add_v3_v3(vlr->v4->n, vlr1->n); 02637 } 02638 } 02639 if (dl->flag & DL_CYCL_U) { 02640 02641 for (u = 0; u < sizeu; u++) 02642 { 02643 /* optimize! :*/ 02644 vlr= RE_findOrAddVlak(obr, UVTOINDEX(u, 0)); 02645 vlr1= RE_findOrAddVlak(obr, UVTOINDEX(u, sizev-1)); 02646 add_v3_v3(vlr1->v2->n, vlr->n); 02647 add_v3_v3(vlr1->v3->n, vlr->n); 02648 add_v3_v3(vlr->v1->n, vlr1->n); 02649 add_v3_v3(vlr->v4->n, vlr1->n); 02650 } 02651 } 02652 /* last vertex is an extra case: 02653 02654 ^ ()----()----()----() 02655 | | | || | 02656 u | |(0,n)||(0,0)| 02657 | | || | 02658 ()====()====[]====() 02659 | | || | 02660 | |(m,n)||(m,0)| 02661 | | || | 02662 ()----()----()----() 02663 v -> 02664 02665 vertex [] is no longer shared, therefore distribute 02666 normals of the surrounding faces to all of the duplicates of [] 02667 */ 02668 02669 if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)) 02670 { 02671 vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */ 02672 vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0,0)); /* (0,0) */ 02673 add_v3_v3v3(n1, vlr->n, vlr1->n); 02674 vlr2= RE_findOrAddVlak(obr, UVTOINDEX(0, sizev-1)); /* (0,n) */ 02675 add_v3_v3(n1, vlr2->n); 02676 vlr3= RE_findOrAddVlak(obr, UVTOINDEX(sizeu-1, 0)); /* (m,0) */ 02677 add_v3_v3(n1, vlr3->n); 02678 copy_v3_v3(vlr->v3->n, n1); 02679 copy_v3_v3(vlr1->v1->n, n1); 02680 copy_v3_v3(vlr2->v2->n, n1); 02681 copy_v3_v3(vlr3->v4->n, n1); 02682 } 02683 for(a = startvert; a < obr->totvert; a++) { 02684 ver= RE_findOrAddVert(obr, a); 02685 normalize_v3(ver->n); 02686 } 02687 02688 02689 return orcoret; 02690 } 02691 02692 static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr, 02693 int timeoffset, float *orco, float mat[4][4]) 02694 { 02695 Object *ob= obr->ob; 02696 int a, end, totvert, vertofs; 02697 short mat_iter; 02698 VertRen *ver; 02699 VlakRen *vlr; 02700 MVert *mvert = NULL; 02701 MFace *mface; 02702 Material *ma; 02703 /* Curve *cu= ELEM(ob->type, OB_FONT, OB_CURVE) ? ob->data : NULL; */ 02704 02705 mvert= dm->getVertArray(dm); 02706 totvert= dm->getNumVerts(dm); 02707 02708 for(a=0; a<totvert; a++, mvert++) { 02709 ver= RE_findOrAddVert(obr, obr->totvert++); 02710 copy_v3_v3(ver->co, mvert->co); 02711 mul_m4_v3(mat, ver->co); 02712 02713 if(orco) { 02714 ver->orco= orco; 02715 orco+=3; 02716 } 02717 } 02718 02719 if(!timeoffset) { 02720 /* store customdata names, because DerivedMesh is freed */ 02721 RE_set_customdata_names(obr, &dm->faceData); 02722 02723 /* still to do for keys: the correct local texture coordinate */ 02724 02725 /* faces in order of color blocks */ 02726 vertofs= obr->totvert - totvert; 02727 for(mat_iter= 0; (mat_iter < ob->totcol || (mat_iter==0 && ob->totcol==0)); mat_iter++) { 02728 02729 ma= give_render_material(re, ob, mat_iter+1); 02730 end= dm->getNumFaces(dm); 02731 mface= dm->getFaceArray(dm); 02732 02733 for(a=0; a<end; a++, mface++) { 02734 int v1, v2, v3, v4, flag; 02735 02736 if(mface->mat_nr == mat_iter) { 02737 float len; 02738 02739 v1= mface->v1; 02740 v2= mface->v2; 02741 v3= mface->v3; 02742 v4= mface->v4; 02743 flag= mface->flag & ME_SMOOTH; 02744 02745 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 02746 vlr->v1= RE_findOrAddVert(obr, vertofs+v1); 02747 vlr->v2= RE_findOrAddVert(obr, vertofs+v2); 02748 vlr->v3= RE_findOrAddVert(obr, vertofs+v3); 02749 if(v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4); 02750 else vlr->v4= 0; 02751 02752 /* render normals are inverted in render */ 02753 if(vlr->v4) 02754 len= normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 02755 else 02756 len= normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); 02757 02758 vlr->mat= ma; 02759 vlr->flag= flag; 02760 vlr->ec= 0; /* mesh edges rendered separately */ 02761 02762 if(len==0) obr->totvlak--; 02763 else { 02764 CustomDataLayer *layer; 02765 MTFace *mtface, *mtf; 02766 MCol *mcol, *mc; 02767 int index, mtfn= 0, mcn= 0; 02768 char *name; 02769 02770 for(index=0; index<dm->faceData.totlayer; index++) { 02771 layer= &dm->faceData.layers[index]; 02772 name= layer->name; 02773 02774 if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { 02775 mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); 02776 mtface= (MTFace*)layer->data; 02777 *mtf= mtface[a]; 02778 } 02779 else if(layer->type == CD_MCOL && mcn < MAX_MCOL) { 02780 mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); 02781 mcol= (MCol*)layer->data; 02782 memcpy(mc, &mcol[a*4], sizeof(MCol)*4); 02783 } 02784 } 02785 } 02786 } 02787 } 02788 } 02789 02790 /* Normals */ 02791 calc_vertexnormals(re, obr, 0, 0); 02792 } 02793 02794 } 02795 02796 static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset) 02797 { 02798 Object *ob= obr->ob; 02799 Nurb *nu=0; 02800 Curve *cu; 02801 ListBase displist= {NULL, NULL}; 02802 DispList *dl; 02803 Material **matar; 02804 float *orco=NULL, mat[4][4]; 02805 int a, totmat, need_orco=0; 02806 DerivedMesh *dm= NULL; 02807 02808 cu= ob->data; 02809 nu= cu->nurb.first; 02810 if(nu==0) return; 02811 02812 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 02813 invert_m4_m4(ob->imat, mat); 02814 02815 /* material array */ 02816 totmat= ob->totcol+1; 02817 matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar"); 02818 02819 for(a=0; a<totmat; a++) { 02820 matar[a]= give_render_material(re, ob, a+1); 02821 02822 if(matar[a] && matar[a]->texco & TEXCO_ORCO) 02823 need_orco= 1; 02824 } 02825 02826 if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1; 02827 02828 makeDispListSurf(re->scene, ob, &displist, &dm, 1, 0); 02829 02830 if (dm) { 02831 if(need_orco) { 02832 orco= makeOrcoDispList(re->scene, ob, dm, 1); 02833 if(orco) { 02834 set_object_orco(re, ob, orco); 02835 } 02836 } 02837 02838 init_render_dm(dm, re, obr, timeoffset, orco, mat); 02839 dm->release(dm); 02840 } else { 02841 if(need_orco) { 02842 orco= get_object_orco(re, ob); 02843 } 02844 02845 /* walk along displaylist and create rendervertices/-faces */ 02846 for(dl=displist.first; dl; dl=dl->next) { 02847 /* watch out: u ^= y, v ^= x !! */ 02848 if(dl->type==DL_SURF) 02849 orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); 02850 } 02851 } 02852 02853 freedisplist(&displist); 02854 02855 MEM_freeN(matar); 02856 } 02857 02858 static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) 02859 { 02860 Object *ob= obr->ob; 02861 Curve *cu; 02862 VertRen *ver; 02863 VlakRen *vlr; 02864 DispList *dl; 02865 DerivedMesh *dm = NULL; 02866 ListBase disp={NULL, NULL}; 02867 Material **matar; 02868 float *data, *fp, *orco=NULL; 02869 float n[3], mat[4][4]; 02870 int nr, startvert, a, b; 02871 int need_orco=0, totmat; 02872 02873 cu= ob->data; 02874 if(ob->type==OB_FONT && cu->str==NULL) return; 02875 else if(ob->type==OB_CURVE && cu->nurb.first==NULL) return; 02876 02877 makeDispListCurveTypes_forRender(re->scene, ob, &disp, &dm, 0); 02878 dl= disp.first; 02879 if(dl==NULL) return; 02880 02881 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 02882 invert_m4_m4(ob->imat, mat); 02883 02884 /* material array */ 02885 totmat= ob->totcol+1; 02886 matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar"); 02887 02888 for(a=0; a<totmat; a++) { 02889 matar[a]= give_render_material(re, ob, a+1); 02890 02891 if(matar[a] && matar[a]->texco & TEXCO_ORCO) 02892 need_orco= 1; 02893 } 02894 02895 if (dm) { 02896 if(need_orco) { 02897 orco= makeOrcoDispList(re->scene, ob, dm, 1); 02898 if(orco) { 02899 set_object_orco(re, ob, orco); 02900 } 02901 } 02902 02903 init_render_dm(dm, re, obr, timeoffset, orco, mat); 02904 dm->release(dm); 02905 } else { 02906 if(need_orco) { 02907 orco= get_object_orco(re, ob); 02908 } 02909 02910 while(dl) { 02911 if(dl->col > ob->totcol) { 02912 /* pass */ 02913 } 02914 else if(dl->type==DL_INDEX3) { 02915 int *index; 02916 02917 startvert= obr->totvert; 02918 data= dl->verts; 02919 02920 for(a=0; a<dl->nr; a++, data+=3) { 02921 ver= RE_findOrAddVert(obr, obr->totvert++); 02922 copy_v3_v3(ver->co, data); 02923 02924 mul_m4_v3(mat, ver->co); 02925 02926 if (orco) { 02927 ver->orco = orco; 02928 orco += 3; 02929 } 02930 } 02931 02932 if(timeoffset==0) { 02933 float tmp[3]; 02934 const int startvlak= obr->totvlak; 02935 02936 zero_v3(n); 02937 index= dl->index; 02938 for(a=0; a<dl->parts; a++, index+=3) { 02939 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 02940 vlr->v1= RE_findOrAddVert(obr, startvert+index[0]); 02941 vlr->v2= RE_findOrAddVert(obr, startvert+index[1]); 02942 vlr->v3= RE_findOrAddVert(obr, startvert+index[2]); 02943 vlr->v4= NULL; 02944 02945 if(area_tri_v3(vlr->v3->co, vlr->v2->co, vlr->v1->co)>FLT_EPSILON) { 02946 normal_tri_v3(tmp, vlr->v3->co, vlr->v2->co, vlr->v1->co); 02947 add_v3_v3(n, tmp); 02948 } 02949 02950 vlr->mat= matar[ dl->col ]; 02951 vlr->flag= 0; 02952 vlr->ec= 0; 02953 } 02954 02955 normalize_v3(n); 02956 02957 /* vertex normals */ 02958 for(a= startvlak; a<obr->totvlak; a++) { 02959 vlr= RE_findOrAddVlak(obr, a); 02960 02961 copy_v3_v3(vlr->n, n); 02962 add_v3_v3(vlr->v1->n, vlr->n); 02963 add_v3_v3(vlr->v3->n, vlr->n); 02964 add_v3_v3(vlr->v2->n, vlr->n); 02965 } 02966 for(a=startvert; a<obr->totvert; a++) { 02967 ver= RE_findOrAddVert(obr, a); 02968 normalize_v3(ver->n); 02969 } 02970 } 02971 } 02972 else if (dl->type==DL_SURF) { 02973 02974 /* cyclic U means an extruded full circular curve, we skip bevel splitting then */ 02975 if (dl->flag & DL_CYCL_U) { 02976 orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); 02977 } 02978 else { 02979 int p1,p2,p3,p4; 02980 02981 fp= dl->verts; 02982 startvert= obr->totvert; 02983 nr= dl->nr*dl->parts; 02984 02985 while(nr--) { 02986 ver= RE_findOrAddVert(obr, obr->totvert++); 02987 02988 copy_v3_v3(ver->co, fp); 02989 mul_m4_v3(mat, ver->co); 02990 fp+= 3; 02991 02992 if (orco) { 02993 ver->orco = orco; 02994 orco += 3; 02995 } 02996 } 02997 02998 if(dl->bevelSplitFlag || timeoffset==0) { 02999 const int startvlak= obr->totvlak; 03000 03001 for(a=0; a<dl->parts; a++) { 03002 03003 if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0) 03004 break; 03005 03006 p1+= startvert; 03007 p2+= startvert; 03008 p3+= startvert; 03009 p4+= startvert; 03010 03011 for(; b<dl->nr; b++) { 03012 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 03013 /* important 1 offset in order is kept [#24913] */ 03014 vlr->v1= RE_findOrAddVert(obr, p2); 03015 vlr->v2= RE_findOrAddVert(obr, p1); 03016 vlr->v3= RE_findOrAddVert(obr, p3); 03017 vlr->v4= RE_findOrAddVert(obr, p4); 03018 vlr->ec= ME_V2V3+ME_V3V4; 03019 if(a==0) vlr->ec+= ME_V1V2; 03020 03021 vlr->flag= dl->rt; 03022 03023 normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 03024 vlr->mat= matar[ dl->col ]; 03025 03026 p4= p3; 03027 p3++; 03028 p2= p1; 03029 p1++; 03030 } 03031 } 03032 03033 if (dl->bevelSplitFlag) { 03034 for(a=0; a<dl->parts-1+!!(dl->flag&DL_CYCL_V); a++) 03035 if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F))) 03036 split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U); 03037 } 03038 03039 /* vertex normals */ 03040 for(a= startvlak; a<obr->totvlak; a++) { 03041 vlr= RE_findOrAddVlak(obr, a); 03042 03043 add_v3_v3(vlr->v1->n, vlr->n); 03044 add_v3_v3(vlr->v3->n, vlr->n); 03045 add_v3_v3(vlr->v2->n, vlr->n); 03046 add_v3_v3(vlr->v4->n, vlr->n); 03047 } 03048 for(a=startvert; a<obr->totvert; a++) { 03049 ver= RE_findOrAddVert(obr, a); 03050 normalize_v3(ver->n); 03051 } 03052 } 03053 } 03054 } 03055 03056 dl= dl->next; 03057 } 03058 } 03059 03060 freedisplist(&disp); 03061 03062 MEM_freeN(matar); 03063 } 03064 03065 /* ------------------------------------------------------------------------- */ 03066 /* Mesh */ 03067 /* ------------------------------------------------------------------------- */ 03068 03069 struct edgesort { 03070 unsigned int v1, v2; 03071 int f; 03072 unsigned int i1, i2; 03073 }; 03074 03075 /* edges have to be added with lowest index first for sorting */ 03076 static void to_edgesort(struct edgesort *ed, 03077 unsigned int i1, unsigned int i2, 03078 unsigned int v1, unsigned int v2, int f) 03079 { 03080 if (v1 > v2) { 03081 SWAP(unsigned int, v1, v2); 03082 SWAP(unsigned int, i1, i2); 03083 } 03084 03085 ed->v1= v1; 03086 ed->v2= v2; 03087 ed->i1= i1; 03088 ed->i2= i2; 03089 ed->f = f; 03090 } 03091 03092 static int vergedgesort(const void *v1, const void *v2) 03093 { 03094 const struct edgesort *x1=v1, *x2=v2; 03095 03096 if( x1->v1 > x2->v1) return 1; 03097 else if( x1->v1 < x2->v1) return -1; 03098 else if( x1->v2 > x2->v2) return 1; 03099 else if( x1->v2 < x2->v2) return -1; 03100 03101 return 0; 03102 } 03103 03104 static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort) 03105 { 03106 MFace *mf, *mface; 03107 MTFace *tface=NULL; 03108 struct edgesort *edsort, *ed; 03109 unsigned int *mcol=NULL; 03110 int a, totedge=0, totface; 03111 03112 mface= dm->getFaceArray(dm); 03113 totface= dm->getNumFaces(dm); 03114 tface= dm->getFaceDataArray(dm, CD_MTFACE); 03115 mcol= dm->getFaceDataArray(dm, CD_MCOL); 03116 03117 if(mcol==NULL && tface==NULL) return NULL; 03118 03119 /* make sorted table with edges and face indices in it */ 03120 for(a= totface, mf= mface; a>0; a--, mf++) { 03121 if(mf->v4) totedge+=4; 03122 else if(mf->v3) totedge+=3; 03123 } 03124 03125 if(totedge==0) 03126 return NULL; 03127 03128 ed= edsort= MEM_callocN(totedge*sizeof(struct edgesort), "edgesort"); 03129 03130 for(a=0, mf=mface; a<totface; a++, mf++) { 03131 to_edgesort(ed++, 0, 1, mf->v1, mf->v2, a); 03132 to_edgesort(ed++, 1, 2, mf->v2, mf->v3, a); 03133 if(mf->v4) { 03134 to_edgesort(ed++, 2, 3, mf->v3, mf->v4, a); 03135 to_edgesort(ed++, 3, 0, mf->v4, mf->v1, a); 03136 } 03137 else if(mf->v3) 03138 to_edgesort(ed++, 2, 3, mf->v3, mf->v1, a); 03139 } 03140 03141 qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort); 03142 03143 *totedgesort= totedge; 03144 03145 return edsort; 03146 } 03147 03148 static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge) 03149 { 03150 struct edgesort ed, *edp; 03151 CustomDataLayer *layer; 03152 MTFace *mtface, *mtf; 03153 MCol *mcol, *mc; 03154 int index, mtfn, mcn; 03155 char *name; 03156 03157 if(medge->v1 < medge->v2) { 03158 ed.v1= medge->v1; 03159 ed.v2= medge->v2; 03160 } 03161 else { 03162 ed.v1= medge->v2; 03163 ed.v2= medge->v1; 03164 } 03165 03166 edp= bsearch(&ed, edgetable, totedge, sizeof(struct edgesort), vergedgesort); 03167 03168 /* since edges have different index ordering, we have to duplicate mcol and tface */ 03169 if(edp) { 03170 mtfn= mcn= 0; 03171 03172 for(index=0; index<dm->faceData.totlayer; index++) { 03173 layer= &dm->faceData.layers[index]; 03174 name= layer->name; 03175 03176 if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { 03177 mtface= &((MTFace*)layer->data)[edp->f]; 03178 mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); 03179 03180 *mtf= *mtface; 03181 03182 memcpy(mtf->uv[0], mtface->uv[edp->i1], sizeof(float)*2); 03183 memcpy(mtf->uv[1], mtface->uv[edp->i2], sizeof(float)*2); 03184 memcpy(mtf->uv[2], mtface->uv[1], sizeof(float)*2); 03185 memcpy(mtf->uv[3], mtface->uv[1], sizeof(float)*2); 03186 } 03187 else if(layer->type == CD_MCOL && mcn < MAX_MCOL) { 03188 mcol= &((MCol*)layer->data)[edp->f*4]; 03189 mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); 03190 03191 mc[0]= mcol[edp->i1]; 03192 mc[1]= mc[2]= mc[3]= mcol[edp->i2]; 03193 } 03194 } 03195 } 03196 } 03197 03198 static void free_camera_inside_volumes(Render *re) 03199 { 03200 BLI_freelistN(&re->render_volumes_inside); 03201 } 03202 03203 static void init_camera_inside_volumes(Render *re) 03204 { 03205 ObjectInstanceRen *obi; 03206 VolumeOb *vo; 03207 float co[3] = {0.f, 0.f, 0.f}; 03208 03209 for(vo= re->volumes.first; vo; vo= vo->next) { 03210 for(obi= re->instancetable.first; obi; obi= obi->next) { 03211 if (obi->obr == vo->obr) { 03212 if (point_inside_volume_objectinstance(re, obi, co)) { 03213 MatInside *mi; 03214 03215 mi = MEM_mallocN(sizeof(MatInside), "camera inside material"); 03216 mi->ma = vo->ma; 03217 mi->obi = obi; 03218 03219 BLI_addtail(&(re->render_volumes_inside), mi); 03220 } 03221 } 03222 } 03223 } 03224 03225 /* debug { 03226 MatInside *m; 03227 for (m=re->render_volumes_inside.first; m; m=m->next) { 03228 printf("matinside: ma: %s \n", m->ma->id.name+2); 03229 } 03230 }*/ 03231 } 03232 03233 static void add_volume(Render *re, ObjectRen *obr, Material *ma) 03234 { 03235 struct VolumeOb *vo; 03236 03237 vo = MEM_mallocN(sizeof(VolumeOb), "volume object"); 03238 03239 vo->ma = ma; 03240 vo->obr = obr; 03241 03242 BLI_addtail(&re->volumes, vo); 03243 } 03244 03245 static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) 03246 { 03247 Object *ob= obr->ob; 03248 Mesh *me; 03249 MVert *mvert = NULL; 03250 MFace *mface; 03251 VlakRen *vlr; //, *vlr1; 03252 VertRen *ver; 03253 Material *ma; 03254 MSticky *ms = NULL; 03255 DerivedMesh *dm; 03256 CustomDataMask mask; 03257 float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3], 03258 float *orco=0; 03259 int need_orco=0, need_stress=0, need_nmap_tangent=0, need_tangent=0; 03260 int a, a1, ok, vertofs; 03261 int end, do_autosmooth=0, totvert = 0; 03262 int use_original_normals= 0; 03263 int recalc_normals = 0; // false by default 03264 int negative_scale; 03265 03266 me= ob->data; 03267 03268 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 03269 invert_m4_m4(ob->imat, mat); 03270 copy_m3_m4(imat, ob->imat); 03271 negative_scale= is_negative_m4(mat); 03272 03273 if(me->totvert==0) 03274 return; 03275 03276 need_orco= 0; 03277 for(a=1; a<=ob->totcol; a++) { 03278 ma= give_render_material(re, ob, a); 03279 if(ma) { 03280 if(ma->texco & (TEXCO_ORCO|TEXCO_STRESS)) 03281 need_orco= 1; 03282 if(ma->texco & TEXCO_STRESS) 03283 need_stress= 1; 03284 /* normalmaps, test if tangents needed, separated from shading */ 03285 if(ma->mode_l & MA_TANGENT_V) { 03286 need_tangent= 1; 03287 if(me->mtface==NULL) 03288 need_orco= 1; 03289 } 03290 if(ma->mode_l & MA_NORMAP_TANG) { 03291 if(me->mtface==NULL) { 03292 need_orco= 1; 03293 need_tangent= 1; 03294 } 03295 need_nmap_tangent= 1; 03296 } 03297 } 03298 } 03299 03300 if(re->flag & R_NEED_TANGENT) { 03301 /* exception for tangent space baking */ 03302 if(me->mtface==NULL) { 03303 need_orco= 1; 03304 need_tangent= 1; 03305 } 03306 need_nmap_tangent= 1; 03307 } 03308 03309 /* check autosmooth and displacement, we then have to skip only-verts optimize */ 03310 do_autosmooth |= (me->flag & ME_AUTOSMOOTH); 03311 if(do_autosmooth) 03312 timeoffset= 0; 03313 if(test_for_displace(re, ob ) ) 03314 timeoffset= 0; 03315 03316 mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; 03317 if(!timeoffset) 03318 if(need_orco) 03319 mask |= CD_MASK_ORCO; 03320 03321 dm= mesh_create_derived_render(re->scene, ob, mask); 03322 if(dm==NULL) return; /* in case duplicated object fails? */ 03323 03324 if(mask & CD_MASK_ORCO) { 03325 orco= dm->getVertDataArray(dm, CD_ORCO); 03326 if(orco) { 03327 orco= MEM_dupallocN(orco); 03328 set_object_orco(re, ob, orco); 03329 } 03330 } 03331 03332 mvert= dm->getVertArray(dm); 03333 totvert= dm->getNumVerts(dm); 03334 03335 /* attempt to autsmooth on original mesh, only without subsurf */ 03336 if(do_autosmooth && me->totvert==totvert && me->totface==dm->getNumFaces(dm)) 03337 use_original_normals= 1; 03338 03339 ms = (totvert==me->totvert)?me->msticky:NULL; 03340 03341 ma= give_render_material(re, ob, 1); 03342 03343 03344 if(ma->material_type == MA_TYPE_HALO) { 03345 make_render_halos(re, obr, me, totvert, mvert, ma, orco); 03346 } 03347 else { 03348 03349 for(a=0; a<totvert; a++, mvert++) { 03350 ver= RE_findOrAddVert(obr, obr->totvert++); 03351 copy_v3_v3(ver->co, mvert->co); 03352 if(do_autosmooth==0) { /* autosmooth on original unrotated data to prevent differences between frames */ 03353 normal_short_to_float_v3(ver->n, mvert->no); 03354 mul_m4_v3(mat, ver->co); 03355 mul_transposed_m3_v3(imat, ver->n); 03356 normalize_v3(ver->n); 03357 negate_v3(ver->n); 03358 } 03359 03360 if(orco) { 03361 ver->orco= orco; 03362 orco+=3; 03363 } 03364 if(ms) { 03365 float *sticky= RE_vertren_get_sticky(obr, ver, 1); 03366 sticky[0]= ms->co[0]; 03367 sticky[1]= ms->co[1]; 03368 ms++; 03369 } 03370 } 03371 03372 if(!timeoffset) { 03373 /* store customdata names, because DerivedMesh is freed */ 03374 RE_set_customdata_names(obr, &dm->faceData); 03375 03376 /* add tangent layer if we need one */ 03377 if(need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) 03378 DM_add_tangent_layer(dm); 03379 03380 /* still to do for keys: the correct local texture coordinate */ 03381 03382 /* faces in order of color blocks */ 03383 vertofs= obr->totvert - totvert; 03384 for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) { 03385 03386 ma= give_render_material(re, ob, a1+1); 03387 03388 /* test for 100% transparant */ 03389 ok= 1; 03390 if(ma->alpha==0.0f && ma->spectra==0.0f && ma->filter==0.0f && (ma->mode & MA_TRANSP) && (ma->mode & MA_RAYMIRROR)==0) { 03391 ok= 0; 03392 /* texture on transparency? */ 03393 for(a=0; a<MAX_MTEX; a++) { 03394 if(ma->mtex[a] && ma->mtex[a]->tex) { 03395 if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1; 03396 } 03397 } 03398 } 03399 03400 /* if wire material, and we got edges, don't do the faces */ 03401 if(ma->material_type == MA_TYPE_WIRE) { 03402 end= dm->getNumEdges(dm); 03403 if(end) ok= 0; 03404 } 03405 03406 if(ok) { 03407 end= dm->getNumFaces(dm); 03408 mface= dm->getFaceArray(dm); 03409 03410 for(a=0; a<end; a++, mface++) { 03411 int v1, v2, v3, v4, flag; 03412 03413 if( mface->mat_nr==a1 ) { 03414 float len; 03415 int reverse_verts = negative_scale!=0 && do_autosmooth==0; 03416 int rev_tab[] = {reverse_verts==0 ? 0 : 2, 1, reverse_verts==0 ? 2 : 0, 3}; 03417 v1= reverse_verts==0 ? mface->v1 : mface->v3; 03418 v2= mface->v2; 03419 v3= reverse_verts==0 ? mface->v3 : mface->v1; 03420 v4= mface->v4; 03421 flag= mface->flag & ME_SMOOTH; 03422 03423 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 03424 vlr->v1= RE_findOrAddVert(obr, vertofs+v1); 03425 vlr->v2= RE_findOrAddVert(obr, vertofs+v2); 03426 vlr->v3= RE_findOrAddVert(obr, vertofs+v3); 03427 if(v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4); 03428 else vlr->v4= 0; 03429 03430 /* render normals are inverted in render */ 03431 if(use_original_normals) { 03432 MFace *mf= me->mface+a; 03433 MVert *mv= me->mvert; 03434 03435 if(vlr->v4) 03436 len= normal_quad_v3( vlr->n, mv[mf->v4].co, mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co); 03437 else 03438 len= normal_tri_v3( vlr->n,mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co); 03439 } 03440 else { 03441 if(vlr->v4) 03442 len= normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); 03443 else 03444 len= normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); 03445 } 03446 03447 vlr->mat= ma; 03448 vlr->flag= flag; 03449 vlr->ec= 0; /* mesh edges rendered separately */ 03450 03451 if(len==0) obr->totvlak--; 03452 else { 03453 CustomDataLayer *layer; 03454 MTFace *mtface, *mtf; 03455 MCol *mcol, *mc; 03456 int index, mtfn= 0, mcn= 0, mtng=0, vindex; 03457 char *name; 03458 int nr_verts = v4!=0 ? 4 : 3; 03459 03460 for(index=0; index<dm->faceData.totlayer; index++) { 03461 layer= &dm->faceData.layers[index]; 03462 name= layer->name; 03463 03464 if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { 03465 int t; 03466 mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); 03467 mtface= (MTFace*)layer->data; 03468 *mtf= mtface[a]; // copy face info 03469 for(vindex=0; vindex<nr_verts; vindex++) 03470 for(t=0; t<2; t++) 03471 mtf->uv[vindex][t]=mtface[a].uv[rev_tab[vindex]][t]; 03472 } 03473 else if(layer->type == CD_MCOL && mcn < MAX_MCOL) { 03474 mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); 03475 mcol= (MCol*)layer->data; 03476 for(vindex=0; vindex<nr_verts; vindex++) 03477 mc[vindex]=mcol[a*4+rev_tab[vindex]]; 03478 } 03479 else if(layer->type == CD_TANGENT && mtng < 1) 03480 { 03481 if(need_nmap_tangent!=0) 03482 { 03483 const float * tangent = (const float *) layer->data; 03484 float * ftang = RE_vlakren_get_nmap_tangent(obr, vlr, 1); 03485 for(vindex=0; vindex<nr_verts; vindex++) 03486 { 03487 copy_v4_v4(ftang+vindex*4, tangent+a*16+rev_tab[vindex]*4); 03488 mul_mat3_m4_v3(mat, ftang+vindex*4); 03489 normalize_v3(ftang+vindex*4); 03490 } 03491 } 03492 } 03493 } 03494 } 03495 } 03496 } 03497 } 03498 } 03499 03500 /* exception... we do edges for wire mode. potential conflict when faces exist... */ 03501 end= dm->getNumEdges(dm); 03502 mvert= dm->getVertArray(dm); 03503 ma= give_render_material(re, ob, 1); 03504 if(end && (ma->material_type == MA_TYPE_WIRE)) { 03505 MEdge *medge; 03506 struct edgesort *edgetable; 03507 int totedge= 0; 03508 recalc_normals= 1; 03509 03510 medge= dm->getEdgeArray(dm); 03511 03512 /* we want edges to have UV and vcol too... */ 03513 edgetable= make_mesh_edge_lookup(dm, &totedge); 03514 03515 for(a1=0; a1<end; a1++, medge++) { 03516 if (medge->flag&ME_EDGERENDER) { 03517 MVert *v0 = &mvert[medge->v1]; 03518 MVert *v1 = &mvert[medge->v2]; 03519 03520 vlr= RE_findOrAddVlak(obr, obr->totvlak++); 03521 vlr->v1= RE_findOrAddVert(obr, vertofs+medge->v1); 03522 vlr->v2= RE_findOrAddVert(obr, vertofs+medge->v2); 03523 vlr->v3= vlr->v2; 03524 vlr->v4= NULL; 03525 03526 if(edgetable) 03527 use_mesh_edge_lookup(obr, dm, medge, vlr, edgetable, totedge); 03528 03529 xn= -(v0->no[0]+v1->no[0]); 03530 yn= -(v0->no[1]+v1->no[1]); 03531 zn= -(v0->no[2]+v1->no[2]); 03532 /* transpose ! */ 03533 vlr->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; 03534 vlr->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; 03535 vlr->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; 03536 normalize_v3(vlr->n); 03537 03538 vlr->mat= ma; 03539 vlr->flag= 0; 03540 vlr->ec= ME_V1V2; 03541 } 03542 } 03543 if(edgetable) 03544 MEM_freeN(edgetable); 03545 } 03546 } 03547 } 03548 03549 if(!timeoffset) { 03550 if(need_stress) 03551 calc_edge_stress(re, obr, me); 03552 03553 if (test_for_displace(re, ob ) ) { 03554 recalc_normals= 1; 03555 calc_vertexnormals(re, obr, 0, 0); 03556 if(do_autosmooth) 03557 do_displacement(re, obr, mat, imat); 03558 else 03559 do_displacement(re, obr, NULL, NULL); 03560 } 03561 03562 if(do_autosmooth) { 03563 recalc_normals= 1; 03564 autosmooth(re, obr, mat, me->smoothresh); 03565 } 03566 03567 if(recalc_normals!=0 || need_tangent!=0) 03568 calc_vertexnormals(re, obr, need_tangent, need_nmap_tangent); 03569 } 03570 03571 dm->release(dm); 03572 } 03573 03574 /* ------------------------------------------------------------------------- */ 03575 /* Lamps and Shadowbuffers */ 03576 /* ------------------------------------------------------------------------- */ 03577 03578 static void initshadowbuf(Render *re, LampRen *lar, float mat[][4]) 03579 { 03580 struct ShadBuf *shb; 03581 float viewinv[4][4]; 03582 03583 /* if(la->spsi<16) return; */ 03584 03585 /* memory alloc */ 03586 shb= (struct ShadBuf *)MEM_callocN( sizeof(struct ShadBuf),"initshadbuf"); 03587 lar->shb= shb; 03588 03589 if(shb==NULL) return; 03590 03591 VECCOPY(shb->co, lar->co); /* int copy */ 03592 03593 /* percentage render: keep track of min and max */ 03594 shb->size= (lar->bufsize*re->r.size)/100; 03595 03596 if(shb->size<512) shb->size= 512; 03597 else if(shb->size > lar->bufsize) shb->size= lar->bufsize; 03598 03599 shb->size &= ~15; /* make sure its multiples of 16 */ 03600 03601 shb->samp= lar->samp; 03602 shb->soft= lar->soft; 03603 shb->shadhalostep= lar->shadhalostep; 03604 03605 normalize_m4(mat); 03606 invert_m4_m4(shb->winmat, mat); /* winmat is temp */ 03607 03608 /* matrix: combination of inverse view and lampmat */ 03609 /* calculate again: the ortho-render has no correct viewinv */ 03610 invert_m4_m4(viewinv, re->viewmat); 03611 mult_m4_m4m4(shb->viewmat, shb->winmat, viewinv); 03612 03613 /* projection */ 03614 shb->d= lar->clipsta; 03615 shb->clipend= lar->clipend; 03616 03617 /* bias is percentage, made 2x larger because of correction for angle of incidence */ 03618 /* when a ray is closer to parallel of a face, bias value is increased during render */ 03619 shb->bias= (0.02f*lar->bias)*0x7FFFFFFF; 03620 03621 /* halfway method (average of first and 2nd z) reduces bias issues */ 03622 if(ELEM(lar->buftype, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) 03623 shb->bias= 0.1f*shb->bias; 03624 03625 shb->compressthresh= lar->compressthresh; 03626 } 03627 03628 static void area_lamp_vectors(LampRen *lar) 03629 { 03630 float xsize= 0.5f*lar->area_size, ysize= 0.5f*lar->area_sizey, multifac; 03631 03632 /* make it smaller, so area light can be multisampled */ 03633 multifac= 1.0f/sqrtf((float)lar->ray_totsamp); 03634 xsize *= multifac; 03635 ysize *= multifac; 03636 03637 /* corner vectors */ 03638 lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; 03639 lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; 03640 lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; 03641 03642 /* corner vectors */ 03643 lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; 03644 lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; 03645 lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; 03646 03647 /* corner vectors */ 03648 lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; 03649 lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; 03650 lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; 03651 03652 /* corner vectors */ 03653 lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; 03654 lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; 03655 lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; 03656 /* only for correction button size, matrix size works on energy */ 03657 lar->areasize= lar->dist*lar->dist/(4.0f*xsize*ysize); 03658 } 03659 03660 /* If lar takes more lamp data, the decoupling will be better. */ 03661 static GroupObject *add_render_lamp(Render *re, Object *ob) 03662 { 03663 Lamp *la= ob->data; 03664 LampRen *lar; 03665 GroupObject *go; 03666 float mat[4][4], angle, xn, yn; 03667 float vec[3]; 03668 int c; 03669 03670 /* previewrender sets this to zero... prevent accidents */ 03671 if(la==NULL) return NULL; 03672 03673 /* prevent only shadow from rendering light */ 03674 if(la->mode & LA_ONLYSHADOW) 03675 if((re->r.mode & R_SHADOW)==0) 03676 return NULL; 03677 03678 re->totlamp++; 03679 03680 /* groups is used to unify support for lightgroups, this is the global lightgroup */ 03681 go= MEM_callocN(sizeof(GroupObject), "groupobject"); 03682 BLI_addtail(&re->lights, go); 03683 go->ob= ob; 03684 /* lamprens are in own list, for freeing */ 03685 lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren"); 03686 BLI_addtail(&re->lampren, lar); 03687 go->lampren= lar; 03688 03689 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 03690 invert_m4_m4(ob->imat, mat); 03691 03692 copy_m3_m4(lar->mat, mat); 03693 copy_m3_m4(lar->imat, ob->imat); 03694 03695 lar->bufsize = la->bufsize; 03696 lar->samp = la->samp; 03697 lar->buffers= la->buffers; 03698 if(lar->buffers==0) lar->buffers= 1; 03699 lar->buftype= la->buftype; 03700 lar->filtertype= la->filtertype; 03701 lar->soft = la->soft; 03702 lar->shadhalostep = la->shadhalostep; 03703 lar->clipsta = la->clipsta; 03704 lar->clipend = la->clipend; 03705 03706 lar->bias = la->bias; 03707 lar->compressthresh = la->compressthresh; 03708 03709 lar->type= la->type; 03710 lar->mode= la->mode; 03711 03712 lar->energy= la->energy; 03713 if(la->mode & LA_NEG) lar->energy= -lar->energy; 03714 03715 lar->vec[0]= -mat[2][0]; 03716 lar->vec[1]= -mat[2][1]; 03717 lar->vec[2]= -mat[2][2]; 03718 normalize_v3(lar->vec); 03719 lar->co[0]= mat[3][0]; 03720 lar->co[1]= mat[3][1]; 03721 lar->co[2]= mat[3][2]; 03722 lar->dist= la->dist; 03723 lar->haint= la->haint; 03724 lar->distkw= lar->dist*lar->dist; 03725 lar->r= lar->energy*la->r; 03726 lar->g= lar->energy*la->g; 03727 lar->b= lar->energy*la->b; 03728 lar->shdwr= la->shdwr; 03729 lar->shdwg= la->shdwg; 03730 lar->shdwb= la->shdwb; 03731 lar->k= la->k; 03732 03733 // area 03734 lar->ray_samp= la->ray_samp; 03735 lar->ray_sampy= la->ray_sampy; 03736 lar->ray_sampz= la->ray_sampz; 03737 03738 lar->area_size= la->area_size; 03739 lar->area_sizey= la->area_sizey; 03740 lar->area_sizez= la->area_sizez; 03741 03742 lar->area_shape= la->area_shape; 03743 03744 /* Annoying, lamp UI does this, but the UI might not have been used? - add here too. 03745 * make sure this matches buttons_shading.c's logic */ 03746 if(ELEM4(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && (la->mode & LA_SHAD_RAY)) 03747 if (ELEM3(la->type, LA_SPOT, LA_SUN, LA_LOCAL)) 03748 if (la->ray_samp_method == LA_SAMP_CONSTANT) la->ray_samp_method = LA_SAMP_HALTON; 03749 03750 lar->ray_samp_method= la->ray_samp_method; 03751 lar->ray_samp_type= la->ray_samp_type; 03752 03753 lar->adapt_thresh= la->adapt_thresh; 03754 lar->sunsky = NULL; 03755 03756 if( ELEM(lar->type, LA_SPOT, LA_LOCAL)) { 03757 lar->ray_totsamp= lar->ray_samp*lar->ray_samp; 03758 lar->area_shape = LA_AREA_SQUARE; 03759 lar->area_sizey= lar->area_size; 03760 } 03761 else if(lar->type==LA_AREA) { 03762 switch(lar->area_shape) { 03763 case LA_AREA_SQUARE: 03764 lar->ray_totsamp= lar->ray_samp*lar->ray_samp; 03765 lar->ray_sampy= lar->ray_samp; 03766 lar->area_sizey= lar->area_size; 03767 break; 03768 case LA_AREA_RECT: 03769 lar->ray_totsamp= lar->ray_samp*lar->ray_sampy; 03770 break; 03771 case LA_AREA_CUBE: 03772 lar->ray_totsamp= lar->ray_samp*lar->ray_samp*lar->ray_samp; 03773 lar->ray_sampy= lar->ray_samp; 03774 lar->ray_sampz= lar->ray_samp; 03775 lar->area_sizey= lar->area_size; 03776 lar->area_sizez= lar->area_size; 03777 break; 03778 case LA_AREA_BOX: 03779 lar->ray_totsamp= lar->ray_samp*lar->ray_sampy*lar->ray_sampz; 03780 break; 03781 } 03782 03783 area_lamp_vectors(lar); 03784 init_jitter_plane(lar); // subsamples 03785 } 03786 else if(lar->type==LA_SUN){ 03787 lar->ray_totsamp= lar->ray_samp*lar->ray_samp; 03788 lar->area_shape = LA_AREA_SQUARE; 03789 lar->area_sizey= lar->area_size; 03790 03791 if((la->sun_effect_type & LA_SUN_EFFECT_SKY) || 03792 (la->sun_effect_type & LA_SUN_EFFECT_AP)){ 03793 lar->sunsky = (struct SunSky*)MEM_callocN(sizeof(struct SunSky), "sunskyren"); 03794 lar->sunsky->effect_type = la->sun_effect_type; 03795 03796 copy_v3_v3(vec,ob->obmat[2]); 03797 normalize_v3(vec); 03798 03799 InitSunSky(lar->sunsky, la->atm_turbidity, vec, la->horizon_brightness, 03800 la->spread, la->sun_brightness, la->sun_size, la->backscattered_light, 03801 la->skyblendfac, la->skyblendtype, la->sky_exposure, la->sky_colorspace); 03802 03803 InitAtmosphere(lar->sunsky, la->sun_intensity, 1.0, 1.0, la->atm_inscattering_factor, la->atm_extinction_factor, 03804 la->atm_distance_factor); 03805 } 03806 } 03807 else lar->ray_totsamp= 0; 03808 03809 lar->spotsi= la->spotsize; 03810 if(lar->mode & LA_HALO) { 03811 if(lar->spotsi>170.0f) lar->spotsi= 170.0f; 03812 } 03813 lar->spotsi= cosf( (float)M_PI*lar->spotsi/360.0f ); 03814 lar->spotbl= (1.0f-lar->spotsi)*la->spotblend; 03815 03816 memcpy(lar->mtex, la->mtex, MAX_MTEX*sizeof(void *)); 03817 03818 lar->lay= ob->lay & 0xFFFFFF; // higher 8 bits are localview layers 03819 03820 lar->falloff_type = la->falloff_type; 03821 lar->ld1= la->att1; 03822 lar->ld2= la->att2; 03823 lar->curfalloff = curvemapping_copy(la->curfalloff); 03824 03825 if(lar->type==LA_SPOT) { 03826 03827 normalize_v3(lar->imat[0]); 03828 normalize_v3(lar->imat[1]); 03829 normalize_v3(lar->imat[2]); 03830 03831 xn= saacos(lar->spotsi); 03832 xn= sin(xn)/cos(xn); 03833 lar->spottexfac= 1.0f/(xn); 03834 03835 if(lar->mode & LA_ONLYSHADOW) { 03836 if((lar->mode & (LA_SHAD_BUF|LA_SHAD_RAY))==0) lar->mode -= LA_ONLYSHADOW; 03837 } 03838 03839 } 03840 03841 /* set flag for spothalo en initvars */ 03842 if(la->type==LA_SPOT && (la->mode & LA_HALO) && (la->buftype != LA_SHADBUF_DEEP)) { 03843 if(la->haint>0.0f) { 03844 re->flag |= R_LAMPHALO; 03845 03846 /* camera position (0,0,0) rotate around lamp */ 03847 lar->sh_invcampos[0]= -lar->co[0]; 03848 lar->sh_invcampos[1]= -lar->co[1]; 03849 lar->sh_invcampos[2]= -lar->co[2]; 03850 mul_m3_v3(lar->imat, lar->sh_invcampos); 03851 03852 /* z factor, for a normalized volume */ 03853 angle= saacos(lar->spotsi); 03854 xn= lar->spotsi; 03855 yn= sin(angle); 03856 lar->sh_zfac= yn/xn; 03857 /* pre-scale */ 03858 lar->sh_invcampos[2]*= lar->sh_zfac; 03859 03860 /* halfway shadow buffer doesn't work for volumetric effects */ 03861 if(lar->buftype == LA_SHADBUF_HALFWAY) 03862 lar->buftype = LA_SHADBUF_REGULAR; 03863 03864 } 03865 } 03866 else if(la->type==LA_HEMI) { 03867 lar->mode &= ~(LA_SHAD_RAY|LA_SHAD_BUF); 03868 } 03869 03870 for(c=0; c<MAX_MTEX; c++) { 03871 if(la->mtex[c] && la->mtex[c]->tex) { 03872 if (la->mtex[c]->mapto & LAMAP_COL) 03873 lar->mode |= LA_TEXTURE; 03874 if (la->mtex[c]->mapto & LAMAP_SHAD) 03875 lar->mode |= LA_SHAD_TEX; 03876 03877 if(G.rendering) { 03878 if(re->osa) { 03879 if(la->mtex[c]->tex->type==TEX_IMAGE) lar->mode |= LA_OSATEX; 03880 } 03881 } 03882 } 03883 } 03884 03885 /* old code checked for internal render (aka not yafray) */ 03886 { 03887 /* to make sure we can check ray shadow easily in the render code */ 03888 if(lar->mode & LA_SHAD_RAY) { 03889 if( (re->r.mode & R_RAYTRACE)==0) 03890 lar->mode &= ~LA_SHAD_RAY; 03891 } 03892 03893 03894 if(re->r.mode & R_SHADOW) { 03895 03896 if(la->type==LA_AREA && (lar->mode & LA_SHAD_RAY) && (lar->ray_samp_method == LA_SAMP_CONSTANT)) { 03897 init_jitter_plane(lar); 03898 } 03899 else if (la->type==LA_SPOT && (lar->mode & LA_SHAD_BUF) ) { 03900 /* Per lamp, one shadow buffer is made. */ 03901 lar->bufflag= la->bufflag; 03902 copy_m4_m4(mat, ob->obmat); 03903 initshadowbuf(re, lar, mat); // mat is altered 03904 } 03905 03906 03907 /* this is the way used all over to check for shadow */ 03908 if(lar->shb || (lar->mode & LA_SHAD_RAY)) { 03909 LampShadowSample *ls; 03910 LampShadowSubSample *lss; 03911 int a, b; 03912 03913 memset(re->shadowsamplenr, 0, sizeof(re->shadowsamplenr)); 03914 03915 lar->shadsamp= MEM_mallocN(re->r.threads*sizeof(LampShadowSample), "lamp shadow sample"); 03916 ls= lar->shadsamp; 03917 03918 /* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */ 03919 for(a=0; a<re->r.threads; a++, ls++) { 03920 lss= ls->s; 03921 for(b=0; b<re->r.osa; b++, lss++) { 03922 lss->samplenr= -1; /* used to detect whether we store or read */ 03923 lss->shadfac[0]= 1.0f; 03924 lss->shadfac[1]= 1.0f; 03925 lss->shadfac[2]= 1.0f; 03926 lss->shadfac[3]= 1.0f; 03927 } 03928 } 03929 } 03930 } 03931 } 03932 03933 return go; 03934 } 03935 03936 /* layflag: allows material group to ignore layerflag */ 03937 static void add_lightgroup(Render *re, Group *group, int exclusive) 03938 { 03939 GroupObject *go, *gol; 03940 03941 group->id.flag &= ~LIB_DOIT; 03942 03943 /* it's a bit too many loops in loops... but will survive */ 03944 /* note that 'exclusive' will remove it from the global list */ 03945 for(go= group->gobject.first; go; go= go->next) { 03946 go->lampren= NULL; 03947 03948 if(go->ob->lay & re->lay) { 03949 if(go->ob && go->ob->type==OB_LAMP) { 03950 for(gol= re->lights.first; gol; gol= gol->next) { 03951 if(gol->ob==go->ob) { 03952 go->lampren= gol->lampren; 03953 break; 03954 } 03955 } 03956 if(go->lampren==NULL) 03957 gol= add_render_lamp(re, go->ob); 03958 if(gol && exclusive) { 03959 BLI_remlink(&re->lights, gol); 03960 MEM_freeN(gol); 03961 } 03962 } 03963 } 03964 } 03965 } 03966 03967 static void set_material_lightgroups(Render *re) 03968 { 03969 Group *group; 03970 Material *ma; 03971 03972 /* not for preview render */ 03973 if(re->scene->r.scemode & R_PREVIEWBUTS) 03974 return; 03975 03976 for(group= re->main->group.first; group; group=group->id.next) 03977 group->id.flag |= LIB_DOIT; 03978 03979 /* it's a bit too many loops in loops... but will survive */ 03980 /* hola! materials not in use...? */ 03981 for(ma= re->main->mat.first; ma; ma=ma->id.next) { 03982 if(ma->group && (ma->group->id.flag & LIB_DOIT)) 03983 add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY); 03984 } 03985 } 03986 03987 static void set_renderlayer_lightgroups(Render *re, Scene *sce) 03988 { 03989 SceneRenderLayer *srl; 03990 03991 for(srl= sce->r.layers.first; srl; srl= srl->next) { 03992 if(srl->light_override) 03993 add_lightgroup(re, srl->light_override, 0); 03994 } 03995 } 03996 03997 /* ------------------------------------------------------------------------- */ 03998 /* World */ 03999 /* ------------------------------------------------------------------------- */ 04000 04001 void init_render_world(Render *re) 04002 { 04003 int a; 04004 char *cp; 04005 04006 if(re->scene && re->scene->world) { 04007 re->wrld= *(re->scene->world); 04008 04009 cp= (char *)&re->wrld.fastcol; 04010 04011 cp[0]= 255.0f*re->wrld.horr; 04012 cp[1]= 255.0f*re->wrld.horg; 04013 cp[2]= 255.0f*re->wrld.horb; 04014 cp[3]= 1; 04015 04016 copy_v3_v3(re->grvec, re->viewmat[2]); 04017 normalize_v3(re->grvec); 04018 copy_m3_m4(re->imat, re->viewinv); 04019 04020 for(a=0; a<MAX_MTEX; a++) 04021 if(re->wrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX; 04022 04023 /* AO samples should be OSA minimum */ 04024 if(re->osa) 04025 while(re->wrld.aosamp*re->wrld.aosamp < re->osa) 04026 re->wrld.aosamp++; 04027 if(!(re->r.mode & R_RAYTRACE) && (re->wrld.ao_gather_method == WO_AOGATHER_RAYTRACE)) 04028 re->wrld.mode &= ~(WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT); 04029 } 04030 else { 04031 memset(&re->wrld, 0, sizeof(World)); 04032 re->wrld.exp= 0.0f; 04033 re->wrld.range= 1.0f; 04034 04035 /* for mist pass */ 04036 re->wrld.miststa= re->clipsta; 04037 re->wrld.mistdist= re->clipend-re->clipsta; 04038 re->wrld.misi= 1.0f; 04039 } 04040 04041 re->wrld.linfac= 1.0f + powf((2.0f*re->wrld.exp + 0.5f), -10); 04042 re->wrld.logfac= logf((re->wrld.linfac-1.0f)/re->wrld.linfac) / re->wrld.range; 04043 } 04044 04045 04046 04047 /* ------------------------------------------------------------------------- */ 04048 /* Object Finalization */ 04049 /* ------------------------------------------------------------------------- */ 04050 04051 /* prevent phong interpolation for giving ray shadow errors (terminator problem) */ 04052 static void set_phong_threshold(ObjectRen *obr) 04053 { 04054 // VertRen *ver; 04055 VlakRen *vlr; 04056 float thresh= 0.0, dot; 04057 int tot=0, i; 04058 04059 /* Added check for 'pointy' situations, only dotproducts of 0.9 and larger 04060 are taken into account. This threshold is meant to work on smooth geometry, not 04061 for extreme cases (ton) */ 04062 04063 for(i=0; i<obr->totvlak; i++) { 04064 vlr= RE_findOrAddVlak(obr, i); 04065 if(vlr->flag & R_SMOOTH) { 04066 dot= dot_v3v3(vlr->n, vlr->v1->n); 04067 dot= ABS(dot); 04068 if(dot>0.9f) { 04069 thresh+= dot; tot++; 04070 } 04071 dot= dot_v3v3(vlr->n, vlr->v2->n); 04072 dot= ABS(dot); 04073 if(dot>0.9f) { 04074 thresh+= dot; tot++; 04075 } 04076 04077 dot= dot_v3v3(vlr->n, vlr->v3->n); 04078 dot= ABS(dot); 04079 if(dot>0.9f) { 04080 thresh+= dot; tot++; 04081 } 04082 04083 if(vlr->v4) { 04084 dot= dot_v3v3(vlr->n, vlr->v4->n); 04085 dot= ABS(dot); 04086 if(dot>0.9f) { 04087 thresh+= dot; tot++; 04088 } 04089 } 04090 } 04091 } 04092 04093 if(tot) { 04094 thresh/= (float)tot; 04095 obr->ob->smoothresh= cosf(0.5f*(float)M_PI-saacos(thresh)); 04096 } 04097 } 04098 04099 /* per face check if all samples should be taken. 04100 if raytrace or multisample, do always for raytraced material, or when material full_osa set */ 04101 static void set_fullsample_trace_flag(Render *re, ObjectRen *obr) 04102 { 04103 VlakRen *vlr; 04104 int a, trace, mode, osa; 04105 04106 osa= re->osa; 04107 trace= re->r.mode & R_RAYTRACE; 04108 04109 for(a=obr->totvlak-1; a>=0; a--) { 04110 vlr= RE_findOrAddVlak(obr, a); 04111 mode= vlr->mat->mode; 04112 04113 if(trace && (mode & MA_TRACEBLE)) 04114 vlr->flag |= R_TRACEBLE; 04115 04116 if(osa) { 04117 if(mode & MA_FULL_OSA) { 04118 vlr->flag |= R_FULL_OSA; 04119 } 04120 else if(trace) { 04121 if(mode & MA_SHLESS); 04122 else if(vlr->mat->material_type == MA_TYPE_VOLUME); 04123 else if((mode & MA_RAYMIRROR) || ((mode & MA_TRANSP) && (mode & MA_RAYTRANSP))) { 04124 /* for blurry reflect/refract, better to take more samples 04125 * inside the raytrace than as OSA samples */ 04126 if ((vlr->mat->gloss_mir == 1.0f) && (vlr->mat->gloss_tra == 1.0f)) 04127 vlr->flag |= R_FULL_OSA; 04128 } 04129 } 04130 } 04131 } 04132 } 04133 04134 /* split quads for predictable baking 04135 * dir 1 == (0,1,2) (0,2,3), 2 == (1,3,0) (1,2,3) 04136 */ 04137 static void split_quads(ObjectRen *obr, int dir) 04138 { 04139 VlakRen *vlr, *vlr1; 04140 int a; 04141 04142 for(a=obr->totvlak-1; a>=0; a--) { 04143 vlr= RE_findOrAddVlak(obr, a); 04144 04145 /* test if rendering as a quad or triangle, skip wire */ 04146 if(vlr->v4 && (vlr->flag & R_STRAND)==0 && (vlr->mat->material_type != MA_TYPE_WIRE)) { 04147 04148 if(vlr->v4) { 04149 04150 vlr1= RE_vlakren_copy(obr, vlr); 04151 vlr1->flag |= R_FACE_SPLIT; 04152 04153 if( dir==2 ) vlr->flag |= R_DIVIDE_24; 04154 else vlr->flag &= ~R_DIVIDE_24; 04155 04156 /* new vertex pointers */ 04157 if (vlr->flag & R_DIVIDE_24) { 04158 vlr1->v1= vlr->v2; 04159 vlr1->v2= vlr->v3; 04160 vlr1->v3= vlr->v4; 04161 04162 vlr->v3 = vlr->v4; 04163 04164 vlr1->flag |= R_DIVIDE_24; 04165 } 04166 else { 04167 vlr1->v1= vlr->v1; 04168 vlr1->v2= vlr->v3; 04169 vlr1->v3= vlr->v4; 04170 04171 vlr1->flag &= ~R_DIVIDE_24; 04172 } 04173 vlr->v4 = vlr1->v4 = NULL; 04174 04175 /* new normals */ 04176 normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); 04177 normal_tri_v3( vlr1->n,vlr1->v3->co, vlr1->v2->co, vlr1->v1->co); 04178 } 04179 /* clear the flag when not divided */ 04180 else vlr->flag &= ~R_DIVIDE_24; 04181 } 04182 } 04183 } 04184 04185 static void check_non_flat_quads(ObjectRen *obr) 04186 { 04187 VlakRen *vlr, *vlr1; 04188 VertRen *v1, *v2, *v3, *v4; 04189 float nor[3], xn, flen; 04190 int a; 04191 04192 for(a=obr->totvlak-1; a>=0; a--) { 04193 vlr= RE_findOrAddVlak(obr, a); 04194 04195 /* test if rendering as a quad or triangle, skip wire */ 04196 if(vlr->v4 && (vlr->flag & R_STRAND)==0 && (vlr->mat->material_type != MA_TYPE_WIRE)) { 04197 04198 /* check if quad is actually triangle */ 04199 v1= vlr->v1; 04200 v2= vlr->v2; 04201 v3= vlr->v3; 04202 v4= vlr->v4; 04203 sub_v3_v3v3(nor, v1->co, v2->co); 04204 if( ABS(nor[0])<FLT_EPSILON10 && ABS(nor[1])<FLT_EPSILON10 && ABS(nor[2])<FLT_EPSILON10 ) { 04205 vlr->v1= v2; 04206 vlr->v2= v3; 04207 vlr->v3= v4; 04208 vlr->v4= NULL; 04209 } 04210 else { 04211 sub_v3_v3v3(nor, v2->co, v3->co); 04212 if( ABS(nor[0])<FLT_EPSILON10 && ABS(nor[1])<FLT_EPSILON10 && ABS(nor[2])<FLT_EPSILON10 ) { 04213 vlr->v2= v3; 04214 vlr->v3= v4; 04215 vlr->v4= NULL; 04216 } 04217 else { 04218 sub_v3_v3v3(nor, v3->co, v4->co); 04219 if( ABS(nor[0])<FLT_EPSILON10 && ABS(nor[1])<FLT_EPSILON10 && ABS(nor[2])<FLT_EPSILON10 ) { 04220 vlr->v4= NULL; 04221 } 04222 else { 04223 sub_v3_v3v3(nor, v4->co, v1->co); 04224 if( ABS(nor[0])<FLT_EPSILON10 && ABS(nor[1])<FLT_EPSILON10 && ABS(nor[2])<FLT_EPSILON10 ) { 04225 vlr->v4= NULL; 04226 } 04227 } 04228 } 04229 } 04230 04231 if(vlr->v4) { 04232 04233 /* Face is divided along edge with the least gradient */ 04234 /* Flagged with R_DIVIDE_24 if divide is from vert 2 to 4 */ 04235 /* 4---3 4---3 */ 04236 /* |\ 1| or |1 /| */ 04237 /* |0\ | |/ 0| */ 04238 /* 1---2 1---2 0 = orig face, 1 = new face */ 04239 04240 /* render normals are inverted in render! we calculate normal of single tria here */ 04241 flen= normal_tri_v3( nor,vlr->v4->co, vlr->v3->co, vlr->v1->co); 04242 if(flen==0.0f) normal_tri_v3( nor,vlr->v4->co, vlr->v2->co, vlr->v1->co); 04243 04244 xn= nor[0]*vlr->n[0] + nor[1]*vlr->n[1] + nor[2]*vlr->n[2]; 04245 04246 if(ABS(xn) < 0.999995f ) { // checked on noisy fractal grid 04247 04248 float d1, d2; 04249 04250 vlr1= RE_vlakren_copy(obr, vlr); 04251 vlr1->flag |= R_FACE_SPLIT; 04252 04253 /* split direction based on vnorms */ 04254 normal_tri_v3( nor,vlr->v1->co, vlr->v2->co, vlr->v3->co); 04255 d1= nor[0]*vlr->v1->n[0] + nor[1]*vlr->v1->n[1] + nor[2]*vlr->v1->n[2]; 04256 04257 normal_tri_v3( nor,vlr->v2->co, vlr->v3->co, vlr->v4->co); 04258 d2= nor[0]*vlr->v2->n[0] + nor[1]*vlr->v2->n[1] + nor[2]*vlr->v2->n[2]; 04259 04260 if( fabs(d1) < fabs(d2) ) vlr->flag |= R_DIVIDE_24; 04261 else vlr->flag &= ~R_DIVIDE_24; 04262 04263 /* new vertex pointers */ 04264 if (vlr->flag & R_DIVIDE_24) { 04265 vlr1->v1= vlr->v2; 04266 vlr1->v2= vlr->v3; 04267 vlr1->v3= vlr->v4; 04268 04269 vlr->v3 = vlr->v4; 04270 04271 vlr1->flag |= R_DIVIDE_24; 04272 } 04273 else { 04274 vlr1->v1= vlr->v1; 04275 vlr1->v2= vlr->v3; 04276 vlr1->v3= vlr->v4; 04277 04278 vlr1->flag &= ~R_DIVIDE_24; 04279 } 04280 vlr->v4 = vlr1->v4 = NULL; 04281 04282 /* new normals */ 04283 normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); 04284 normal_tri_v3( vlr1->n,vlr1->v3->co, vlr1->v2->co, vlr1->v1->co); 04285 } 04286 /* clear the flag when not divided */ 04287 else vlr->flag &= ~R_DIVIDE_24; 04288 } 04289 } 04290 } 04291 } 04292 04293 static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset) 04294 { 04295 Object *ob= obr->ob; 04296 VertRen *ver= NULL; 04297 StrandRen *strand= NULL; 04298 StrandBound *sbound= NULL; 04299 float min[3], max[3], smin[3], smax[3]; 04300 int a, b; 04301 04302 if(obr->totvert || obr->totvlak || obr->tothalo || obr->totstrand) { 04303 /* the exception below is because displace code now is in init_render_mesh call, 04304 I will look at means to have autosmooth enabled for all object types 04305 and have it as general postprocess, like displace */ 04306 if(ob->type!=OB_MESH && test_for_displace(re, ob)) 04307 do_displacement(re, obr, NULL, NULL); 04308 04309 if(!timeoffset) { 04310 /* phong normal interpolation can cause error in tracing 04311 * (terminator problem) */ 04312 ob->smoothresh= 0.0; 04313 if((re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW)) 04314 set_phong_threshold(obr); 04315 04316 if (re->flag & R_BAKING && re->r.bake_quad_split != 0) { 04317 /* Baking lets us define a quad split order */ 04318 split_quads(obr, re->r.bake_quad_split); 04319 } else { 04320 if((re->r.mode & R_SIMPLIFY && re->r.simplify_flag & R_SIMPLE_NO_TRIANGULATE) == 0) 04321 check_non_flat_quads(obr); 04322 } 04323 04324 set_fullsample_trace_flag(re, obr); 04325 04326 /* compute bounding boxes for clipping */ 04327 INIT_MINMAX(min, max); 04328 for(a=0; a<obr->totvert; a++) { 04329 if((a & 255)==0) ver= obr->vertnodes[a>>8].vert; 04330 else ver++; 04331 04332 DO_MINMAX(ver->co, min, max); 04333 } 04334 04335 if(obr->strandbuf) { 04336 float width; 04337 04338 /* compute average bounding box of strandpoint itself (width) */ 04339 if(obr->strandbuf->flag & R_STRAND_B_UNITS) 04340 obr->strandbuf->maxwidth= MAX2(obr->strandbuf->ma->strand_sta, obr->strandbuf->ma->strand_end); 04341 else 04342 obr->strandbuf->maxwidth= 0.0f; 04343 04344 width= obr->strandbuf->maxwidth; 04345 sbound= obr->strandbuf->bound; 04346 for(b=0; b<obr->strandbuf->totbound; b++, sbound++) { 04347 04348 INIT_MINMAX(smin, smax); 04349 04350 for(a=sbound->start; a<sbound->end; a++) { 04351 strand= RE_findOrAddStrand(obr, a); 04352 strand_minmax(strand, smin, smax, width); 04353 } 04354 04355 copy_v3_v3(sbound->boundbox[0], smin); 04356 copy_v3_v3(sbound->boundbox[1], smax); 04357 04358 DO_MINMAX(smin, min, max); 04359 DO_MINMAX(smax, min, max); 04360 } 04361 } 04362 04363 copy_v3_v3(obr->boundbox[0], min); 04364 copy_v3_v3(obr->boundbox[1], max); 04365 } 04366 } 04367 } 04368 04369 /* ------------------------------------------------------------------------- */ 04370 /* Database */ 04371 /* ------------------------------------------------------------------------- */ 04372 04373 static int render_object_type(short type) 04374 { 04375 return OB_TYPE_SUPPORT_MATERIAL(type); 04376 } 04377 04378 static void find_dupli_instances(Render *re, ObjectRen *obr) 04379 { 04380 ObjectInstanceRen *obi; 04381 float imat[4][4], obmat[4][4], obimat[4][4], nmat[3][3]; 04382 int first = 1; 04383 04384 mult_m4_m4m4(obmat, re->viewmat, obr->obmat); 04385 invert_m4_m4(imat, obmat); 04386 04387 /* for objects instanced by dupliverts/faces/particles, we go over the 04388 * list of instances to find ones that instance obr, and setup their 04389 * matrices and obr pointer */ 04390 for(obi=re->instancetable.last; obi; obi=obi->prev) { 04391 if(!obi->obr && obi->ob == obr->ob && obi->psysindex == obr->psysindex) { 04392 obi->obr= obr; 04393 04394 /* compute difference between object matrix and 04395 * object matrix with dupli transform, in viewspace */ 04396 copy_m4_m4(obimat, obi->mat); 04397 mult_m4_m4m4(obi->mat, obimat, imat); 04398 04399 copy_m3_m4(nmat, obi->mat); 04400 invert_m3_m3(obi->nmat, nmat); 04401 transpose_m3(obi->nmat); 04402 04403 if(!first) { 04404 re->totvert += obr->totvert; 04405 re->totvlak += obr->totvlak; 04406 re->tothalo += obr->tothalo; 04407 re->totstrand += obr->totstrand; 04408 } 04409 else 04410 first= 0; 04411 } 04412 } 04413 } 04414 04415 static void assign_dupligroup_dupli(Render *re, ObjectInstanceRen *obi, ObjectRen *obr) 04416 { 04417 float imat[4][4], obmat[4][4], obimat[4][4], nmat[3][3]; 04418 04419 mult_m4_m4m4(obmat, re->viewmat, obr->obmat); 04420 invert_m4_m4(imat, obmat); 04421 04422 obi->obr= obr; 04423 04424 /* compute difference between object matrix and 04425 * object matrix with dupli transform, in viewspace */ 04426 copy_m4_m4(obimat, obi->mat); 04427 mult_m4_m4m4(obi->mat, obimat, imat); 04428 04429 copy_m3_m4(nmat, obi->mat); 04430 invert_m3_m3(obi->nmat, nmat); 04431 transpose_m3(obi->nmat); 04432 04433 re->totvert += obr->totvert; 04434 re->totvlak += obr->totvlak; 04435 re->tothalo += obr->tothalo; 04436 re->totstrand += obr->totstrand; 04437 } 04438 04439 static ObjectRen *find_dupligroup_dupli(Render *re, Object *ob, int psysindex) 04440 { 04441 ObjectRen *obr; 04442 04443 /* if the object is itself instanced, we don't want to create an instance 04444 * for it */ 04445 if(ob->transflag & OB_RENDER_DUPLI) 04446 return NULL; 04447 04448 /* try to find an object that was already created so we can reuse it 04449 * and save memory */ 04450 for(obr=re->objecttable.first; obr; obr=obr->next) 04451 if(obr->ob == ob && obr->psysindex == psysindex && (obr->flag & R_INSTANCEABLE)) 04452 return obr; 04453 04454 return NULL; 04455 } 04456 04457 static void set_dupli_tex_mat(Render *re, ObjectInstanceRen *obi, DupliObject *dob) 04458 { 04459 /* For duplis we need to have a matrix that transform the coordinate back 04460 * to it's original position, without the dupli transforms. We also check 04461 * the matrix is actually needed, to save memory on lots of dupliverts for 04462 * example */ 04463 static Object *lastob= NULL; 04464 static int needtexmat= 0; 04465 04466 /* init */ 04467 if(!re) { 04468 lastob= NULL; 04469 needtexmat= 0; 04470 return; 04471 } 04472 04473 /* check if we actually need it */ 04474 if(lastob != dob->ob) { 04475 Material ***material; 04476 short a, *totmaterial; 04477 04478 lastob= dob->ob; 04479 needtexmat= 0; 04480 04481 totmaterial= give_totcolp(dob->ob); 04482 material= give_matarar(dob->ob); 04483 04484 if(totmaterial && material) 04485 for(a= 0; a<*totmaterial; a++) 04486 if((*material)[a] && (*material)[a]->texco & TEXCO_OBJECT) 04487 needtexmat= 1; 04488 } 04489 04490 if(needtexmat) { 04491 float imat[4][4]; 04492 04493 obi->duplitexmat= BLI_memarena_alloc(re->memArena, sizeof(float)*4*4); 04494 invert_m4_m4(imat, dob->mat); 04495 mul_serie_m4(obi->duplitexmat, re->viewmat, dob->omat, imat, re->viewinv, 0, 0, 0, 0); 04496 } 04497 } 04498 04499 static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset) 04500 { 04501 Object *ob= obr->ob; 04502 ParticleSystem *psys; 04503 int i; 04504 04505 if(obr->psysindex) { 04506 if((!obr->prev || obr->prev->ob != ob || (obr->prev->flag & R_INSTANCEABLE)==0) && ob->type==OB_MESH) { 04507 /* the emitter mesh wasn't rendered so the modifier stack wasn't 04508 * evaluated with render settings */ 04509 DerivedMesh *dm; 04510 dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); 04511 dm->release(dm); 04512 } 04513 04514 for(psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++) 04515 psys= psys->next; 04516 04517 render_new_particle_system(re, obr, psys, timeoffset); 04518 } 04519 else { 04520 if ELEM(ob->type, OB_FONT, OB_CURVE) 04521 init_render_curve(re, obr, timeoffset); 04522 else if(ob->type==OB_SURF) 04523 init_render_surf(re, obr, timeoffset); 04524 else if(ob->type==OB_MESH) 04525 init_render_mesh(re, obr, timeoffset); 04526 else if(ob->type==OB_MBALL) 04527 init_render_mball(re, obr); 04528 } 04529 04530 finalize_render_object(re, obr, timeoffset); 04531 04532 re->totvert += obr->totvert; 04533 re->totvlak += obr->totvlak; 04534 re->tothalo += obr->tothalo; 04535 re->totstrand += obr->totstrand; 04536 } 04537 04538 static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *dob, int timeoffset) 04539 { 04540 ObjectRen *obr; 04541 ObjectInstanceRen *obi; 04542 ParticleSystem *psys; 04543 int show_emitter, allow_render= 1, index, psysindex, i; 04544 04545 index= (dob)? dob->index: 0; 04546 04547 /* the emitter has to be processed first (render levels of modifiers) */ 04548 /* so here we only check if the emitter should be rendered */ 04549 if(ob->particlesystem.first) { 04550 show_emitter= 0; 04551 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 04552 show_emitter += psys->part->draw & PART_DRAW_EMITTER; 04553 psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); 04554 } 04555 04556 /* if no psys has "show emitter" selected don't render emitter */ 04557 if(show_emitter == 0) 04558 allow_render= 0; 04559 } 04560 04561 /* one render object for the data itself */ 04562 if(allow_render) { 04563 obr= RE_addRenderObject(re, ob, par, index, 0, ob->lay); 04564 if((dob && !dob->animated) || (ob->transflag & OB_RENDER_DUPLI)) { 04565 obr->flag |= R_INSTANCEABLE; 04566 copy_m4_m4(obr->obmat, ob->obmat); 04567 } 04568 init_render_object_data(re, obr, timeoffset); 04569 04570 /* only add instance for objects that have not been used for dupli */ 04571 if(!(ob->transflag & OB_RENDER_DUPLI)) { 04572 obi= RE_addRenderInstance(re, obr, ob, par, index, 0, NULL, ob->lay); 04573 if(dob) set_dupli_tex_mat(re, obi, dob); 04574 } 04575 else 04576 find_dupli_instances(re, obr); 04577 04578 for (i=1; i<=ob->totcol; i++) { 04579 Material* ma = give_render_material(re, ob, i); 04580 if (ma && ma->material_type == MA_TYPE_VOLUME) 04581 add_volume(re, obr, ma); 04582 } 04583 } 04584 04585 /* and one render object per particle system */ 04586 if(ob->particlesystem.first) { 04587 psysindex= 1; 04588 for(psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) { 04589 obr= RE_addRenderObject(re, ob, par, index, psysindex, ob->lay); 04590 if((dob && !dob->animated) || (ob->transflag & OB_RENDER_DUPLI)) { 04591 obr->flag |= R_INSTANCEABLE; 04592 copy_m4_m4(obr->obmat, ob->obmat); 04593 } 04594 if(dob) 04595 psys->flag |= PSYS_USE_IMAT; 04596 init_render_object_data(re, obr, timeoffset); 04597 psys_render_restore(ob, psys); 04598 psys->flag &= ~PSYS_USE_IMAT; 04599 04600 /* only add instance for objects that have not been used for dupli */ 04601 if(!(ob->transflag & OB_RENDER_DUPLI)) { 04602 obi= RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL, ob->lay); 04603 if(dob) set_dupli_tex_mat(re, obi, dob); 04604 } 04605 else 04606 find_dupli_instances(re, obr); 04607 } 04608 } 04609 } 04610 04611 /* par = pointer to duplicator parent, needed for object lookup table */ 04612 /* index = when duplicater copies same object (particle), the counter */ 04613 static void init_render_object(Render *re, Object *ob, Object *par, DupliObject *dob, int timeoffset) 04614 { 04615 static double lasttime= 0.0; 04616 double time; 04617 float mat[4][4]; 04618 04619 if(ob->type==OB_LAMP) 04620 add_render_lamp(re, ob); 04621 else if(render_object_type(ob->type)) 04622 add_render_object(re, ob, par, dob, timeoffset); 04623 else { 04624 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 04625 invert_m4_m4(ob->imat, mat); 04626 } 04627 04628 time= PIL_check_seconds_timer(); 04629 if(time - lasttime > 1.0) { 04630 lasttime= time; 04631 /* clumsy copying still */ 04632 re->i.totvert= re->totvert; 04633 re->i.totface= re->totvlak; 04634 re->i.totstrand= re->totstrand; 04635 re->i.tothalo= re->tothalo; 04636 re->i.totlamp= re->totlamp; 04637 re->stats_draw(re->sdh, &re->i); 04638 } 04639 04640 ob->flag |= OB_DONE; 04641 } 04642 04643 void RE_Database_Free(Render *re) 04644 { 04645 LampRen *lar; 04646 04647 /* statistics for debugging render memory usage */ 04648 if((G.f & G_DEBUG) && (G.rendering)) { 04649 if((re->r.scemode & R_PREVIEWBUTS)==0) { 04650 BKE_image_print_memlist(); 04651 MEM_printmemlist_stats(); 04652 } 04653 } 04654 04655 /* FREE */ 04656 04657 for(lar= re->lampren.first; lar; lar= lar->next) { 04658 freeshadowbuf(lar); 04659 if(lar->jitter) MEM_freeN(lar->jitter); 04660 if(lar->shadsamp) MEM_freeN(lar->shadsamp); 04661 if(lar->sunsky) MEM_freeN(lar->sunsky); 04662 curvemapping_free(lar->curfalloff); 04663 } 04664 04665 free_volume_precache(re); 04666 04667 BLI_freelistN(&re->lampren); 04668 BLI_freelistN(&re->lights); 04669 04670 free_renderdata_tables(re); 04671 04672 /* free orco */ 04673 free_mesh_orco_hash(re); 04674 #if 0 /* radio can be redone better */ 04675 end_radio_render(); 04676 #endif 04677 end_render_materials(re->main); 04678 end_render_textures(re); 04679 04680 free_pointdensities(re); 04681 04682 free_camera_inside_volumes(re); 04683 04684 if(re->wrld.aosphere) { 04685 MEM_freeN(re->wrld.aosphere); 04686 re->wrld.aosphere= NULL; 04687 re->scene->world->aosphere= NULL; 04688 } 04689 if(re->wrld.aotables) { 04690 MEM_freeN(re->wrld.aotables); 04691 re->wrld.aotables= NULL; 04692 re->scene->world->aotables= NULL; 04693 } 04694 if(re->r.mode & R_RAYTRACE) 04695 free_render_qmcsampler(re); 04696 04697 if(re->r.mode & R_RAYTRACE) freeraytree(re); 04698 04699 free_sss(re); 04700 free_occ(re); 04701 free_strand_surface(re); 04702 04703 re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; 04704 re->i.convertdone= 0; 04705 04706 re->bakebuf= NULL; 04707 04708 if(re->scene) 04709 if(re->scene->r.scemode & R_FREE_IMAGE) 04710 if((re->r.scemode & R_PREVIEWBUTS)==0) 04711 BKE_image_free_all_textures(); 04712 04713 if(re->memArena) { 04714 BLI_memarena_free(re->memArena); 04715 re->memArena = NULL; 04716 } 04717 } 04718 04719 static int allow_render_object(Render *re, Object *ob, int nolamps, int onlyselected, Object *actob) 04720 { 04721 /* override not showing object when duplis are used with particles */ 04722 if(ob->transflag & OB_DUPLIPARTS) 04723 ; /* let particle system(s) handle showing vs. not showing */ 04724 else if((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) 04725 return 0; 04726 04727 /* don't add non-basic meta objects, ends up having renderobjects with no geometry */ 04728 if (ob->type == OB_MBALL && ob!=find_basis_mball(re->scene, ob)) 04729 return 0; 04730 04731 if(nolamps && (ob->type==OB_LAMP)) 04732 return 0; 04733 04734 if(onlyselected && (ob!=actob && !(ob->flag & SELECT))) 04735 return 0; 04736 04737 return 1; 04738 } 04739 04740 static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Object *obd) 04741 { 04742 ParticleSystem *psys; 04743 Material *ma; 04744 short a, *totmaterial; 04745 04746 /* don't allow objects with halos. we need to have 04747 * all halo's to sort them globally in advance */ 04748 totmaterial= give_totcolp(obd); 04749 04750 if(totmaterial) { 04751 for(a= 0; a<*totmaterial; a++) { 04752 ma= give_current_material(obd, a); 04753 if(ma && (ma->material_type == MA_TYPE_HALO)) 04754 return 0; 04755 } 04756 } 04757 04758 for(psys=obd->particlesystem.first; psys; psys=psys->next) 04759 if(!ELEM5(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)) 04760 return 0; 04761 04762 /* don't allow lamp, animated duplis, or radio render */ 04763 return (render_object_type(obd->type) && 04764 (!(dob->type == OB_DUPLIGROUP) || !dob->animated)); 04765 } 04766 04767 static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, int level, int enable) 04768 { 04769 /* ugly function, but we need to set particle systems to their render 04770 * settings before calling object_duplilist, to get render level duplis */ 04771 Group *group; 04772 GroupObject *go; 04773 ParticleSystem *psys; 04774 DerivedMesh *dm; 04775 04776 if(level >= MAX_DUPLI_RECUR) 04777 return; 04778 04779 if(ob->transflag & OB_DUPLIPARTS) { 04780 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 04781 if(ELEM(psys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { 04782 if(enable) 04783 psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); 04784 else 04785 psys_render_restore(ob, psys); 04786 } 04787 } 04788 04789 if(enable) { 04790 /* this is to make sure we get render level duplis in groups: 04791 * the derivedmesh must be created before init_render_mesh, 04792 * since object_duplilist does dupliparticles before that */ 04793 dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); 04794 dm->release(dm); 04795 04796 for(psys=ob->particlesystem.first; psys; psys=psys->next) 04797 psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; 04798 } 04799 } 04800 04801 if(ob->dup_group==NULL) return; 04802 group= ob->dup_group; 04803 04804 for(go= group->gobject.first; go; go= go->next) 04805 dupli_render_particle_set(re, go->ob, timeoffset, level+1, enable); 04806 } 04807 04808 static int get_vector_renderlayers(Scene *sce) 04809 { 04810 SceneRenderLayer *srl; 04811 unsigned int lay= 0; 04812 04813 for(srl= sce->r.layers.first; srl; srl= srl->next) 04814 if(srl->passflag & SCE_PASS_VECTOR) 04815 lay |= srl->lay; 04816 04817 return lay; 04818 } 04819 04820 static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, int onlyselected, Object *actob, int timeoffset, int level) 04821 { 04822 GroupObject *go; 04823 Object *ob; 04824 04825 /* simple preventing of too deep nested groups */ 04826 if(level>MAX_DUPLI_RECUR) return; 04827 04828 /* recursively go into dupligroups to find objects with OB_RENDER_DUPLI 04829 * that were not created yet */ 04830 for(go= group->gobject.first; go; go= go->next) { 04831 ob= go->ob; 04832 04833 if(ob->flag & OB_DONE) { 04834 if(ob->transflag & OB_RENDER_DUPLI) { 04835 if(allow_render_object(re, ob, nolamps, onlyselected, actob)) { 04836 init_render_object(re, ob, NULL, 0, timeoffset); 04837 ob->transflag &= ~OB_RENDER_DUPLI; 04838 04839 if(ob->dup_group) 04840 add_group_render_dupli_obs(re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, level+1); 04841 } 04842 } 04843 } 04844 } 04845 } 04846 04847 static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset) 04848 { 04849 Base *base; 04850 Object *ob; 04851 Group *group; 04852 ObjectInstanceRen *obi; 04853 Scene *sce_iter; 04854 float mat[4][4]; 04855 int lay, vectorlay; 04856 04857 /* for duplis we need the Object texture mapping to work as if 04858 * untransformed, set_dupli_tex_mat sets the matrix to allow that 04859 * NULL is just for init */ 04860 set_dupli_tex_mat(NULL, NULL, NULL); 04861 04862 /* loop over all objects rather then using SETLOOPER because we may 04863 * reference an mtex-mapped object which isnt rendered or is an 04864 * empty in a dupli group. We could scan all render material/lamp/world 04865 * mtex's for mapto objects but its easier just to set the 04866 * 'imat' / 'imat_ren' on all and unlikely to be a performance hit 04867 * See bug: [#28744] - campbell */ 04868 for(ob= re->main->object.first; ob; ob= ob->id.next) { 04869 /* imat objects has to be done here, since displace can have texture using Object map-input */ 04870 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 04871 invert_m4_m4(ob->imat_ren, mat); 04872 copy_m4_m4(ob->imat, ob->imat_ren); 04873 /* each object should only be rendered once */ 04874 ob->flag &= ~OB_DONE; 04875 ob->transflag &= ~OB_RENDER_DUPLI; 04876 } 04877 04878 for(SETLOOPER(re->scene, sce_iter, base)) { 04879 ob= base->object; 04880 04881 /* in the prev/next pass for making speed vectors, avoid creating 04882 * objects that are not on a renderlayer with a vector pass, can 04883 * save a lot of time in complex scenes */ 04884 vectorlay= get_vector_renderlayers(re->scene); 04885 lay= (timeoffset)? renderlay & vectorlay: renderlay; 04886 04887 /* if the object has been restricted from rendering in the outliner, ignore it */ 04888 if(ob->restrictflag & OB_RESTRICT_RENDER) continue; 04889 04890 /* OB_DONE means the object itself got duplicated, so was already converted */ 04891 if(ob->flag & OB_DONE) { 04892 /* OB_RENDER_DUPLI means instances for it were already created, now 04893 * it still needs to create the ObjectRen containing the data */ 04894 if(ob->transflag & OB_RENDER_DUPLI) { 04895 if(allow_render_object(re, ob, nolamps, onlyselected, actob)) { 04896 init_render_object(re, ob, NULL, 0, timeoffset); 04897 ob->transflag &= ~OB_RENDER_DUPLI; 04898 } 04899 } 04900 } 04901 else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->lay)) ) { 04902 if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) { 04903 DupliObject *dob; 04904 ListBase *lb; 04905 04906 /* create list of duplis generated by this object, particle 04907 * system need to have render settings set for dupli particles */ 04908 dupli_render_particle_set(re, ob, timeoffset, 0, 1); 04909 lb= object_duplilist(re->scene, ob); 04910 dupli_render_particle_set(re, ob, timeoffset, 0, 0); 04911 04912 for(dob= lb->first; dob; dob= dob->next) { 04913 Object *obd= dob->ob; 04914 04915 copy_m4_m4(obd->obmat, dob->mat); 04916 04917 /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */ 04918 if(!(obd->transflag & OB_RENDER_DUPLI) && dob->no_draw) 04919 continue; 04920 04921 if(obd->restrictflag & OB_RESTRICT_RENDER) 04922 continue; 04923 04924 if(obd->type==OB_MBALL) 04925 continue; 04926 04927 if(!allow_render_object(re, obd, nolamps, onlyselected, actob)) 04928 continue; 04929 04930 if(allow_render_dupli_instance(re, dob, obd)) { 04931 ParticleSystem *psys; 04932 ObjectRen *obr = NULL; 04933 int psysindex; 04934 float mat[4][4]; 04935 04936 obi=NULL; 04937 04938 /* instances instead of the actual object are added in two cases, either 04939 * this is a duplivert/face/particle, or it is a non-animated object in 04940 * a dupligroup that has already been created before */ 04941 if(dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) { 04942 mult_m4_m4m4(mat, re->viewmat, dob->mat); 04943 obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat, obd->lay); 04944 04945 /* fill in instance variables for texturing */ 04946 set_dupli_tex_mat(re, obi, dob); 04947 if(dob->type != OB_DUPLIGROUP) { 04948 copy_v3_v3(obi->dupliorco, dob->orco); 04949 obi->dupliuv[0]= dob->uv[0]; 04950 obi->dupliuv[1]= dob->uv[1]; 04951 } 04952 else { 04953 /* for the second case, setup instance to point to the already 04954 * created object, and possibly setup instances if this object 04955 * itself was duplicated. for the first case find_dupli_instances 04956 * will be called later. */ 04957 assign_dupligroup_dupli(re, obi, obr); 04958 if(obd->transflag & OB_RENDER_DUPLI) 04959 find_dupli_instances(re, obr); 04960 } 04961 } 04962 04963 /* same logic for particles, each particle system has it's own object, so 04964 * need to go over them separately */ 04965 psysindex= 1; 04966 for(psys=obd->particlesystem.first; psys; psys=psys->next) { 04967 if(dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) { 04968 if(obi == NULL) 04969 mult_m4_m4m4(mat, re->viewmat, dob->mat); 04970 obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat, obd->lay); 04971 04972 set_dupli_tex_mat(re, obi, dob); 04973 if(dob->type != OB_DUPLIGROUP) { 04974 copy_v3_v3(obi->dupliorco, dob->orco); 04975 obi->dupliuv[0]= dob->uv[0]; 04976 obi->dupliuv[1]= dob->uv[1]; 04977 } 04978 else { 04979 assign_dupligroup_dupli(re, obi, obr); 04980 if(obd->transflag & OB_RENDER_DUPLI) 04981 find_dupli_instances(re, obr); 04982 } 04983 } 04984 } 04985 04986 if(obi==NULL) 04987 /* can't instance, just create the object */ 04988 init_render_object(re, obd, ob, dob, timeoffset); 04989 04990 if(dob->type != OB_DUPLIGROUP) { 04991 obd->flag |= OB_DONE; 04992 obd->transflag |= OB_RENDER_DUPLI; 04993 } 04994 } 04995 else 04996 init_render_object(re, obd, ob, dob, timeoffset); 04997 04998 if(re->test_break(re->tbh)) break; 04999 } 05000 free_object_duplilist(lb); 05001 05002 if(allow_render_object(re, ob, nolamps, onlyselected, actob)) 05003 init_render_object(re, ob, NULL, 0, timeoffset); 05004 } 05005 else if(allow_render_object(re, ob, nolamps, onlyselected, actob)) 05006 init_render_object(re, ob, NULL, 0, timeoffset); 05007 } 05008 05009 if(re->test_break(re->tbh)) break; 05010 } 05011 05012 /* objects in groups with OB_RENDER_DUPLI set still need to be created, 05013 * since they may not be part of the scene */ 05014 for(group= re->main->group.first; group; group=group->id.next) 05015 add_group_render_dupli_obs(re, group, nolamps, onlyselected, actob, timeoffset, 0); 05016 05017 if(!re->test_break(re->tbh)) 05018 RE_makeRenderInstances(re); 05019 } 05020 05021 /* used to be 'rotate scene' */ 05022 void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int lay, int use_camera_view) 05023 { 05024 Scene *sce; 05025 float mat[4][4]; 05026 float amb[3]; 05027 Object *camera= RE_GetCamera(re); 05028 05029 re->main= bmain; 05030 re->scene= scene; 05031 re->lay= lay; 05032 05033 /* per second, per object, stats print this */ 05034 re->i.infostr= "Preparing Scene data"; 05035 re->i.cfra= scene->r.cfra; 05036 BLI_strncpy(re->i.scenename, scene->id.name+2, sizeof(re->i.scenename)); 05037 05038 /* XXX add test if dbase was filled already? */ 05039 05040 re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "render db arena"); 05041 re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; 05042 re->lights.first= re->lights.last= NULL; 05043 re->lampren.first= re->lampren.last= NULL; 05044 05045 slurph_opt= 0; 05046 re->i.partsdone= 0; /* signal now in use for previewrender */ 05047 05048 /* in localview, lamps are using normal layers, objects only local bits */ 05049 if(re->lay & 0xFF000000) 05050 lay &= 0xFF000000; 05051 05052 /* applies changes fully */ 05053 if((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0) 05054 scene_update_for_newframe(re->main, re->scene, lay); 05055 05056 /* if no camera, viewmat should have been set! */ 05057 if(use_camera_view && camera) { 05058 /* called before but need to call again incase of lens animation from the 05059 * above call to scene_update_for_newframe, fixes bug. [#22702]. 05060 * following calls dont depend on 'RE_SetCamera' */ 05061 RE_SetCamera(re, camera); 05062 05063 normalize_m4(camera->obmat); 05064 invert_m4_m4(mat, camera->obmat); 05065 RE_SetView(re, mat); 05066 camera->recalc= OB_RECALC_OB; /* force correct matrix for scaled cameras */ 05067 } 05068 05069 init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */ 05070 if(re->r.mode & R_RAYTRACE) { 05071 init_render_qmcsampler(re); 05072 05073 if(re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) 05074 if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) 05075 init_ao_sphere(&re->wrld); 05076 } 05077 05078 /* still bad... doing all */ 05079 init_render_textures(re); 05080 copy_v3_v3(amb, &re->wrld.ambr); 05081 init_render_materials(re->main, re->r.mode, amb); 05082 set_node_shader_lamp_loop(shade_material_loop); 05083 05084 /* MAKE RENDER DATA */ 05085 database_init_objects(re, lay, 0, 0, 0, 0); 05086 05087 if(!re->test_break(re->tbh)) { 05088 int tothalo; 05089 05090 set_material_lightgroups(re); 05091 for(sce= re->scene; sce; sce= sce->set) 05092 set_renderlayer_lightgroups(re, sce); 05093 05094 slurph_opt= 1; 05095 05096 /* for now some clumsy copying still */ 05097 re->i.totvert= re->totvert; 05098 re->i.totface= re->totvlak; 05099 re->i.totstrand= re->totstrand; 05100 re->i.tothalo= re->tothalo; 05101 re->i.totlamp= re->totlamp; 05102 re->stats_draw(re->sdh, &re->i); 05103 05104 /* don't sort stars */ 05105 tothalo= re->tothalo; 05106 if(!re->test_break(re->tbh)) { 05107 if(re->wrld.mode & WO_STARS) { 05108 re->i.infostr= "Creating Starfield"; 05109 re->stats_draw(re->sdh, &re->i); 05110 RE_make_stars(re, NULL, NULL, NULL, NULL); 05111 } 05112 } 05113 sort_halos(re, tothalo); 05114 05115 init_camera_inside_volumes(re); 05116 05117 re->i.infostr= "Creating Shadowbuffers"; 05118 re->stats_draw(re->sdh, &re->i); 05119 05120 /* SHADOW BUFFER */ 05121 threaded_makeshadowbufs(re); 05122 05123 /* old code checked for internal render (aka not yafray) */ 05124 { 05125 /* raytree */ 05126 if(!re->test_break(re->tbh)) { 05127 if(re->r.mode & R_RAYTRACE) { 05128 makeraytree(re); 05129 } 05130 } 05131 /* ENVIRONMENT MAPS */ 05132 if(!re->test_break(re->tbh)) 05133 make_envmaps(re); 05134 05135 /* point density texture */ 05136 if(!re->test_break(re->tbh)) 05137 make_pointdensities(re); 05138 /* voxel data texture */ 05139 if(!re->test_break(re->tbh)) 05140 make_voxeldata(re); 05141 } 05142 05143 if(!re->test_break(re->tbh)) 05144 project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); 05145 05146 /* Occlusion */ 05147 if((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh)) 05148 if(re->wrld.ao_gather_method == WO_AOGATHER_APPROX) 05149 if(re->r.mode & R_SHADOW) 05150 make_occ_tree(re); 05151 05152 /* SSS */ 05153 if((re->r.mode & R_SSS) && !re->test_break(re->tbh)) 05154 make_sss_tree(re); 05155 05156 if(!re->test_break(re->tbh)) 05157 if(re->r.mode & R_RAYTRACE) 05158 volume_precache(re); 05159 05160 } 05161 05162 if(re->test_break(re->tbh)) 05163 RE_Database_Free(re); 05164 else 05165 re->i.convertdone= 1; 05166 05167 re->i.infostr= NULL; 05168 re->stats_draw(re->sdh, &re->i); 05169 } 05170 05171 /* exported call to recalculate hoco for vertices, when winmat changed */ 05172 void RE_DataBase_ApplyWindow(Render *re) 05173 { 05174 project_renderdata(re, projectverto, 0, 0, 0); 05175 } 05176 05177 void RE_DataBase_GetView(Render *re, float mat[][4]) 05178 { 05179 copy_m4_m4(mat, re->viewmat); 05180 } 05181 05182 /* ------------------------------------------------------------------------- */ 05183 /* Speed Vectors */ 05184 /* ------------------------------------------------------------------------- */ 05185 05186 static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int lay, int timeoffset) 05187 { 05188 Object *camera= RE_GetCamera(re); 05189 float mat[4][4]; 05190 05191 re->scene= scene; 05192 re->lay= lay; 05193 05194 /* XXX add test if dbase was filled already? */ 05195 05196 re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vector render db arena"); 05197 re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; 05198 re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0; 05199 re->lights.first= re->lights.last= NULL; 05200 05201 slurph_opt= 0; 05202 05203 /* in localview, lamps are using normal layers, objects only local bits */ 05204 if(re->lay & 0xFF000000) 05205 lay &= 0xFF000000; 05206 05207 /* applies changes fully */ 05208 scene->r.cfra += timeoffset; 05209 scene_update_for_newframe(re->main, re->scene, lay); 05210 05211 /* if no camera, viewmat should have been set! */ 05212 if(camera) { 05213 normalize_m4(camera->obmat); 05214 invert_m4_m4(mat, camera->obmat); 05215 RE_SetView(re, mat); 05216 } 05217 05218 /* MAKE RENDER DATA */ 05219 database_init_objects(re, lay, 0, 0, 0, timeoffset); 05220 05221 if(!re->test_break(re->tbh)) 05222 project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); 05223 05224 /* do this in end, particles for example need cfra */ 05225 scene->r.cfra -= timeoffset; 05226 } 05227 05228 /* choose to use static, to prevent giving too many args to this call */ 05229 static void speedvector_project(Render *re, float zco[2], const float co[3], const float ho[4]) 05230 { 05231 static float pixelphix=0.0f, pixelphiy=0.0f, zmulx=0.0f, zmuly=0.0f; 05232 static int pano= 0; 05233 float div; 05234 05235 /* initialize */ 05236 if(re) { 05237 pano= re->r.mode & R_PANORAMA; 05238 05239 /* precalculate amount of radians 1 pixel rotates */ 05240 if(pano) { 05241 /* size of 1 pixel mapped to viewplane coords */ 05242 float psize= (re->viewplane.xmax-re->viewplane.xmin)/(float)re->winx; 05243 /* x angle of a pixel */ 05244 pixelphix= atan(psize/re->clipsta); 05245 05246 psize= (re->viewplane.ymax-re->viewplane.ymin)/(float)re->winy; 05247 /* y angle of a pixel */ 05248 pixelphiy= atan(psize/re->clipsta); 05249 } 05250 zmulx= re->winx/2; 05251 zmuly= re->winy/2; 05252 05253 return; 05254 } 05255 05256 /* now map hocos to screenspace, uses very primitive clip still */ 05257 if(ho[3]<0.1f) div= 10.0f; 05258 else div= 1.0f/ho[3]; 05259 05260 /* use cylinder projection */ 05261 if(pano) { 05262 float vec[3], ang; 05263 /* angle between (0,0,-1) and (co) */ 05264 copy_v3_v3(vec, co); 05265 05266 ang= saacos(-vec[2]/sqrtf(vec[0]*vec[0] + vec[2]*vec[2])); 05267 if(vec[0]<0.0f) ang= -ang; 05268 zco[0]= ang/pixelphix + zmulx; 05269 05270 ang= 0.5f*(float)M_PI - saacos(vec[1]/sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2])); 05271 zco[1]= ang/pixelphiy + zmuly; 05272 05273 } 05274 else { 05275 zco[0]= zmulx*(1.0f+ho[0]*div); 05276 zco[1]= zmuly*(1.0f+ho[1]*div); 05277 } 05278 } 05279 05280 static void calculate_speedvector(const float vectors[2], int step, float winsq, float winroot, const float co[3], const float ho[4], float speed[4]) 05281 { 05282 float zco[2], len; 05283 05284 speedvector_project(NULL, zco, co, ho); 05285 05286 zco[0]= vectors[0] - zco[0]; 05287 zco[1]= vectors[1] - zco[1]; 05288 05289 /* enable nice masks for hardly moving stuff or float inaccuracy */ 05290 if(zco[0]<0.1f && zco[0]>-0.1f && zco[1]<0.1f && zco[1]>-0.1f ) { 05291 zco[0]= 0.0f; 05292 zco[1]= 0.0f; 05293 } 05294 05295 /* maximize speed for image width, otherwise it never looks good */ 05296 len= zco[0]*zco[0] + zco[1]*zco[1]; 05297 if(len > winsq) { 05298 len= winroot/sqrtf(len); 05299 zco[0]*= len; 05300 zco[1]*= len; 05301 } 05302 05303 /* note; in main vecblur loop speedvec is negated again */ 05304 if(step) { 05305 speed[2]= -zco[0]; 05306 speed[3]= -zco[1]; 05307 } 05308 else { 05309 speed[0]= zco[0]; 05310 speed[1]= zco[1]; 05311 } 05312 } 05313 05314 static float *calculate_strandsurface_speedvectors(Render *re, ObjectInstanceRen *obi, StrandSurface *mesh) 05315 { 05316 if(mesh->co && mesh->prevco && mesh->nextco) { 05317 float winsq= (float)re->winx*(float)re->winy; /* int's can wrap on large images */ 05318 float winroot= sqrt(winsq); 05319 float (*winspeed)[4]; 05320 float ho[4], prevho[4], nextho[4], winmat[4][4], vec[2]; 05321 int a; 05322 05323 if(obi->flag & R_TRANSFORMED) 05324 mult_m4_m4m4(winmat, re->winmat, obi->mat); 05325 else 05326 copy_m4_m4(winmat, re->winmat); 05327 05328 winspeed= MEM_callocN(sizeof(float)*4*mesh->totvert, "StrandSurfWin"); 05329 05330 for(a=0; a<mesh->totvert; a++) { 05331 projectvert(mesh->co[a], winmat, ho); 05332 05333 projectvert(mesh->prevco[a], winmat, prevho); 05334 speedvector_project(NULL, vec, mesh->prevco[a], prevho); 05335 calculate_speedvector(vec, 0, winsq, winroot, mesh->co[a], ho, winspeed[a]); 05336 05337 projectvert(mesh->nextco[a], winmat, nextho); 05338 speedvector_project(NULL, vec, mesh->nextco[a], nextho); 05339 calculate_speedvector(vec, 1, winsq, winroot, mesh->co[a], ho, winspeed[a]); 05340 } 05341 05342 return (float*)winspeed; 05343 } 05344 05345 return NULL; 05346 } 05347 05348 static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step) 05349 { 05350 ObjectRen *obr= obi->obr; 05351 VertRen *ver= NULL; 05352 StrandRen *strand= NULL; 05353 StrandBuffer *strandbuf; 05354 StrandSurface *mesh= NULL; 05355 float *speed, (*winspeed)[4]=NULL, ho[4], winmat[4][4]; 05356 float *co1, *co2, *co3, *co4, w[4]; 05357 float winsq= (float)re->winx*(float)re->winy, winroot= sqrt(winsq); /* int's can wrap on large images */ 05358 int a, *face, *index; 05359 05360 if(obi->flag & R_TRANSFORMED) 05361 mult_m4_m4m4(winmat, re->winmat, obi->mat); 05362 else 05363 copy_m4_m4(winmat, re->winmat); 05364 05365 if(obr->vertnodes) { 05366 for(a=0; a<obr->totvert; a++, vectors+=2) { 05367 if((a & 255)==0) ver= obr->vertnodes[a>>8].vert; 05368 else ver++; 05369 05370 speed= RE_vertren_get_winspeed(obi, ver, 1); 05371 projectvert(ver->co, winmat, ho); 05372 calculate_speedvector(vectors, step, winsq, winroot, ver->co, ho, speed); 05373 } 05374 } 05375 05376 if(obr->strandnodes) { 05377 strandbuf= obr->strandbuf; 05378 mesh= (strandbuf)? strandbuf->surface: NULL; 05379 05380 /* compute speed vectors at surface vertices */ 05381 if(mesh) 05382 winspeed= (float(*)[4])calculate_strandsurface_speedvectors(re, obi, mesh); 05383 05384 if(winspeed) { 05385 for(a=0; a<obr->totstrand; a++, vectors+=2) { 05386 if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; 05387 else strand++; 05388 05389 index= RE_strandren_get_face(obr, strand, 0); 05390 if(index && *index < mesh->totface) { 05391 speed= RE_strandren_get_winspeed(obi, strand, 1); 05392 05393 /* interpolate speed vectors from strand surface */ 05394 face= mesh->face[*index]; 05395 05396 co1= mesh->co[face[0]]; 05397 co2= mesh->co[face[1]]; 05398 co3= mesh->co[face[2]]; 05399 co4= (face[3])? mesh->co[face[3]]: NULL; 05400 05401 interp_weights_face_v3( w,co1, co2, co3, co4, strand->vert->co); 05402 05403 zero_v4(speed); 05404 madd_v4_v4fl(speed, winspeed[face[0]], w[0]); 05405 madd_v4_v4fl(speed, winspeed[face[1]], w[1]); 05406 madd_v4_v4fl(speed, winspeed[face[2]], w[2]); 05407 if(face[3]) 05408 madd_v4_v4fl(speed, winspeed[face[3]], w[3]); 05409 } 05410 } 05411 05412 MEM_freeN(winspeed); 05413 } 05414 } 05415 } 05416 05417 static int load_fluidsimspeedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step) 05418 { 05419 ObjectRen *obr= obi->obr; 05420 Object *fsob= obr->ob; 05421 VertRen *ver= NULL; 05422 float *speed, div, zco[2], avgvel[4] = {0.0, 0.0, 0.0, 0.0}; 05423 float zmulx= re->winx/2, zmuly= re->winy/2, len; 05424 float winsq= (float)re->winx*(float)re->winy, winroot= sqrt(winsq); /* int's can wrap on large images */ 05425 int a, j; 05426 float hoco[4], ho[4], fsvec[4], camco[4]; 05427 float mat[4][4], winmat[4][4]; 05428 float imat[4][4]; 05429 FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsob, eModifierType_Fluidsim); 05430 FluidsimSettings *fss; 05431 FluidVertexVelocity *velarray = NULL; 05432 05433 /* only one step needed */ 05434 if(step) return 1; 05435 05436 if(fluidmd) 05437 fss = fluidmd->fss; 05438 else 05439 return 0; 05440 05441 copy_m4_m4(mat, re->viewmat); 05442 invert_m4_m4(imat, mat); 05443 05444 /* set first vertex OK */ 05445 if(!fss->meshVelocities) return 0; 05446 05447 if( obr->totvert != fss->totvert) { 05448 //fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", obr->totvert, fsob->fluidsimSettings->meshSurface->totvert); // DEBUG 05449 return 0; 05450 } 05451 05452 velarray = fss->meshVelocities; 05453 05454 if(obi->flag & R_TRANSFORMED) 05455 mult_m4_m4m4(winmat, re->winmat, obi->mat); 05456 else 05457 copy_m4_m4(winmat, re->winmat); 05458 05459 /* (bad) HACK calculate average velocity */ 05460 /* better solution would be fixing getVelocityAt() in intern/elbeem/intern/solver_util.cpp 05461 so that also small drops/little water volumes return a velocity != 0. 05462 But I had no luck in fixing that function - DG */ 05463 for(a=0; a<obr->totvert; a++) { 05464 for(j=0;j<3;j++) avgvel[j] += velarray[a].vel[j]; 05465 05466 } 05467 for(j=0;j<3;j++) avgvel[j] /= (float)(obr->totvert); 05468 05469 05470 for(a=0; a<obr->totvert; a++, vectors+=2) { 05471 if((a & 255)==0) 05472 ver= obr->vertnodes[a>>8].vert; 05473 else 05474 ver++; 05475 05476 // get fluid velocity 05477 fsvec[3] = 0.; 05478 //fsvec[0] = fsvec[1] = fsvec[2] = fsvec[3] = 0.; fsvec[2] = 2.; // NT fixed test 05479 for(j=0;j<3;j++) fsvec[j] = velarray[a].vel[j]; 05480 05481 /* (bad) HACK insert average velocity if none is there (see previous comment) */ 05482 if((fsvec[0] == 0.0f) && (fsvec[1] == 0.0f) && (fsvec[2] == 0.0f)) 05483 { 05484 fsvec[0] = avgvel[0]; 05485 fsvec[1] = avgvel[1]; 05486 fsvec[2] = avgvel[2]; 05487 } 05488 05489 // transform (=rotate) to cam space 05490 camco[0]= imat[0][0]*fsvec[0] + imat[0][1]*fsvec[1] + imat[0][2]*fsvec[2]; 05491 camco[1]= imat[1][0]*fsvec[0] + imat[1][1]*fsvec[1] + imat[1][2]*fsvec[2]; 05492 camco[2]= imat[2][0]*fsvec[0] + imat[2][1]*fsvec[1] + imat[2][2]*fsvec[2]; 05493 05494 // get homogenous coordinates 05495 projectvert(camco, winmat, hoco); 05496 projectvert(ver->co, winmat, ho); 05497 05498 /* now map hocos to screenspace, uses very primitive clip still */ 05499 // use ho[3] of original vertex, xy component of vel. direction 05500 if(ho[3]<0.1f) div= 10.0f; 05501 else div= 1.0f/ho[3]; 05502 zco[0]= zmulx*hoco[0]*div; 05503 zco[1]= zmuly*hoco[1]*div; 05504 05505 // maximize speed as usual 05506 len= zco[0]*zco[0] + zco[1]*zco[1]; 05507 if(len > winsq) { 05508 len= winroot/sqrtf(len); 05509 zco[0]*= len; zco[1]*= len; 05510 } 05511 05512 speed= RE_vertren_get_winspeed(obi, ver, 1); 05513 // set both to the same value 05514 speed[0]= speed[2]= zco[0]; 05515 speed[1]= speed[3]= zco[1]; 05516 //if(a<20) fprintf(stderr,"speed %d %f,%f | camco %f,%f,%f | hoco %f,%f,%f,%f \n", a, speed[0], speed[1], camco[0],camco[1], camco[2], hoco[0],hoco[1], hoco[2],hoco[3]); // NT DEBUG 05517 } 05518 05519 return 1; 05520 } 05521 05522 /* makes copy per object of all vectors */ 05523 /* result should be that we can free entire database */ 05524 static void copy_dbase_object_vectors(Render *re, ListBase *lb) 05525 { 05526 ObjectInstanceRen *obi, *obilb; 05527 ObjectRen *obr; 05528 VertRen *ver= NULL; 05529 float *vec, ho[4], winmat[4][4]; 05530 int a, totvector; 05531 05532 for(obi= re->instancetable.first; obi; obi= obi->next) { 05533 obr= obi->obr; 05534 05535 obilb= MEM_mallocN(sizeof(ObjectInstanceRen), "ObInstanceVector"); 05536 memcpy(obilb, obi, sizeof(ObjectInstanceRen)); 05537 BLI_addtail(lb, obilb); 05538 05539 obilb->totvector= totvector= obr->totvert; 05540 05541 if(totvector > 0) { 05542 vec= obilb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array"); 05543 05544 if(obi->flag & R_TRANSFORMED) 05545 mult_m4_m4m4(winmat, re->winmat, obi->mat); 05546 else 05547 copy_m4_m4(winmat, re->winmat); 05548 05549 for(a=0; a<obr->totvert; a++, vec+=2) { 05550 if((a & 255)==0) ver= obr->vertnodes[a>>8].vert; 05551 else ver++; 05552 05553 projectvert(ver->co, winmat, ho); 05554 speedvector_project(NULL, vec, ver->co, ho); 05555 } 05556 } 05557 } 05558 } 05559 05560 static void free_dbase_object_vectors(ListBase *lb) 05561 { 05562 ObjectInstanceRen *obi; 05563 05564 for(obi= lb->first; obi; obi= obi->next) 05565 if(obi->vectors) 05566 MEM_freeN(obi->vectors); 05567 BLI_freelistN(lb); 05568 } 05569 05570 void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned int lay) 05571 { 05572 ObjectInstanceRen *obi, *oldobi; 05573 StrandSurface *mesh; 05574 ListBase *table; 05575 ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL}; 05576 ListBase strandsurface; 05577 int step; 05578 05579 re->i.infostr= "Calculating previous frame vectors"; 05580 re->r.mode |= R_SPEED; 05581 05582 speedvector_project(re, NULL, NULL, NULL); /* initializes projection code */ 05583 05584 /* creates entire dbase */ 05585 database_fromscene_vectors(re, sce, lay, -1); 05586 05587 /* copy away vertex info */ 05588 copy_dbase_object_vectors(re, &oldtable); 05589 05590 /* free dbase and make the future one */ 05591 strandsurface= re->strandsurface; 05592 memset(&re->strandsurface, 0, sizeof(ListBase)); 05593 RE_Database_Free(re); 05594 re->strandsurface= strandsurface; 05595 05596 if(!re->test_break(re->tbh)) { 05597 /* creates entire dbase */ 05598 re->i.infostr= "Calculating next frame vectors"; 05599 05600 database_fromscene_vectors(re, sce, lay, +1); 05601 } 05602 /* copy away vertex info */ 05603 copy_dbase_object_vectors(re, &newtable); 05604 05605 /* free dbase and make the real one */ 05606 strandsurface= re->strandsurface; 05607 memset(&re->strandsurface, 0, sizeof(ListBase)); 05608 RE_Database_Free(re); 05609 re->strandsurface= strandsurface; 05610 05611 if(!re->test_break(re->tbh)) 05612 RE_Database_FromScene(re, bmain, sce, lay, 1); 05613 05614 if(!re->test_break(re->tbh)) { 05615 int vectorlay= get_vector_renderlayers(re->scene); 05616 05617 for(step= 0; step<2; step++) { 05618 05619 if(step) 05620 table= &newtable; 05621 else 05622 table= &oldtable; 05623 05624 oldobi= table->first; 05625 for(obi= re->instancetable.first; obi && oldobi; obi= obi->next) { 05626 int ok= 1; 05627 FluidsimModifierData *fluidmd; 05628 05629 if(!(obi->lay & vectorlay)) 05630 continue; 05631 05632 obi->totvector= obi->obr->totvert; 05633 05634 /* find matching object in old table */ 05635 if(oldobi->ob!=obi->ob || oldobi->par!=obi->par || oldobi->index!=obi->index || oldobi->psysindex!=obi->psysindex) { 05636 ok= 0; 05637 for(oldobi= table->first; oldobi; oldobi= oldobi->next) 05638 if(oldobi->ob==obi->ob && oldobi->par==obi->par && oldobi->index==obi->index && oldobi->psysindex==obi->psysindex) 05639 break; 05640 if(oldobi==NULL) 05641 oldobi= table->first; 05642 else 05643 ok= 1; 05644 } 05645 if(ok==0) { 05646 printf("speed table: missing object %s\n", obi->ob->id.name+2); 05647 continue; 05648 } 05649 05650 // NT check for fluidsim special treatment 05651 fluidmd = (FluidsimModifierData *)modifiers_findByType(obi->ob, eModifierType_Fluidsim); 05652 if(fluidmd && fluidmd->fss && (fluidmd->fss->type & OB_FLUIDSIM_DOMAIN)) { 05653 // use preloaded per vertex simulation data , only does calculation for step=1 05654 // NOTE/FIXME - velocities and meshes loaded unnecessarily often during the database_fromscene_vectors calls... 05655 load_fluidsimspeedvectors(re, obi, oldobi->vectors, step); 05656 } 05657 else { 05658 /* check if both have same amounts of vertices */ 05659 if(obi->totvector==oldobi->totvector) 05660 calculate_speedvectors(re, obi, oldobi->vectors, step); 05661 else 05662 printf("Warning: object %s has different amount of vertices or strands on other frame\n", obi->ob->id.name+2); 05663 } // not fluidsim 05664 05665 oldobi= oldobi->next; 05666 } 05667 } 05668 } 05669 05670 free_dbase_object_vectors(&oldtable); 05671 free_dbase_object_vectors(&newtable); 05672 05673 for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { 05674 if(mesh->prevco) { 05675 MEM_freeN(mesh->prevco); 05676 mesh->prevco= NULL; 05677 } 05678 if(mesh->nextco) { 05679 MEM_freeN(mesh->nextco); 05680 mesh->nextco= NULL; 05681 } 05682 } 05683 05684 re->i.infostr= NULL; 05685 re->stats_draw(re->sdh, &re->i); 05686 } 05687 05688 05689 /* ------------------------------------------------------------------------- */ 05690 /* Baking */ 05691 /* ------------------------------------------------------------------------- */ 05692 05693 /* setup for shaded view or bake, so only lamps and materials are initialized */ 05694 /* type: 05695 RE_BAKE_LIGHT: for shaded view, only add lamps 05696 RE_BAKE_ALL: for baking, all lamps and objects 05697 RE_BAKE_NORMALS:for baking, no lamps and only selected objects 05698 RE_BAKE_AO: for baking, no lamps, but all objects 05699 RE_BAKE_TEXTURE:for baking, no lamps, only selected objects 05700 RE_BAKE_DISPLACEMENT:for baking, no lamps, only selected objects 05701 RE_BAKE_SHADOW: for baking, only shadows, but all objects 05702 */ 05703 void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, const int type, Object *actob) 05704 { 05705 Object *camera; 05706 float mat[4][4]; 05707 float amb[3]; 05708 const short onlyselected= !ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO); 05709 const short nolamps= ELEM3(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT); 05710 05711 re->main= bmain; 05712 re->scene= scene; 05713 re->lay= lay; 05714 05715 /* renderdata setup and exceptions */ 05716 re->r= scene->r; 05717 05718 RE_init_threadcount(re); 05719 05720 re->flag |= R_BAKING; 05721 re->excludeob= actob; 05722 if(actob) 05723 re->flag |= R_BAKE_TRACE; 05724 05725 if(type==RE_BAKE_NORMALS && re->r.bake_normal_space==R_BAKE_SPACE_TANGENT) 05726 re->flag |= R_NEED_TANGENT; 05727 05728 if(!actob && ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT)) { 05729 re->r.mode &= ~R_SHADOW; 05730 re->r.mode &= ~R_RAYTRACE; 05731 } 05732 05733 if(!actob && (type==RE_BAKE_SHADOW)) { 05734 re->r.mode |= R_SHADOW; 05735 } 05736 05737 /* setup render stuff */ 05738 re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "bake db arena"); 05739 05740 re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; 05741 re->lights.first= re->lights.last= NULL; 05742 re->lampren.first= re->lampren.last= NULL; 05743 05744 /* in localview, lamps are using normal layers, objects only local bits */ 05745 if(re->lay & 0xFF000000) 05746 lay &= 0xFF000000; 05747 05748 camera= RE_GetCamera(re); 05749 05750 /* if no camera, set unit */ 05751 if(camera) { 05752 normalize_m4(camera->obmat); 05753 invert_m4_m4(mat, camera->obmat); 05754 RE_SetView(re, mat); 05755 } 05756 else { 05757 unit_m4(mat); 05758 RE_SetView(re, mat); 05759 } 05760 copy_m3_m4(re->imat, re->viewinv); 05761 05762 /* TODO: deep shadow maps + baking + strands */ 05763 /* strands use the window matrix and view size, there is to correct 05764 * window matrix but at least avoids malloc and crash loop [#27807] */ 05765 unit_m4(re->winmat); 05766 re->winx= re->winy= 256; 05767 /* done setting dummy values */ 05768 05769 init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */ 05770 if(re->r.mode & R_RAYTRACE) { 05771 init_render_qmcsampler(re); 05772 05773 if(re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) 05774 if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) 05775 init_ao_sphere(&re->wrld); 05776 } 05777 05778 /* still bad... doing all */ 05779 init_render_textures(re); 05780 05781 copy_v3_v3(amb, &re->wrld.ambr); 05782 init_render_materials(re->main, re->r.mode, amb); 05783 05784 set_node_shader_lamp_loop(shade_material_loop); 05785 05786 /* MAKE RENDER DATA */ 05787 database_init_objects(re, lay, nolamps, onlyselected, actob, 0); 05788 05789 set_material_lightgroups(re); 05790 05791 /* SHADOW BUFFER */ 05792 if(type!=RE_BAKE_LIGHT) 05793 if(re->r.mode & R_SHADOW) 05794 threaded_makeshadowbufs(re); 05795 05796 /* raytree */ 05797 if(!re->test_break(re->tbh)) 05798 if(re->r.mode & R_RAYTRACE) 05799 makeraytree(re); 05800 05801 /* point density texture */ 05802 if(!re->test_break(re->tbh)) 05803 make_pointdensities(re); 05804 05805 /* voxel data texture */ 05806 if(!re->test_break(re->tbh)) 05807 make_voxeldata(re); 05808 05809 /* occlusion */ 05810 if((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh)) 05811 if(re->wrld.ao_gather_method == WO_AOGATHER_APPROX) 05812 if(re->r.mode & R_SHADOW) 05813 make_occ_tree(re); 05814 } 05815 05816 /* ------------------------------------------------------------------------- */ 05817 /* Sticky texture coords */ 05818 /* ------------------------------------------------------------------------- */ 05819 05820 void RE_make_sticky(Scene *scene, View3D *v3d) 05821 { 05822 Object *ob; 05823 Base *base; 05824 MVert *mvert; 05825 Mesh *me; 05826 MSticky *ms; 05827 Render *re; 05828 float ho[4], mat[4][4]; 05829 int a; 05830 Object *camera= NULL; 05831 05832 if(v3d==NULL) { 05833 printf("Need a 3d view to make sticky\n"); 05834 return; 05835 } 05836 05837 if(v3d) camera= V3D_CAMERA_LOCAL(v3d); 05838 if(camera == NULL) camera= scene->camera; 05839 05840 if(camera==NULL) { 05841 printf("Need camera to make sticky\n"); 05842 return; 05843 } 05844 if(scene->obedit) { 05845 printf("Unable to make sticky in Edit Mode\n"); 05846 return; 05847 } 05848 05849 re= RE_NewRender("_make sticky_"); 05850 RE_InitState(re, NULL, &scene->r, NULL, scene->r.xsch, scene->r.ysch, NULL); 05851 05852 /* use renderdata and camera to set viewplane */ 05853 RE_SetCamera(re, camera); 05854 05855 /* and set view matrix */ 05856 normalize_m4(camera->obmat); 05857 invert_m4_m4(mat, camera->obmat); 05858 RE_SetView(re, mat); 05859 05860 for(base= FIRSTBASE; base; base= base->next) { 05861 if TESTBASELIB(v3d, base) { 05862 if(base->object->type==OB_MESH) { 05863 ob= base->object; 05864 05865 me= ob->data; 05866 mvert= me->mvert; 05867 if(me->msticky) 05868 CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert); 05869 me->msticky= CustomData_add_layer(&me->vdata, CD_MSTICKY, 05870 CD_CALLOC, NULL, me->totvert); 05871 05872 where_is_object(scene, ob); 05873 mult_m4_m4m4(mat, re->viewmat, ob->obmat); 05874 05875 ms= me->msticky; 05876 for(a=0; a<me->totvert; a++, ms++, mvert++) { 05877 copy_v3_v3(ho, mvert->co); 05878 mul_m4_v3(mat, ho); 05879 projectverto(ho, re->winmat, ho); 05880 ms->co[0]= ho[0]/ho[3]; 05881 ms->co[1]= ho[1]/ho[3]; 05882 } 05883 } 05884 } 05885 } 05886 } 05887