]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/prtview/portals.cpp
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / contrib / prtview / portals.cpp
1 /*\r
2 PrtView plugin for GtkRadiant\r
3 Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com\r
4 \r
5 This library is free software; you can redistribute it and/or\r
6 modify it under the terms of the GNU Lesser General Public\r
7 License as published by the Free Software Foundation; either\r
8 version 2.1 of the License, or (at your option) any later version.\r
9 \r
10 This library is distributed in the hope that it will be useful,\r
11 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
13 Lesser General Public License for more details.\r
14 \r
15 You should have received a copy of the GNU Lesser General Public\r
16 License along with this library; if not, write to the Free Software\r
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
18 */\r
19 \r
20 #include "stdafx.h"\r
21 #include <string.h>\r
22 #include <stdlib.h>\r
23 #ifndef __APPLE__\r
24 #include <search.h>\r
25 #endif\r
26 #include <stdio.h>\r
27 \r
28 #define LINE_BUF 1000\r
29 \r
30 CPortals portals;\r
31 CPortalsRender render;\r
32 \r
33 int compare( const void *arg1, const void *arg2 )\r
34 {\r
35 \r
36         if(portals.portal[*((int *)arg1)].dist > portals.portal[*((int *)arg2)].dist)\r
37                 return -1;\r
38         else if(portals.portal[*((int *)arg1)].dist < portals.portal[*((int *)arg2)].dist)\r
39                 return 1;\r
40 \r
41         return 0;\r
42 }\r
43 \r
44 \r
45 CBspPortal::CBspPortal()\r
46 {\r
47         memset(this, 0, sizeof(CBspPortal));\r
48 }\r
49 \r
50 CBspPortal::~CBspPortal()\r
51 {\r
52         delete[] point;\r
53         delete[] inner_point;\r
54 }\r
55 \r
56 qboolean CBspPortal::Build(char *def)\r
57 {\r
58         char *c = def;\r
59         unsigned int n;\r
60         int dummy1, dummy2;\r
61         int res_cnt, i;\r
62 \r
63         if(portals.hint_flags)\r
64         {\r
65                 res_cnt = sscanf(def, "%u %d %d %d", &point_count, &dummy1, &dummy2, (int *)&hint);\r
66         }\r
67         else\r
68         {\r
69                 sscanf(def, "%u", &point_count);\r
70                 hint = FALSE;\r
71         }\r
72 \r
73         if(point_count < 3 || (portals.hint_flags && res_cnt < 4))\r
74                 return FALSE;\r
75 \r
76         point = new CBspPoint[point_count];\r
77         inner_point = new CBspPoint[point_count];\r
78 \r
79         for(n = 0; n < point_count; n++)\r
80         {\r
81                 for(; *c != 0 && *c != '('; c++);\r
82 \r
83                 if(*c == 0)\r
84                         return FALSE;\r
85 \r
86                 c++;\r
87 \r
88                 sscanf(c, "%f %f %f", point[n].p, point[n].p+1, point[n].p+2);\r
89 \r
90                 center.p[0] += point[n].p[0];\r
91                 center.p[1] += point[n].p[1];\r
92                 center.p[2] += point[n].p[2];\r
93 \r
94                 if(n == 0)\r
95                 {\r
96                         for(i = 0; i < 3; i++)\r
97                         {\r
98                                 min[i] = point[n].p[i];\r
99                                 max[i] = point[n].p[i];\r
100                         }\r
101                 }\r
102                 else\r
103                 {\r
104                         for(i = 0; i < 3; i++)\r
105                         {\r
106                                 if(min[i] > point[n].p[i])\r
107                                         min[i] = point[n].p[i];\r
108                                 if(max[i] < point[n].p[i])\r
109                                         max[i] = point[n].p[i];\r
110                         }\r
111                 }\r
112         }\r
113 \r
114         center.p[0] /= (float)point_count;\r
115         center.p[1] /= (float)point_count;\r
116         center.p[2] /= (float)point_count;\r
117 \r
118         for(n = 0; n < point_count; n++)\r
119         {\r
120                 inner_point[n].p[0] = (0.01f * center.p[0]) + (0.99f * point[n].p[0]);\r
121                 inner_point[n].p[1] = (0.01f * center.p[1]) + (0.99f * point[n].p[1]);\r
122                 inner_point[n].p[2] = (0.01f * center.p[2]) + (0.99f * point[n].p[2]);\r
123         }\r
124 \r
125         fp_color_random[0] = (float)(rand() & 0xff) / 255.0f;\r
126         fp_color_random[1] = (float)(rand() & 0xff) / 255.0f;\r
127         fp_color_random[2] = (float)(rand() & 0xff) / 255.0f;\r
128         fp_color_random[3] = 1.0f;\r
129 \r
130         return TRUE;\r
131 }\r
132 \r
133 CPortals::CPortals()\r
134 {\r
135         memset(this, 0, sizeof(CPortals));\r
136 }\r
137 \r
138 CPortals::~CPortals()\r
139 {\r
140         Purge();\r
141 }\r
142 \r
143 void CPortals::Purge()\r
144 {\r
145         delete[] portal;\r
146         delete[] portal_sort;\r
147         portal = NULL;\r
148         portal_sort = NULL;\r
149         portal_count = 0;\r
150 \r
151         /*\r
152         delete[] node;\r
153         node = NULL;\r
154         node_count = 0;\r
155         */\r
156 }\r
157 \r
158 void CPortals::Load()\r
159 {\r
160         char buf[LINE_BUF+1];\r
161 \r
162         memset(buf, 0, LINE_BUF + 1);\r
163         \r
164         Purge();\r
165 \r
166         Sys_Printf(MSG_PREFIX "Loading portal file %s.\n", fn);\r
167 \r
168         FILE *in;\r
169 \r
170         in = fopen(fn, "rt");\r
171 \r
172         if(in == NULL)\r
173         {\r
174                 Sys_Printf("  ERROR - could not open file.\n");\r
175 \r
176                 return;\r
177         }\r
178 \r
179         if(!fgets(buf, LINE_BUF, in))\r
180         {\r
181                 fclose(in);\r
182 \r
183                 Sys_Printf("  ERROR - File ended prematurely.\n");\r
184 \r
185                 return;\r
186         }\r
187 \r
188         if(strncmp("PRT1", buf, 4) != 0)\r
189         {\r
190                 fclose(in);\r
191 \r
192                 Sys_Printf("  ERROR - File header indicates wrong file type (should be \"PRT1\").\n");\r
193 \r
194                 return;\r
195         }\r
196 \r
197         if(!fgets(buf, LINE_BUF, in))\r
198         {\r
199                 fclose(in);\r
200 \r
201                 Sys_Printf("  ERROR - File ended prematurely.\n");\r
202 \r
203                 return;\r
204         }\r
205 \r
206         sscanf(buf, "%u", &node_count);\r
207 /*\r
208         if(node_count > 0xFFFF)\r
209         {\r
210                 fclose(in);\r
211 \r
212                 node_count = 0;\r
213 \r
214                 Sys_Printf("  ERROR - Extreme number of nodes, aborting.\n");\r
215 \r
216                 return;\r
217         }\r
218         */\r
219 \r
220         if(!fgets(buf, LINE_BUF, in))\r
221         {\r
222                 fclose(in);\r
223 \r
224                 node_count = 0;\r
225 \r
226                 Sys_Printf("  ERROR - File ended prematurely.\n");\r
227 \r
228                 return;\r
229         }\r
230 \r
231         sscanf(buf, "%u", &portal_count);\r
232 \r
233         if(portal_count > 0xFFFF)\r
234         {\r
235                 fclose(in);\r
236 \r
237                 portal_count = 0;\r
238                 node_count = 0;\r
239 \r
240                 Sys_Printf("  ERROR - Extreme number of portals, aborting.\n");\r
241 \r
242                 return;\r
243         }\r
244 \r
245         if(portal_count < 0)\r
246         {\r
247                 fclose(in);\r
248 \r
249                 portal_count = 0;\r
250                 node_count = 0;\r
251 \r
252                 Sys_Printf("  ERROR - number of portals equals 0, aborting.\n");\r
253 \r
254                 return;\r
255         }\r
256 \r
257 //      node = new CBspNode[node_count];\r
258         portal = new CBspPortal[portal_count];\r
259         portal_sort = new int[portal_count];\r
260 \r
261         unsigned int n;\r
262         qboolean first = TRUE;\r
263         unsigned test_vals_1, test_vals_2;\r
264 \r
265         hint_flags = FALSE;\r
266 \r
267         for(n = 0; n < portal_count; )\r
268         {\r
269                 if(!fgets(buf, LINE_BUF, in))\r
270                 {\r
271                         fclose(in);\r
272 \r
273                         Purge();\r
274 \r
275                         Sys_Printf("  ERROR - Could not find information for portal number %d of %d.\n", n + 1, portal_count);\r
276 \r
277                         return;\r
278                 }\r
279 \r
280                 if(!portal[n].Build(buf))\r
281                 {\r
282                         if(first && sscanf(buf, "%d %d", &test_vals_1, &test_vals_2) == 1) // skip additional counts of later data, not needed\r
283                         {\r
284                                 // We can count on hint flags being in the file\r
285                                 hint_flags = TRUE;\r
286                                 continue;\r
287                         }\r
288 \r
289                         first = FALSE;\r
290 \r
291                         fclose(in);\r
292 \r
293                         Purge();\r
294 \r
295                         Sys_Printf("  ERROR - Information for portal number %d of %d is not formatted correctly.\n", n + 1, portal_count);\r
296 \r
297                         return;\r
298                 }\r
299 \r
300                 n++;\r
301         }\r
302 \r
303         fclose(in);\r
304 \r
305         Sys_Printf("  %u portals read in.\n", node_count, portal_count);\r
306 }\r
307 \r
308 void CPortals::FixColors()\r
309 {\r
310         fp_color_2d[0] = (float)GetRValue(color_2d) / 255.0f;\r
311         fp_color_2d[1] = (float)GetGValue(color_2d) / 255.0f;\r
312         fp_color_2d[2] = (float)GetBValue(color_2d) / 255.0f;\r
313         fp_color_2d[3] = 1.0f;\r
314 \r
315         fp_color_3d[0] = (float)GetRValue(color_3d) / 255.0f;\r
316         fp_color_3d[1] = (float)GetGValue(color_3d) / 255.0f;\r
317         fp_color_3d[2] = (float)GetBValue(color_3d) / 255.0f;\r
318         fp_color_3d[3] = 1.0f;\r
319 \r
320         fp_color_fog[0] = 0.0f;//(float)GetRValue(color_fog) / 255.0f;\r
321         fp_color_fog[1] = 0.0f;//(float)GetGValue(color_fog) / 255.0f;\r
322         fp_color_fog[2] = 0.0f;//(float)GetBValue(color_fog) / 255.0f;\r
323         fp_color_fog[3] = 1.0f;\r
324 }\r
325 \r
326 CPortalsRender::CPortalsRender()\r
327 {\r
328         refCount = 1;\r
329 }\r
330 \r
331 CPortalsRender::~CPortalsRender()\r
332 {\r
333 }\r
334 \r
335 void CPortalsRender::Register()\r
336 {\r
337         g_QglTable.m_pfnHookGL2DWindow( this );\r
338         g_QglTable.m_pfnHookGL3DWindow( this );\r
339 }\r
340 \r
341 void CPortalsRender::Draw2D( VIEWTYPE vt )\r
342 {\r
343         if(!portals.show_2d || portals.portal_count < 1)\r
344                 return;\r
345 \r
346         g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);\r
347 \r
348         if(portals.aa_2d)\r
349         {\r
350                 g_QglTable.m_pfn_qglEnable(GL_BLEND);\r
351                 g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);\r
352         }\r
353         else\r
354         {\r
355                 g_QglTable.m_pfn_qglDisable(GL_BLEND);\r
356                 g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);\r
357         }\r
358 \r
359         switch(vt)\r
360         {\r
361         case XY:\r
362                 break;\r
363         case XZ:\r
364                 g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f);\r
365                 break;\r
366         case YZ:\r
367                 g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f);\r
368                 g_QglTable.m_pfn_qglRotatef(270.0f, 0.0f, 0.0f, 1.0f);\r
369                 break;\r
370         }\r
371 \r
372         g_QglTable.m_pfn_qglLineWidth(portals.width_2d * 0.5f);\r
373 \r
374         g_QglTable.m_pfn_qglColor4fv(portals.fp_color_2d);\r
375 \r
376         unsigned int n, p;\r
377 \r
378         for(n = 0; n < portals.portal_count; n++)\r
379         {\r
380                 g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);\r
381 \r
382                 for(p = 0; p < portals.portal[n].point_count; p++)\r
383                         g_QglTable.m_pfn_qglVertex3fv(portals.portal[n].point[p].p);\r
384 \r
385                 g_QglTable.m_pfn_qglEnd();\r
386         }\r
387 \r
388         g_QglTable.m_pfn_qglPopAttrib();\r
389 }\r
390 \r
391 /*\r
392  * Transform a point (column vector) by a 4x4 matrix.  I.e.  out = m * in\r
393  * Input:  m - the 4x4 matrix\r
394  *         in - the 4x1 vector\r
395  * Output:  out - the resulting 4x1 vector.\r
396  */\r
397 static void transform_point( GLdouble out[4], const GLdouble m[16],\r
398                              const GLdouble in[4] )\r
399 {\r
400 #define M(row,col)  m[col*4+row]\r
401    out[0] = M(0,0) * in[0] + M(0,1) * in[1] + M(0,2) * in[2] + M(0,3) * in[3];\r
402    out[1] = M(1,0) * in[0] + M(1,1) * in[1] + M(1,2) * in[2] + M(1,3) * in[3];\r
403    out[2] = M(2,0) * in[0] + M(2,1) * in[1] + M(2,2) * in[2] + M(2,3) * in[3];\r
404    out[3] = M(3,0) * in[0] + M(3,1) * in[1] + M(3,2) * in[2] + M(3,3) * in[3];\r
405 #undef M\r
406 }\r
407 \r
408 #include <math.h>\r
409 \r
410 \r
411 /*\r
412  * Perform a 4x4 matrix multiplication  (product = a x b).\r
413  * Input:  a, b - matrices to multiply\r
414  * Output:  product - product of a and b\r
415  */\r
416 static void matmul( GLdouble *product, const GLdouble *a, const GLdouble *b )\r
417 {\r
418    /* This matmul was contributed by Thomas Malik */\r
419    GLdouble temp[16];\r
420    GLint i;\r
421 \r
422 #define A(row,col)  a[(col<<2)+row]\r
423 #define B(row,col)  b[(col<<2)+row]\r
424 #define T(row,col)  temp[(col<<2)+row]\r
425 \r
426    /* i-te Zeile */\r
427    for (i = 0; i < 4; i++)\r
428      {\r
429         T(i, 0) = A(i, 0) * B(0, 0) + A(i, 1) * B(1, 0) + A(i, 2) * B(2, 0) + A(i, 3) * B(3, 0);\r
430         T(i, 1) = A(i, 0) * B(0, 1) + A(i, 1) * B(1, 1) + A(i, 2) * B(2, 1) + A(i, 3) * B(3, 1);\r
431         T(i, 2) = A(i, 0) * B(0, 2) + A(i, 1) * B(1, 2) + A(i, 2) * B(2, 2) + A(i, 3) * B(3, 2);\r
432         T(i, 3) = A(i, 0) * B(0, 3) + A(i, 1) * B(1, 3) + A(i, 2) * B(2, 3) + A(i, 3) * B(3, 3);\r
433      }\r
434 \r
435 #undef A\r
436 #undef B\r
437 #undef T\r
438    memcpy ( product, temp, 16*sizeof(GLdouble) );\r
439 }\r
440 \r
441 \r
442 \r
443 /*\r
444  * Compute inverse of 4x4 transformation matrix.\r
445  * Code contributed by Jacques Leroy jle@star.be\r
446  * Return GL_TRUE for success, GL_FALSE for failure (singular matrix)\r
447  */\r
448 static GLboolean invert_matrix( const GLdouble *m, GLdouble *out )\r
449 {\r
450 /* NB. OpenGL Matrices are COLUMN major. */\r
451 #define SWAP_ROWS(a, b) { GLdouble *_tmp = a; (a)=(b); (b)=_tmp; }\r
452 #define MAT(m,r,c) (m)[(c)*4+(r)]\r
453 \r
454  GLdouble wtmp[4][8];\r
455  GLdouble m0, m1, m2, m3, s;\r
456  GLdouble *r0, *r1, *r2, *r3;\r
457 \r
458  r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];\r
459 \r
460  r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1),\r
461  r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3),\r
462  r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,\r
463 \r
464  r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1),\r
465  r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3),\r
466  r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,\r
467 \r
468  r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1),\r
469  r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3),\r
470  r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,\r
471 \r
472  r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1),\r
473  r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3),\r
474  r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;\r
475 \r
476  /* choose pivot - or die */\r
477  if (fabs(r3[0])>fabs(r2[0])) SWAP_ROWS(r3, r2);\r
478  if (fabs(r2[0])>fabs(r1[0])) SWAP_ROWS(r2, r1);\r
479  if (fabs(r1[0])>fabs(r0[0])) SWAP_ROWS(r1, r0);\r
480  if (0.0 == r0[0])  return GL_FALSE;\r
481 \r
482  /* eliminate first variable     */\r
483  m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0];\r
484  s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s;\r
485  s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s;\r
486  s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s;\r
487  s = r0[4];\r
488  if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; }\r
489  s = r0[5];\r
490  if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; }\r
491  s = r0[6];\r
492  if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; }\r
493  s = r0[7];\r
494  if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; }\r
495 \r
496  /* choose pivot - or die */\r
497  if (fabs(r3[1])>fabs(r2[1])) SWAP_ROWS(r3, r2);\r
498  if (fabs(r2[1])>fabs(r1[1])) SWAP_ROWS(r2, r1);\r
499  if (0.0 == r1[1])  return GL_FALSE;\r
500 \r
501  /* eliminate second variable */\r
502  m2 = r2[1]/r1[1]; m3 = r3[1]/r1[1];\r
503  r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2];\r
504  r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3];\r
505  s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; }\r
506  s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; }\r
507  s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; }\r
508  s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; }\r
509 \r
510  /* choose pivot - or die */\r
511  if (fabs(r3[2])>fabs(r2[2])) SWAP_ROWS(r3, r2);\r
512  if (0.0 == r2[2])  return GL_FALSE;\r
513 \r
514  /* eliminate third variable */\r
515  m3 = r3[2]/r2[2];\r
516  r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],\r
517  r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6],\r
518  r3[7] -= m3 * r2[7];\r
519 \r
520  /* last check */\r
521  if (0.0 == r3[3]) return GL_FALSE;\r
522 \r
523  s = 1.0/r3[3];              /* now back substitute row 3 */\r
524  r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s;\r
525 \r
526  m2 = r2[3];                 /* now back substitute row 2 */\r
527  s  = 1.0/r2[2];\r
528  r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),\r
529  r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);\r
530  m1 = r1[3];\r
531  r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,\r
532  r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;\r
533  m0 = r0[3];\r
534  r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,\r
535  r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;\r
536 \r
537  m1 = r1[2];                 /* now back substitute row 1 */\r
538  s  = 1.0/r1[1];\r
539  r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),\r
540  r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);\r
541  m0 = r0[2];\r
542  r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,\r
543  r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;\r
544 \r
545  m0 = r0[1];                 /* now back substitute row 0 */\r
546  s  = 1.0/r0[0];\r
547  r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),\r
548  r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);\r
549 \r
550  MAT(out,0,0) = r0[4]; MAT(out,0,1) = r0[5],\r
551  MAT(out,0,2) = r0[6]; MAT(out,0,3) = r0[7],\r
552  MAT(out,1,0) = r1[4]; MAT(out,1,1) = r1[5],\r
553  MAT(out,1,2) = r1[6]; MAT(out,1,3) = r1[7],\r
554  MAT(out,2,0) = r2[4]; MAT(out,2,1) = r2[5],\r
555  MAT(out,2,2) = r2[6]; MAT(out,2,3) = r2[7],\r
556  MAT(out,3,0) = r3[4]; MAT(out,3,1) = r3[5],\r
557  MAT(out,3,2) = r3[6]; MAT(out,3,3) = r3[7]; \r
558 \r
559  return GL_TRUE;\r
560 \r
561 #undef MAT\r
562 #undef SWAP_ROWS\r
563 }\r
564 \r
565 GLint UnProject(GLdouble winx,GLdouble winy,GLdouble winz,\r
566                 const GLdouble model[16],const GLdouble proj[16],\r
567                 const GLint viewport[4],\r
568                 GLdouble *objx,GLdouble *objy,GLdouble *objz)\r
569 {\r
570     /* matrice de transformation */\r
571     GLdouble m[16], A[16];\r
572     GLdouble in[4],out[4];\r
573 \r
574     /* transformation coordonnees normalisees entre -1 et 1 */\r
575     in[0]=(winx-viewport[0])*2/viewport[2] - 1.0;\r
576     in[1]=(winy-viewport[1])*2/viewport[3] - 1.0;\r
577     in[2]=2*winz - 1.0;\r
578     in[3]=1.0;\r
579 \r
580     /* calcul transformation inverse */\r
581     matmul(A,proj,model);\r
582     invert_matrix(A,m);\r
583 \r
584     /* d'ou les coordonnees objets */\r
585     transform_point(out,m,in);\r
586     if (out[3]==0.0)\r
587        return GL_FALSE;\r
588     *objx=out[0]/out[3];\r
589     *objy=out[1]/out[3];\r
590     *objz=out[2]/out[3];\r
591     return GL_TRUE;\r
592 }\r
593 \r
594 void CPortalsRender::Draw3D()\r
595 {\r
596         if(!portals.show_3d || portals.portal_count < 1)\r
597                 return;\r
598 \r
599         g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);\r
600 \r
601         double cam[3];\r
602         double proj_m[16];\r
603         double model_m[16];\r
604         float min_check[3];\r
605         float max_check[3];\r
606         float trans = (100.0f - portals.trans_3d) / 100.0f;\r
607         int view[4];\r
608 \r
609         g_QglTable.m_pfn_qglGetDoublev(GL_PROJECTION_MATRIX, proj_m);\r
610         g_QglTable.m_pfn_qglGetDoublev(GL_MODELVIEW_MATRIX, model_m);\r
611         g_QglTable.m_pfn_qglGetIntegerv(GL_VIEWPORT, view);\r
612 \r
613         UnProject(0.5 * (double)view[2], 0.5 * (double)view[3], 0.0, model_m, proj_m, view, cam, cam+1, cam+2);\r
614 \r
615         min_check[0] = (float)cam[0] + (portals.clip_range * 64.0f);\r
616         min_check[1] = (float)cam[1] + (portals.clip_range * 64.0f);\r
617         min_check[2] = (float)cam[2] + (portals.clip_range * 64.0f);\r
618         max_check[0] = (float)cam[0] - (portals.clip_range * 64.0f);\r
619         max_check[1] = (float)cam[1] - (portals.clip_range * 64.0f);\r
620         max_check[2] = (float)cam[2] - (portals.clip_range * 64.0f);\r
621 \r
622         g_QglTable.m_pfn_qglHint(GL_FOG_HINT, GL_NICEST);\r
623         \r
624         g_QglTable.m_pfn_qglDisable(GL_CULL_FACE);\r
625 \r
626         g_QglTable.m_pfn_qglDisable(GL_LINE_SMOOTH);\r
627         g_QglTable.m_pfn_qglDisable(GL_POLYGON_SMOOTH);\r
628 \r
629         g_QglTable.m_pfn_qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
630 \r
631         g_QglTable.m_pfn_qglShadeModel(GL_SMOOTH);\r
632 \r
633         g_QglTable.m_pfn_qglEnable(GL_BLEND);\r
634         g_QglTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
635         g_QglTable.m_pfn_qglEnable(GL_POLYGON_SMOOTH);\r
636 \r
637         if(portals.aa_3d)\r
638                 g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);\r
639         else\r
640                 g_QglTable.m_pfn_qglDisable(GL_LINE_SMOOTH);\r
641 \r
642         if(portals.fog)\r
643         {\r
644                 g_QglTable.m_pfn_qglEnable(GL_FOG);\r
645 \r
646                 g_QglTable.m_pfn_qglFogi(GL_FOG_MODE, GL_EXP);\r
647                 g_QglTable.m_pfn_qglFogf(GL_FOG_DENSITY, 0.001f);\r
648                 g_QglTable.m_pfn_qglFogf(GL_FOG_START, 10.0f);\r
649                 g_QglTable.m_pfn_qglFogf(GL_FOG_END, 10000.0f);\r
650                 g_QglTable.m_pfn_qglFogi(GL_FOG_INDEX, 0);\r
651                 g_QglTable.m_pfn_qglFogfv(GL_FOG_COLOR, portals.fp_color_fog);\r
652         }\r
653         else\r
654         {\r
655                 g_QglTable.m_pfn_qglDisable(GL_FOG);\r
656         }\r
657 \r
658         switch(portals.zbuffer)\r
659         {\r
660         case 1:\r
661                 g_QglTable.m_pfn_qglEnable(GL_DEPTH_TEST);\r
662                 g_QglTable.m_pfn_qglDepthMask(GL_FALSE);\r
663                 break;\r
664         case 2:\r
665                 g_QglTable.m_pfn_qglDisable(GL_DEPTH_TEST);\r
666                 break;\r
667         default:\r
668                 g_QglTable.m_pfn_qglEnable(GL_DEPTH_TEST);\r
669                 g_QglTable.m_pfn_qglDepthMask(GL_TRUE);\r
670         }\r
671 \r
672         g_QglTable.m_pfn_qglLineWidth(portals.width_3d * 0.5f);\r
673 \r
674         unsigned int n, p;\r
675 \r
676         if(portals.polygons)\r
677         {\r
678                 if(portals.zbuffer != 0)\r
679                 {\r
680                         float d;\r
681 \r
682                         for(n = 0; n < portals.portal_count; n++)\r
683                         {\r
684                                 d = (float)cam[0] - portals.portal[n].center.p[0];\r
685                                 portals.portal[n].dist = d * d;\r
686 \r
687                                 d = (float)cam[1] - portals.portal[n].center.p[1];\r
688                                 portals.portal[n].dist += d * d;\r
689 \r
690                                 d = (float)cam[2] - portals.portal[n].center.p[2];\r
691                                 portals.portal[n].dist += d * d;\r
692 \r
693                                 portals.portal_sort[n] = n;\r
694                         }\r
695 \r
696                         qsort(portals.portal_sort, portals.portal_count, 4, compare);\r
697                                         \r
698                         for(n = 0; n < portals.portal_count; n++)\r
699                         {\r
700                                 if(portals.polygons == 2 && !portals.portal[portals.portal_sort[n]].hint)\r
701                                         continue;\r
702         \r
703                                 if(portals.clip)\r
704                                 {\r
705                                         if(min_check[0] < portals.portal[portals.portal_sort[n]].min[0])\r
706                                                 continue;\r
707                                         else if(min_check[1] < portals.portal[portals.portal_sort[n]].min[1])\r
708                                                 continue;\r
709                                         else if(min_check[2] < portals.portal[portals.portal_sort[n]].min[2])\r
710                                                 continue;\r
711                                         else if(max_check[0] > portals.portal[portals.portal_sort[n]].max[0])\r
712                                                 continue;\r
713                                         else if(max_check[1] > portals.portal[portals.portal_sort[n]].max[1])\r
714                                                 continue;\r
715                                         else if(max_check[2] > portals.portal[portals.portal_sort[n]].max[2])\r
716                                                 continue;\r
717                                 }\r
718 \r
719                                 g_QglTable.m_pfn_qglColor4f(portals.portal[portals.portal_sort[n]].fp_color_random[0], portals.portal[portals.portal_sort[n]].fp_color_random[1],\r
720                                         portals.portal[portals.portal_sort[n]].fp_color_random[2], trans);\r
721 \r
722                                 g_QglTable.m_pfn_qglBegin(GL_POLYGON);\r
723 \r
724                                         for(p = 0; p < portals.portal[portals.portal_sort[n]].point_count; p++)\r
725                                                 g_QglTable.m_pfn_qglVertex3fv(portals.portal[portals.portal_sort[n]].point[p].p);\r
726 \r
727                                 g_QglTable.m_pfn_qglEnd();\r
728                         }\r
729                 }\r
730                 else\r
731                 {\r
732                         for(n = 0; n < portals.portal_count; n++)\r
733                         {\r
734                                 if(portals.polygons == 2 && !portals.portal[n].hint)\r
735                                         continue;\r
736 \r
737                                 if(portals.clip)\r
738                                 {\r
739                                         if(min_check[0] < portals.portal[n].min[0])\r
740                                                 continue;\r
741                                         else if(min_check[1] < portals.portal[n].min[1])\r
742                                                 continue;\r
743                                         else if(min_check[2] < portals.portal[n].min[2])\r
744                                                 continue;\r
745                                         else if(max_check[0] > portals.portal[n].max[0])\r
746                                                 continue;\r
747                                         else if(max_check[1] > portals.portal[n].max[1])\r
748                                                 continue;\r
749                                         else if(max_check[2] > portals.portal[n].max[2])\r
750                                                 continue;\r
751                                 }\r
752 \r
753                                 g_QglTable.m_pfn_qglColor4f(portals.portal[n].fp_color_random[0], portals.portal[n].fp_color_random[1],\r
754                                         portals.portal[n].fp_color_random[2], trans);\r
755 \r
756                                 g_QglTable.m_pfn_qglBegin(GL_POLYGON);\r
757 \r
758                                         for(p = 0; p < portals.portal[n].point_count; p++)\r
759                                                 g_QglTable.m_pfn_qglVertex3fv(portals.portal[n].point[p].p);\r
760 \r
761                                 g_QglTable.m_pfn_qglEnd();\r
762                         }\r
763                 }\r
764         }\r
765 \r
766         if(portals.lines)\r
767         {\r
768                 g_QglTable.m_pfn_qglColor4fv(portals.fp_color_3d);\r
769 \r
770                 for(n = 0; n < portals.portal_count; n++)\r
771                 {\r
772                         if(portals.lines == 2 && !portals.portal[n].hint)\r
773                                 continue;\r
774 \r
775                         if(portals.clip)\r
776                         {\r
777                                 if(min_check[0] < portals.portal[n].min[0])\r
778                                         continue;\r
779                                 else if(min_check[1] < portals.portal[n].min[1])\r
780                                         continue;\r
781                                 else if(min_check[2] < portals.portal[n].min[2])\r
782                                         continue;\r
783                                 else if(max_check[0] > portals.portal[n].max[0])\r
784                                         continue;\r
785                                 else if(max_check[1] > portals.portal[n].max[1])\r
786                                         continue;\r
787                                 else if(max_check[2] > portals.portal[n].max[2])\r
788                                         continue;\r
789                         }\r
790 \r
791                         g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);\r
792 \r
793                         for(p = 0; p < portals.portal[n].point_count; p++)\r
794                                 g_QglTable.m_pfn_qglVertex3fv(portals.portal[n].inner_point[p].p);\r
795 \r
796                         g_QglTable.m_pfn_qglEnd();\r
797                 }\r
798         }\r
799 \r
800         g_QglTable.m_pfn_qglPopAttrib();\r
801 }\r
802 \r