532c55da9975ecf8a31257e440de0054bfae275f
[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 "BLI_arithb.h"
41
42 #include "render.h" 
43 #include "render_intern.h"
44 #include "renderHelp.h"
45 #include "zbuf.h"
46
47 #ifdef HAVE_CONFIG_H
48 #include <config.h>
49 #endif
50
51 static float panovco, panovsi;
52 static float panophi=0.0;
53 static float tempPanoPhi;
54
55 static int panotestclip(float *v);
56
57 void pushTempPanoPhi(float p) {
58         tempPanoPhi = panophi;
59         panophi = p;
60 }
61
62 void popTempPanoPhi() {
63         panophi = tempPanoPhi;
64 }
65
66 float getPanoPhi(){
67         return panophi;
68 }
69 float getPanovCo(){
70         return panovco;
71 }
72 float getPanovSi(){
73         return panovsi;
74 }
75
76 void setPanoRot(int part)
77 {
78 /*      extern float panovco, panovsi; */
79         static float alpha= 1.0;
80
81         /* part==0 init all */
82
83         if(part==0) {
84
85                 alpha= ((float)R.r.xsch)/R.viewfac;
86                 alpha= 2.0*atan(alpha/2.0);
87         }
88
89
90         /* rotate it all around the y-as with phi degrees */
91
92         panophi= -0.5*(R.r.xparts-1)*alpha + part*alpha;
93
94         panovsi= sin(-panophi);
95         panovco= cos(-panophi);
96
97 }
98
99
100
101
102 static int panotestclip(float *v)
103 {
104         /* to be used for halos en infos */
105         float abs4;
106         short c=0;
107
108         if((R.r.mode & R_PANORAMA)==0) return RE_testclip(v);
109
110         abs4= fabs(v[3]);
111
112         if(v[2]< -abs4) c=16;           /* this used to be " if(v[2]<0) ", see clippz() */
113         else if(v[2]> abs4) c+= 32;
114
115         if( v[1]>abs4) c+=4;
116         else if( v[1]< -abs4) c+=8;
117
118         abs4*= R.r.xparts;
119         if( v[0]>abs4) c+=2;
120         else if( v[0]< -abs4) c+=1;
121
122         return c;
123 }
124
125 /*
126
127   This adds the hcs coordinates to vertices. It iterates over all
128   vertices, halos and faces. After the conversion, we clip in hcs.
129
130   Elsewhere, all primites are converted to vertices. 
131   Called in 
132   - envmapping (envmap.c)
133   - shadow buffering (shadbuf.c)
134   - preparation for rendering (renderPreAndPost.c) 
135
136 */
137
138 /* move to renderer */
139 void setzbufvlaggen( void (*projectfunc)(float *, float *) )
140 /* homocos too */
141 {
142         VlakRen *vlr = NULL;
143         VertRen *ver = NULL;
144         HaloRen *har = NULL;
145         float zn, vec[3], si, co, hoco[4];
146         int a;
147         float panophi = 0.0;
148         
149         panophi = getPanoPhi();
150         si= sin(panophi);
151         co= cos(panophi);
152
153    /* calculate view coordinates (and zbuffer value) */
154         for(a=0; a< R.totvert;a++) {
155                 if((a & 255)==0) ver= R.blove[a>>8];
156                 else ver++;
157
158                 if(R.r.mode & R_PANORAMA) {
159                         vec[0]= co*ver->co[0] + si*ver->co[2];
160                         vec[1]= ver->co[1];
161                         vec[2]= -si*ver->co[0] + co*ver->co[2];
162                 }
163                 else {
164                         VECCOPY(vec, ver->co);
165                 }
166                 /* Go from wcs to hcs ... */
167                 projectfunc(vec, ver->ho);
168                 /* ... and clip in that system. */
169                 ver->clip = RE_testclip(ver->ho);
170                 /* 
171                    Because all other ops are performed in other systems, this is 
172                    the only thing that has to be done.
173                 */
174         }
175
176    /* calculate view coordinates (and zbuffer value) */
177         for(a=0; a<R.tothalo; a++) {
178                 if((a & 255)==0) har= R.bloha[a>>8];
179                 else har++;
180
181                 if(R.r.mode & R_PANORAMA) {
182                         vec[0]= co*har->co[0] + si*har->co[2];
183                         vec[1]= har->co[1];
184                         vec[2]= -si*har->co[0] + co*har->co[2];
185                 }
186                 else {
187                         VECCOPY(vec, har->co);
188                 }
189
190                 projectfunc(vec, hoco);
191
192                 hoco[3]*= 2.0;
193
194                 if( panotestclip(hoco) ) {
195                         har->miny= har->maxy= -10000;   /* that way render clips it */
196                 }
197                 else if(hoco[3]<0.0) {
198                         har->miny= har->maxy= -10000;   /* render clips it */
199                 }
200                 else /* do the projection...*/
201                 {
202                         zn= hoco[3]/2.0;
203                         har->xs= 0.5*R.rectx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
204                         har->ys= 0.5*R.recty*(1.0+hoco[1]/zn);
205                 
206                         /* this should be the zbuffer coordinate */
207                         har->zs= 0x7FFFFF*(1.0+hoco[2]/zn);
208                         /* taking this from the face clip functions? seems ok... */
209                         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
210                         vec[0]+= har->hasize;
211                         projectfunc(vec, hoco);
212                         vec[0]-= har->hasize;
213                         zn= hoco[3];
214                         har->rad= fabs(har->xs- 0.5*R.rectx*(1.0+hoco[0]/zn));
215                 
216                         /* this clip is not really OK, to prevent stars to become too large */
217                         if(har->type & HA_ONLYSKY) {
218                                 if(har->rad>3.0) har->rad= 3.0;
219                         }
220                 
221                         har->radsq= har->rad*har->rad;
222                 
223                         har->miny= har->ys - har->rad/R.ycor;
224                         har->maxy= har->ys + har->rad/R.ycor;
225                 
226                         /* the Zd value is still not really correct for pano */
227                 
228                         vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
229                         projectfunc(vec, hoco);
230                         zn= hoco[3];
231                         zn= fabs(har->zs - 0x7FFFFF*(1.0+hoco[2]/zn));
232                         har->zd= CLAMPIS(zn, 0, INT_MAX);
233                 
234                         /* if( har->zs < 2*har->zd) { */
235                         /* PRINT2(d, d, har->zs, har->zd); */
236                         /* har->alfa= har->mat->alpha * ((float)(har->zs))/(float)(2*har->zd); */
237                         /* } */
238                 
239                 }
240                 
241         }
242
243         /* set flags at 0 if clipped away */
244         for(a=0; a<R.totvlak; a++) {
245                 if((a & 255)==0) vlr= R.blovl[a>>8];
246                 else vlr++;
247
248                         vlr->flag |= R_VISIBLE;
249                         if(vlr->v4) {
250                                 if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE;
251                         }
252                         else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE;
253
254                 }
255
256 }
257
258 /* ------------------------------------------------------------------------- */
259 /* move to renderer */
260
261 void set_normalflags(void)
262 {
263         VlakRen *vlr = NULL;
264         float vec[3], xn, yn, zn;
265         int a1;
266         
267         /* switch normal 'snproj' values (define which axis is the optimal one for calculations) */
268         for(a1=0; a1<R.totvlak; a1++) {
269                 if((a1 & 255)==0) vlr= R.blovl[a1>>8];
270                 else vlr++;
271                 
272                 /* abuse of this flag... this is code that just sets face normal in direction of camera */
273                 /* that convention we should get rid of */
274                 if((vlr->flag & R_NOPUNOFLIP)==0) {
275
276                         vec[0]= vlr->v1->co[0];
277                         vec[1]= vlr->v1->co[1];
278                         vec[2]= vlr->v1->co[2];
279                         
280                         if( (vec[0]*vlr->n[0] +vec[1]*vlr->n[1] +vec[2]*vlr->n[2])<0.0 ) {
281                                 vlr->n[0]= -vlr->n[0];
282                                 vlr->n[1]= -vlr->n[1];
283                                 vlr->n[2]= -vlr->n[2];
284                         }
285                 }
286                 
287                 /* recalculate puno. Displace & flipped matrices can screw up */
288                 vlr->puno= 0;
289                 if( Inpf(vlr->n, vlr->v1->n) < 0.0 ) vlr->puno |= ME_FLIPV1;
290                 if( Inpf(vlr->n, vlr->v2->n) < 0.0 ) vlr->puno |= ME_FLIPV2;
291                 if( Inpf(vlr->n, vlr->v3->n) < 0.0 ) vlr->puno |= ME_FLIPV3;
292                 if(vlr->v4 && Inpf(vlr->n, vlr->v4->n) < 0.0 ) vlr->puno |= ME_FLIPV4;
293                                 
294                 xn= fabs(vlr->n[0]);
295                 yn= fabs(vlr->n[1]);
296                 zn= fabs(vlr->n[2]);
297                 if(zn>=xn && zn>=yn) vlr->snproj= 0;
298                 else if(yn>=xn && yn>=zn) vlr->snproj= 1;
299                 else vlr->snproj= 2;
300
301         }
302 }