Fixed a stupid bug when exporting meshes with empty material slots.
[blender.git] / source / blender / render / intern / source / renderHelp.c
1 /**  
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  * Some helpful conversions/functions.
31  *
32  * $Id$
33  */
34
35 #include <math.h>
36 #include <limits.h>
37 #include <stdlib.h>
38
39 #include "DNA_mesh_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "BKE_utildefines.h"
42 #include "BLI_arithb.h"
43
44 #include "render.h" 
45 #include "renderHelp.h"
46 #include "zbuf.h"
47
48 static float panovco, panovsi;
49 static float panophi=0.0;
50 static float tempPanoPhi;
51
52 static int panotestclip(float *v);
53
54 void pushTempPanoPhi(float p) {
55         tempPanoPhi = panophi;
56         panophi = p;
57 }
58
59 void popTempPanoPhi() {
60         panophi = tempPanoPhi;
61 }
62
63 float getPanoPhi(){
64         return panophi;
65 }
66 float getPanovCo(){
67         return panovco;
68 }
69 float getPanovSi(){
70         return panovsi;
71 }
72
73 void setPanoRot(int part)
74 {
75 /*      extern float panovco, panovsi; */
76         static float alpha= 1.0;
77
78         /* part==0 init all */
79
80         if(part==0) {
81
82                 alpha= ((float)R.r.xsch)/R.viewfac;
83                 alpha= 2.0*atan(alpha/2.0);
84         }
85
86
87         /* rotate it all around the y-as with phi degrees */
88
89         panophi= -0.5*(R.r.xparts-1)*alpha + part*alpha;
90
91         panovsi= sin(-panophi);
92         panovco= cos(-panophi);
93
94 }
95
96
97
98
99 static int panotestclip(float *v)
100 {
101         /* to be used for halos en infos */
102         float abs4;
103         short c=0;
104
105         if((R.r.mode & R_PANORAMA)==0) return RE_testclip(v);
106
107         abs4= fabs(v[3]);
108
109         if(v[2]< -abs4) c=16;           /* this used to be " if(v[2]<0) ", see clippz() */
110         else if(v[2]> abs4) c+= 32;
111
112         if( v[1]>abs4) c+=4;
113         else if( v[1]< -abs4) c+=8;
114
115         abs4*= R.r.xparts;
116         if( v[0]>abs4) c+=2;
117         else if( v[0]< -abs4) c+=1;
118
119         return c;
120 }
121
122 /*
123
124   This adds the hcs coordinates to vertices. It iterates over all
125   vertices, halos and faces. After the conversion, we clip in hcs.
126
127   Elsewhere, all primites are converted to vertices. 
128   Called in 
129   - envmapping (envmap.c)
130   - shadow buffering (shadbuf.c)
131   - preparation for rendering (renderPreAndPost.c) 
132
133 */
134
135 /* move to renderer */
136 void setzbufvlaggen( void (*projectfunc)(float *, float *) )
137 /* homocos too */
138 {
139         VlakRen *vlr = NULL;
140         VertRen *ver = NULL;
141         HaloRen *har = NULL;
142         float zn, vec[3], si, co, hoco[4];
143         int a;
144         float panophi = 0.0;
145         
146         panophi = getPanoPhi();
147         si= sin(panophi);
148         co= cos(panophi);
149
150    /* calculate view coordinates (and zbuffer value) */
151         for(a=0; a< R.totvert;a++) {
152                 if((a & 255)==0) ver= R.blove[a>>8];
153                 else ver++;
154
155                 if(R.r.mode & R_PANORAMA) {
156                         vec[0]= co*ver->co[0] + si*ver->co[2];
157                         vec[1]= ver->co[1];
158                         vec[2]= -si*ver->co[0] + co*ver->co[2];
159                 }
160                 else {
161                         VECCOPY(vec, ver->co);
162                 }
163                 /* Go from wcs to hcs ... */
164                 projectfunc(vec, ver->ho);
165                 /* ... and clip in that system. */
166                 ver->clip = RE_testclip(ver->ho);
167                 /* 
168                    Because all other ops are performed in other systems, this is 
169                    the only thing that has to be done.
170                 */
171         }
172
173    /* calculate view coordinates (and zbuffer value) */
174         for(a=0; a<R.tothalo; a++) {
175                 if((a & 255)==0) har= R.bloha[a>>8];
176                 else har++;
177
178                 if(R.r.mode & R_PANORAMA) {
179                         vec[0]= co*har->co[0] + si*har->co[2];
180                         vec[1]= har->co[1];
181                         vec[2]= -si*har->co[0] + co*har->co[2];
182                 }
183                 else {
184                         VECCOPY(vec, har->co);
185                 }
186
187                 projectfunc(vec, hoco);
188                 
189                 /* we clip halos less critical, but not for the Z */
190                 hoco[0]*= 0.5;
191                 hoco[1]*= 0.5;
192                 
193                 if( panotestclip(hoco) ) {
194                         har->miny= har->maxy= -10000;   /* that way render clips it */
195                 }
196                 else if(hoco[3]<0.0) {
197                         har->miny= har->maxy= -10000;   /* render clips it */
198                 }
199                 else /* do the projection...*/
200                 {
201                         /* bring back hocos */
202                         hoco[0]*= 2.0;
203                         hoco[1]*= 2.0;
204                         
205                         zn= hoco[3];
206                         har->xs= 0.5*R.rectx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
207                         har->ys= 0.5*R.recty*(1.0+hoco[1]/zn);
208                 
209                         /* this should be the zbuffer coordinate */
210                         har->zs= 0x7FFFFF*(hoco[2]/zn);
211                         /* taking this from the face clip functions? seems ok... */
212                         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
213                         
214                         vec[0]+= har->hasize;
215                         projectfunc(vec, hoco);
216                         vec[0]-= har->hasize;
217                         zn= hoco[3];
218                         har->rad= fabs(har->xs- 0.5*R.rectx*(1.0+hoco[0]/zn));
219                 
220                         /* this clip is not really OK, to prevent stars to become too large */
221                         if(har->type & HA_ONLYSKY) {
222                                 if(har->rad>3.0) har->rad= 3.0;
223                         }
224                 
225                         har->radsq= har->rad*har->rad;
226                 
227                         har->miny= har->ys - har->rad/R.ycor;
228                         har->maxy= har->ys + har->rad/R.ycor;
229                 
230                         /* the Zd value is still not really correct for pano */
231                 
232                         vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
233                         projectfunc(vec, hoco);
234                         zn= hoco[3];
235                         zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
236                         har->zd= CLAMPIS(zn, 0, INT_MAX);
237                 
238                 }
239                 
240         }
241
242         /* set flags at 0 if clipped away */
243         for(a=0; a<R.totvlak; a++) {
244                 if((a & 255)==0) vlr= R.blovl[a>>8];
245                 else vlr++;
246
247                         vlr->flag |= R_VISIBLE;
248                         if(vlr->v4) {
249                                 if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE;
250                         }
251                         else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE;
252
253                 }
254
255 }
256
257 /* ------------------------------------------------------------------------- */
258 /* move to renderer */
259
260 void set_normalflags(void)
261 {
262         VlakRen *vlr = NULL;
263         float *v1, xn, yn, zn;
264         int a1, doflip;
265         
266         /* switch normal 'snproj' values (define which axis is the optimal one for calculations) */
267         for(a1=0; a1<R.totvlak; a1++) {
268                 if((a1 & 255)==0) vlr= R.blovl[a1>>8];
269                 else vlr++;
270                 
271                 /* abuse of this flag... this is code that just sets face normal in direction of camera */
272                 /* that convention we should get rid of */
273                 if((vlr->flag & R_NOPUNOFLIP)==0) {
274                         
275                         doflip= 0;
276                         if(R.r.mode & R_ORTHO) {
277                                 if(vlr->n[2]>0.0) doflip= 1;
278                         }
279                         else {
280                                 v1= vlr->v1->co;
281                                 if( (v1[0]*vlr->n[0] +v1[1]*vlr->n[1] +v1[2]*vlr->n[2])<0.0 ) doflip= 1;
282                         }
283                         if(doflip) {
284                                 vlr->n[0]= -vlr->n[0];
285                                 vlr->n[1]= -vlr->n[1];
286                                 vlr->n[2]= -vlr->n[2];
287                         }
288                 }
289                 
290                 /* recalculate puno. Displace & flipped matrices can screw up */
291                 vlr->puno= 0;
292                 if(!(vlr->flag & R_TANGENT)) {
293                         if( Inpf(vlr->n, vlr->v1->n) < 0.0 ) vlr->puno |= ME_FLIPV1;
294                         if( Inpf(vlr->n, vlr->v2->n) < 0.0 ) vlr->puno |= ME_FLIPV2;
295                         if( Inpf(vlr->n, vlr->v3->n) < 0.0 ) vlr->puno |= ME_FLIPV3;
296                         if(vlr->v4 && Inpf(vlr->n, vlr->v4->n) < 0.0 ) vlr->puno |= ME_FLIPV4;
297                 }                               
298                 xn= fabs(vlr->n[0]);
299                 yn= fabs(vlr->n[1]);
300                 zn= fabs(vlr->n[2]);
301                 if(zn>=xn && zn>=yn) vlr->snproj= 0;
302                 else if(yn>=xn && yn>=zn) vlr->snproj= 1;
303                 else vlr->snproj= 2;
304
305         }
306 }