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