b2f7cdfca48230a20836ad0a24a5691272b3577a
[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  * blove/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 #if 0
78 /* proposal for more dynamic allocation of options for render vertices, so we dont
79    have to reserve this space inside vertices */
80 typedef struct VertTableNode {
81         VertRen *vert;
82         float *rad;
83         float *sticky;
84         float *strand;
85         float *tangent;
86         float *stress;
87 } VertTableNode;
88
89 #define RE_STICKY_ELEMS 3
90 float *RE_vertren_get_sticky(VertRen *ver, int verify)
91 {
92         float *sticky;
93         int a= ver->index>>8;
94         
95         sticky= R.blove[a].sticky;
96         if(sticky==NULL) {
97                 if(verify) 
98                         sticky= R.blove[a].sticky= MEM_mallocN(RE_STICKY_ELEMS*sizeof(float), "sticky table");
99                 else
100                         return NULL;
101         }
102         sticky+= (nr & 255)*RE_STICKY_ELEMS;
103 }
104 #endif
105
106 VertRen *RE_findOrAddVert(int nr)
107 {
108         VertRen *v, **temp;
109         static int rblovelen=TABLEINITSIZE;
110         int a;
111
112         if(nr<0) {
113                 printf("error in findOrAddVert: %d\n",nr);
114                 return R.blove[0];
115         }
116         a= nr>>8;
117         
118         if (a>=rblovelen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
119                 //printf("Allocating %i more vert groups.  %i total.\n", 
120                 //      TABLEINITSIZE, rblovelen+TABLEINITSIZE );
121                 temp=R.blove;
122                 R.blove=(VertRen**)MEM_callocN(sizeof(void*)*(rblovelen+TABLEINITSIZE) , "Blove");
123                 memcpy(R.blove, temp, rblovelen*sizeof(void*));
124                 memset(&(R.blove[rblovelen]), 0, TABLEINITSIZE*sizeof(void*));
125                 rblovelen+=TABLEINITSIZE; 
126                 MEM_freeN(temp);        
127         }
128         
129         v= R.blove[a];
130         if(v==0) {
131                 v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
132                 R.blove[a]= v;
133         }
134         v+= (nr & 255);
135         return v;
136 }
137
138 /* ------------------------------------------------------------------------ */
139 int rblohalen=TABLEINITSIZE;
140 HaloRen *RE_findOrAddHalo(int nr)
141 {
142         HaloRen *h, **temp;
143         int a;
144
145         if(nr<0) {
146                 printf("error in findOrAddHalo: %d\n",nr);
147                 return R.bloha[0];
148         }
149         a= nr>>8;
150         
151         if (a>=rblohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
152                 //printf("Allocating %i more halo groups.  %i total.\n", 
153                 //      TABLEINITSIZE, rblohalen+TABLEINITSIZE );
154                 temp=R.bloha;
155                 R.bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(rblohalen+TABLEINITSIZE) , "Bloha");
156                 memcpy(R.bloha, temp, rblohalen*sizeof(void*));
157                 memset(&(R.bloha[rblohalen]), 0, TABLEINITSIZE*sizeof(void*));
158                 rblohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
159                 MEM_freeN(temp);        
160         }
161         
162         h= R.bloha[a];
163         if(h==0) {
164                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
165                 R.bloha[a]= h;
166         }
167         h+= (nr & 255);
168         return h;
169 }
170
171 /* ------------------------------------------------------------------------ */
172
173 VlakRen *RE_findOrAddVlak(int nr)
174 {
175         VlakRen *v, **temp;
176         static int rblovllen=TABLEINITSIZE;
177         int a;
178
179         if(nr<0) {
180                 printf("error in findOrAddVlak: %d\n",nr);
181                 return R.blovl[0];
182         }
183         a= nr>>8;
184         
185         if (a>=rblovllen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
186                 // printf("Allocating %i more face groups.  %i total.\n", 
187                 //      TABLEINITSIZE, rblovllen+TABLEINITSIZE );
188                 temp=R.blovl;
189                 R.blovl=(VlakRen**)MEM_callocN(sizeof(void*)*(rblovllen+TABLEINITSIZE) , "Blovl");
190                 memcpy(R.blovl, temp, rblovllen*sizeof(void*));
191                 memset(&(R.blovl[rblovllen]), 0, TABLEINITSIZE*sizeof(void*));
192                 rblovllen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
193                 MEM_freeN(temp);        
194         }
195         
196         v= R.blovl[a];
197         
198         if(v==0) {
199                 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
200                 R.blovl[a]= v;
201         }
202         v+= (nr & 255);
203         return v;
204 }
205
206 /* ------------------------------------------------------------------------- */
207
208 HaloRen *RE_inithalo(Material *ma,   float *vec,   float *vec1, 
209                                   float *orco,   float hasize,   float vectsize, int seed)
210 {
211         HaloRen *har;
212         MTex *mtex;
213         float tin, tr, tg, tb, ta;
214         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
215
216         if(hasize==0.0) return NULL;
217
218         RE_projectverto(vec, hoco);
219         if(hoco[3]==0.0) return NULL;
220         if(vec1) {
221                 RE_projectverto(vec1, hoco1);
222                 if(hoco1[3]==0.0) return NULL;
223         }
224
225         har= RE_findOrAddHalo(R.tothalo++);
226         VECCOPY(har->co, vec);
227         har->hasize= hasize;
228
229         /* projectvert is done in function 'zbufvlaggen' because of parts/border/pano */
230
231         /* halovect */
232         if(vec1) {
233
234                 har->type |= HA_VECT;
235
236                 zn= hoco[3];
237                 har->xs= 0.5*R.rectx*(hoco[0]/zn);
238                 har->ys= 0.5*R.recty*(hoco[1]/zn);
239                 har->zs= 0x7FFFFF*(hoco[2]/zn);
240
241                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
242
243                 xn=  har->xs - 0.5*R.rectx*(hoco1[0]/hoco1[3]);
244                 yn=  har->ys - 0.5*R.recty*(hoco1[1]/hoco1[3]);
245                 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
246                 else zn= atan2(yn, xn);
247
248                 har->sin= sin(zn);
249                 har->cos= cos(zn);
250                 zn= VecLenf(vec1, vec);
251
252                 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
253                 
254                 VecSubf(har->no, vec, vec1);
255                 Normalise(har->no);
256         }
257
258         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
259
260         har->alfa= ma->alpha;
261         har->r= ma->r;
262         har->g= ma->g;
263         har->b= ma->b;
264         har->add= (255.0*ma->add);
265         har->mat= ma;
266         har->hard= ma->har;
267         har->seed= seed % 256;
268
269         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
270         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
271         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
272         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
273
274
275         if(ma->mtex[0]) {
276
277                 if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
278                 else {
279
280                         mtex= ma->mtex[0];
281                         VECCOPY(texvec, vec);
282
283                         if(mtex->texco & TEXCO_NORM) {
284                                 ;
285                         }
286                         else if(mtex->texco & TEXCO_OBJECT) {
287                                 /* texvec[0]+= imatbase->ivec[0]; */
288                                 /* texvec[1]+= imatbase->ivec[1]; */
289                                 /* texvec[2]+= imatbase->ivec[2]; */
290                                 /* Mat3MulVecfl(imatbase->imat, texvec); */
291                         }
292                         else {
293                                 if(orco) {
294                                         VECCOPY(texvec, orco);
295                                 }
296                         }
297
298                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
299
300                         yn= tin*mtex->colfac;
301                         zn= tin*mtex->varfac;
302
303                         if(mtex->mapto & MAP_COL) {
304                                 zn= 1.0-yn;
305                                 har->r= (yn*tr+ zn*ma->r);
306                                 har->g= (yn*tg+ zn*ma->g);
307                                 har->b= (yn*tb+ zn*ma->b);
308                         }
309                         if(mtex->texco & 16) {
310                                 har->alfa= tin;
311                         }
312                 }
313         }
314
315         return har;
316 }
317 /* ------------------------------------------------------------------------- */