Blender V2.61 - r43446

convertblender.c

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