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