New feature: "Stress" texture input channel
[blender-staging.git] / source / blender / render / intern / source / renderdatabase.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * Storage, retrieval and query of render specific data.
32  */
33
34 /*
35  * All data from a Blender scene is converter by the renderconverter/
36  * into a special format that is used by the render module to make
37  * images out of. These functions interface to the render-specific
38  * database.  
39  *
40  * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
41  * entries each.
42  *
43  * The index of an entry is >>8 (the highest 24 * bits), to find an
44  * offset in a 256-entry block.
45  *
46  * - If the 256-entry block entry has an entry in the
47  * vertnodes/bloha/blovl array of the current block, the i-th entry in
48  * that block is allocated to this entry.
49  *
50  * - If the entry has no block allocated for it yet, memory is
51  * allocated.
52  *
53  * The pointer to the correct entry is returned. Memory is guarateed
54  * to exist (as long as the malloc does not break). Since guarded
55  * allocation is used, memory _must_ be available. Otherwise, an
56  * exit(0) would occur.
57  * 
58  */
59
60 #include <math.h>
61 #include <string.h>
62
63 #include "MEM_guardedalloc.h"
64 #include "BKE_utildefines.h"
65 #include "BLI_arithb.h"
66
67 #include "DNA_material_types.h" 
68 #include "DNA_mesh_types.h" 
69 #include "DNA_texture_types.h" 
70
71 #include "BKE_texture.h" 
72
73 #include "render.h"
74
75 /* ------------------------------------------------------------------------- */
76
77
78 /* More dynamic allocation of options for render vertices, so we dont
79    have to reserve this space inside vertices.
80    Important; vertices should have been created already (to get tables checked) 
81    that's a reason why the calls demand VertRen * as arg, not the index */
82
83 /* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */
84
85 #define RE_STICKY_ELEMS         2
86 #define RE_STRESS_ELEMS         1
87 #define RE_RAD_ELEMS            4
88 #define RE_STRAND_ELEMS         1
89 #define RE_TANGENT_ELEMS        3
90 #define RE_STRESS_ELEMS         1
91
92 /* render allocates totvert/256 of these nodes, for lookup and quick alloc */
93 typedef struct VertTableNode {
94         struct VertRen *vert;
95         float *rad;
96         float *sticky;
97         float *strand;
98         float *tangent;
99         float *stress;
100 } VertTableNode;
101
102 float *RE_vertren_get_sticky(VertRen *ver, int verify)
103 {
104         float *sticky;
105         int nr= ver->index>>8;
106         
107         sticky= R.vertnodes[nr].sticky;
108         if(sticky==NULL) {
109                 if(verify) 
110                         sticky= R.vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
111                 else
112                         return NULL;
113         }
114         return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
115 }
116
117 float *RE_vertren_get_stress(VertRen *ver, int verify)
118 {
119         float *stress;
120         int nr= ver->index>>8;
121         
122         stress= R.vertnodes[nr].stress;
123         if(stress==NULL) {
124                 if(verify) 
125                         stress= R.vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
126                 else
127                         return NULL;
128         }
129         return stress + (ver->index & 255)*RE_STRESS_ELEMS;
130 }
131
132 /* this one callocs! */
133 float *RE_vertren_get_rad(VertRen *ver, int verify)
134 {
135         float *rad;
136         int nr= ver->index>>8;
137         
138         rad= R.vertnodes[nr].rad;
139         if(rad==NULL) {
140                 if(verify) 
141                         rad= R.vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
142                 else
143                         return NULL;
144         }
145         return rad + (ver->index & 255)*RE_RAD_ELEMS;
146 }
147
148 float *RE_vertren_get_strand(VertRen *ver, int verify)
149 {
150         float *strand;
151         int nr= ver->index>>8;
152         
153         strand= R.vertnodes[nr].strand;
154         if(strand==NULL) {
155                 if(verify) 
156                         strand= R.vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
157                 else
158                         return NULL;
159         }
160         return strand + (ver->index & 255)*RE_STRAND_ELEMS;
161 }
162
163 float *RE_vertren_get_tangent(VertRen *ver, int verify)
164 {
165         float *tangent;
166         int nr= ver->index>>8;
167         
168         tangent= R.vertnodes[nr].tangent;
169         if(tangent==NULL) {
170                 if(verify) 
171                         tangent= R.vertnodes[nr].tangent= MEM_mallocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
172                 else
173                         return NULL;
174         }
175         return tangent + (ver->index & 255)*RE_TANGENT_ELEMS;
176 }
177
178
179 VertRen *RE_findOrAddVert(int nr)
180 {
181         VertTableNode *temp;
182         VertRen *v;
183         static int rvertnodeslen=TABLEINITSIZE;
184         int a;
185
186         if(nr<0) {
187                 printf("error in findOrAddVert: %d\n",nr);
188                 return R.vertnodes[0].vert;
189         }
190         a= nr>>8;
191         
192         if (a>=rvertnodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
193                 temp= R.vertnodes;
194                 
195                 R.vertnodes= MEM_mallocN(sizeof(VertTableNode)*(rvertnodeslen+TABLEINITSIZE) , "vertnodes");
196                 memcpy(R.vertnodes, temp, rvertnodeslen*sizeof(VertTableNode));
197                 memset(R.vertnodes+rvertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
198                 
199                 rvertnodeslen+=TABLEINITSIZE; 
200                 MEM_freeN(temp);        
201         }
202         
203         v= R.vertnodes[a].vert;
204         if(v==NULL) {
205                 int i;
206                 
207                 v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
208                 R.vertnodes[a].vert= v;
209                 
210                 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) {
211                         v[a].index= i;
212                 }
213         }
214         v+= (nr & 255);
215         return v;
216 }
217
218 void RE_free_vertex_tables(void)
219 {
220         int a=0;
221         
222         while(R.vertnodes[a].vert) {
223                 if(R.vertnodes[a].vert) {
224                         MEM_freeN(R.vertnodes[a].vert);
225                         R.vertnodes[a].vert= NULL;
226
227                         if(R.vertnodes[a].rad) {
228                                 MEM_freeN(R.vertnodes[a].rad);
229                                 R.vertnodes[a].rad= NULL;
230                         }
231                         if(R.vertnodes[a].sticky) {
232                                 MEM_freeN(R.vertnodes[a].sticky);
233                                 R.vertnodes[a].sticky= NULL;
234                         }
235                         if(R.vertnodes[a].strand) {
236                                 MEM_freeN(R.vertnodes[a].strand);
237                                 R.vertnodes[a].strand= NULL;
238                         }
239                         if(R.vertnodes[a].tangent) {
240                                 MEM_freeN(R.vertnodes[a].tangent);
241                                 R.vertnodes[a].tangent= NULL;
242                         }
243                         if(R.vertnodes[a].stress) {
244                                 MEM_freeN(R.vertnodes[a].stress);
245                                 R.vertnodes[a].stress= NULL;
246                         }
247                 }
248                 a++;
249         }
250 }
251
252 /* only once, on startup */
253 void RE_init_vertex_tables(void)
254 {
255         R.vertnodes= MEM_callocN(sizeof(VertTableNode)*TABLEINITSIZE , "vertnodes");
256 }
257
258 /* ------------------------------------------------------------------------ */
259 int rblohalen=TABLEINITSIZE;
260 HaloRen *RE_findOrAddHalo(int nr)
261 {
262         HaloRen *h, **temp;
263         int a;
264
265         if(nr<0) {
266                 printf("error in findOrAddHalo: %d\n",nr);
267                 return R.bloha[0];
268         }
269         a= nr>>8;
270         
271         if (a>=rblohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
272                 //printf("Allocating %i more halo groups.  %i total.\n", 
273                 //      TABLEINITSIZE, rblohalen+TABLEINITSIZE );
274                 temp=R.bloha;
275                 R.bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(rblohalen+TABLEINITSIZE) , "Bloha");
276                 memcpy(R.bloha, temp, rblohalen*sizeof(void*));
277                 memset(&(R.bloha[rblohalen]), 0, TABLEINITSIZE*sizeof(void*));
278                 rblohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
279                 MEM_freeN(temp);        
280         }
281         
282         h= R.bloha[a];
283         if(h==0) {
284                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
285                 R.bloha[a]= h;
286         }
287         h+= (nr & 255);
288         return h;
289 }
290
291 /* ------------------------------------------------------------------------ */
292
293 VlakRen *RE_findOrAddVlak(int nr)
294 {
295         VlakRen *v, **temp;
296         static int rblovllen=TABLEINITSIZE;
297         int a;
298
299         if(nr<0) {
300                 printf("error in findOrAddVlak: %d\n",nr);
301                 return R.blovl[0];
302         }
303         a= nr>>8;
304         
305         if (a>=rblovllen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
306                 // printf("Allocating %i more face groups.  %i total.\n", 
307                 //      TABLEINITSIZE, rblovllen+TABLEINITSIZE );
308                 temp=R.blovl;
309                 R.blovl=(VlakRen**)MEM_callocN(sizeof(void*)*(rblovllen+TABLEINITSIZE) , "Blovl");
310                 memcpy(R.blovl, temp, rblovllen*sizeof(void*));
311                 memset(&(R.blovl[rblovllen]), 0, TABLEINITSIZE*sizeof(void*));
312                 rblovllen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
313                 MEM_freeN(temp);        
314         }
315         
316         v= R.blovl[a];
317         
318         if(v==0) {
319                 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
320                 R.blovl[a]= v;
321         }
322         v+= (nr & 255);
323         return v;
324 }
325
326 /* ------------------------------------------------------------------------- */
327
328 HaloRen *RE_inithalo(Material *ma,   float *vec,   float *vec1, 
329                                   float *orco,   float hasize,   float vectsize, int seed)
330 {
331         HaloRen *har;
332         MTex *mtex;
333         float tin, tr, tg, tb, ta;
334         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
335
336         if(hasize==0.0) return NULL;
337
338         RE_projectverto(vec, hoco);
339         if(hoco[3]==0.0) return NULL;
340         if(vec1) {
341                 RE_projectverto(vec1, hoco1);
342                 if(hoco1[3]==0.0) return NULL;
343         }
344
345         har= RE_findOrAddHalo(R.tothalo++);
346         VECCOPY(har->co, vec);
347         har->hasize= hasize;
348
349         /* projectvert is done in function 'zbufvlaggen' because of parts/border/pano */
350
351         /* halovect */
352         if(vec1) {
353
354                 har->type |= HA_VECT;
355
356                 zn= hoco[3];
357                 har->xs= 0.5*R.rectx*(hoco[0]/zn);
358                 har->ys= 0.5*R.recty*(hoco[1]/zn);
359                 har->zs= 0x7FFFFF*(hoco[2]/zn);
360
361                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
362
363                 xn=  har->xs - 0.5*R.rectx*(hoco1[0]/hoco1[3]);
364                 yn=  har->ys - 0.5*R.recty*(hoco1[1]/hoco1[3]);
365                 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
366                 else zn= atan2(yn, xn);
367
368                 har->sin= sin(zn);
369                 har->cos= cos(zn);
370                 zn= VecLenf(vec1, vec);
371
372                 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
373                 
374                 VecSubf(har->no, vec, vec1);
375                 Normalise(har->no);
376         }
377
378         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
379
380         har->alfa= ma->alpha;
381         har->r= ma->r;
382         har->g= ma->g;
383         har->b= ma->b;
384         har->add= (255.0*ma->add);
385         har->mat= ma;
386         har->hard= ma->har;
387         har->seed= seed % 256;
388
389         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
390         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
391         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
392         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
393
394
395         if(ma->mtex[0]) {
396
397                 if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
398                 else {
399
400                         mtex= ma->mtex[0];
401                         VECCOPY(texvec, vec);
402
403                         if(mtex->texco & TEXCO_NORM) {
404                                 ;
405                         }
406                         else if(mtex->texco & TEXCO_OBJECT) {
407                                 /* texvec[0]+= imatbase->ivec[0]; */
408                                 /* texvec[1]+= imatbase->ivec[1]; */
409                                 /* texvec[2]+= imatbase->ivec[2]; */
410                                 /* Mat3MulVecfl(imatbase->imat, texvec); */
411                         }
412                         else {
413                                 if(orco) {
414                                         VECCOPY(texvec, orco);
415                                 }
416                         }
417
418                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
419
420                         yn= tin*mtex->colfac;
421                         zn= tin*mtex->varfac;
422
423                         if(mtex->mapto & MAP_COL) {
424                                 zn= 1.0-yn;
425                                 har->r= (yn*tr+ zn*ma->r);
426                                 har->g= (yn*tg+ zn*ma->g);
427                                 har->b= (yn*tb+ zn*ma->b);
428                         }
429                         if(mtex->texco & 16) {
430                                 har->alfa= tin;
431                         }
432                 }
433         }
434
435         return har;
436 }
437 /* ------------------------------------------------------------------------- */