1 // Here lies the slow as shit renderer!
2
3 #ifndef polymer_h_
4 # define polymer_h_
5
6 # include "baselayer.h"
7 # include "build.h"
8 # include "compat.h"
9 # include "glad/glad.h"
10 # include "glbuild.h"
11 # include "hightile.h"
12 # include "mdsprite.h"
13 # include "osd.h"
14 # include "polymost.h"
15 # include "pragmas.h"
16
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20
21 #define PR_LINEAR_FOG
22
23 // CVARS
24 extern int32_t pr_lighting;
25 extern int32_t pr_normalmapping;
26 extern int32_t pr_specularmapping;
27 extern int32_t pr_shadows;
28 extern int32_t pr_shadowcount;
29 extern int32_t pr_shadowdetail;
30 extern int32_t pr_shadowfiltering;
31 extern int32_t pr_maxlightpasses;
32 extern int32_t pr_maxlightpriority;
33 extern int32_t pr_fov;
34 extern double pr_customaspect;
35 extern int32_t pr_billboardingmode;
36 extern int32_t pr_verbosity;
37 extern int32_t pr_wireframe;
38 extern int32_t pr_vbos;
39 extern int32_t pr_buckets;
40 extern int32_t pr_gpusmoothing;
41 extern int32_t pr_overrideparallax;
42 extern float pr_parallaxscale;
43 extern float pr_parallaxbias;
44 extern int32_t pr_overridespecular;
45 extern float pr_specularpower;
46 extern float pr_specularfactor;
47 extern int32_t pr_highpalookups;
48 extern int32_t pr_artmapping;
49 extern int32_t pr_overridehud;
50 extern float pr_hudxadd;
51 extern float pr_hudyadd;
52 extern float pr_hudzadd;
53 extern int32_t pr_hudangadd;
54 extern int32_t pr_hudfov;
55 extern float pr_overridemodelscale;
56 extern int32_t pr_ati_fboworkaround;
57 extern int32_t pr_ati_nodepthoffset;
58 #ifdef __APPLE__
59 extern int32_t pr_ati_textureformat_one;
60 #endif
61 extern int32_t pr_nullrender;
62
63 extern int32_t r_pr_maxlightpasses;
64
65 // MATERIAL
66 typedef enum {
67 PR_BIT_HEADER, // must be first
68 PR_BIT_ANIM_INTERPOLATION,
69 PR_BIT_LIGHTING_PASS,
70 PR_BIT_NORMAL_MAP,
71 PR_BIT_ART_MAP,
72 PR_BIT_DIFFUSE_MAP,
73 PR_BIT_DIFFUSE_DETAIL_MAP,
74 PR_BIT_DIFFUSE_MODULATION,
75 PR_BIT_DIFFUSE_MAP2,
76 PR_BIT_HIGHPALOOKUP_MAP,
77 PR_BIT_SPECULAR_MAP,
78 PR_BIT_SPECULAR_MATERIAL,
79 PR_BIT_MIRROR_MAP,
80 PR_BIT_FOG,
81 PR_BIT_GLOW_MAP,
82 PR_BIT_PROJECTION_MAP,
83 PR_BIT_SHADOW_MAP,
84 PR_BIT_LIGHT_MAP,
85 PR_BIT_SPOT_LIGHT,
86 PR_BIT_POINT_LIGHT,
87 PR_BIT_FOOTER, // must be just before last
88 PR_BIT_COUNT // must be last
89 } prbittype;
90
91 typedef struct s_prmaterial {
92 // PR_BIT_ANIM_INTERPOLATION
93 GLfloat frameprogress;
94 GLfloat* nextframedata;
95 // PR_BIT_NORMAL_MAP
96 GLuint normalmap;
97 GLfloat normalbias[2];
98 GLfloat* tbn;
99 // PR_BIT_ART_MAP
100 GLuint artmap;
101 GLuint basepalmap;
102 GLuint lookupmap;
103 GLint shadeoffset;
104 GLfloat visibility;
105 // PR_BIT_DIFFUSE_MAP
106 GLuint diffusemap;
107 GLfloat diffusescale[2];
108 // PR_BIT_HIGHPALOOKUP_MAP
109 GLuint highpalookupmap;
110 // PR_BIT_DIFFUSE_DETAIL_MAP
111 GLuint detailmap;
112 GLfloat detailscale[2];
113 // PR_BIT_DIFFUSE_MODULATION
114 GLubyte diffusemodulation[4];
115 // PR_BIT_SPECULAR_MAP
116 GLuint specmap;
117 // PR_BIT_SPECULAR_MATERIAL
118 GLfloat specmaterial[2];
119 // PR_BIT_MIRROR_MAP
120 GLuint mirrormap;
121 // PR_BIT_GLOW_MAP
122 GLuint glowmap;
123 // PR_BIT_SHADOW_MAP
124 GLboolean mdspritespace;
125 } _prmaterial;
126
127 typedef struct s_prrograminfo {
128 GLuint handle;
129 // PR_BIT_ANIM_INTERPOLATION
130 GLint attrib_nextFrameData;
131 GLint attrib_nextFrameNormal;
132 GLint uniform_frameProgress;
133 // PR_BIT_NORMAL_MAP
134 GLint attrib_T;
135 GLint attrib_B;
136 GLint attrib_N;
137 GLint uniform_eyePosition;
138 GLint uniform_normalMap;
139 GLint uniform_normalBias;
140 // PR_BIT_ART_MAP
141 GLuint uniform_artMap;
142 GLuint uniform_basePalMap;
143 GLuint uniform_lookupMap;
144 GLuint uniform_shadeOffset;
145 GLuint uniform_visibility;
146 // PR_BIT_DIFFUSE_MAP
147 GLint uniform_diffuseMap;
148 GLint uniform_diffuseScale;
149 // PR_BIT_HIGHPALOOKUP_MAP
150 GLuint uniform_highPalookupMap;
151 // PR_BIT_DIFFUSE_DETAIL_MAP
152 GLint uniform_detailMap;
153 GLint uniform_detailScale;
154 // PR_BIT_SPECULAR_MAP
155 GLint uniform_specMap;
156 // PR_BIT_SPECULAR_MATERIAL
157 GLint uniform_specMaterial;
158 // PR_BIT_MIRROR_MAP
159 GLint uniform_mirrorMap;
160 #ifdef PR_LINEAR_FOG
161 // PR_BIT_FOG
162 GLint uniform_linearFog;
163 #endif
164 // PR_BIT_GLOW_MAP
165 GLint uniform_glowMap;
166 // PR_BIT_PROJECTION_MAP
167 GLint uniform_shadowProjMatrix;
168 // PR_BIT_SHADOW_MAP
169 GLint uniform_shadowMap;
170 // PR_BIT_LIGHT_MAP
171 GLint uniform_lightMap;
172 // PR_BIT_SPOT_LIGHT
173 GLint uniform_spotDir;
174 GLint uniform_spotRadius;
175 } _prprograminfo;
176
177 #define PR_INFO_LOG_BUFFER_SIZE 8192
178
179 // Think about changing highPal[Scale|Bias] in the program bit if you change this
180 #define PR_HIGHPALOOKUP_BIT_DEPTH 6
181 #define PR_HIGHPALOOKUP_DIM (1 << PR_HIGHPALOOKUP_BIT_DEPTH)
182 #define PR_HIGHPALOOKUP_DATA_SIZE (4 * PR_HIGHPALOOKUP_DIM * \
183 PR_HIGHPALOOKUP_DIM * \
184 PR_HIGHPALOOKUP_DIM)
185
186 typedef struct s_prprogrambit {
187 int32_t bit;
188 const char* vert_def;
189 const char* vert_prog;
190 const char* frag_def;
191 const char* frag_prog;
192 } _prprogrambit;
193
194 typedef struct s_prbucket {
195 // index
196 int16_t tilenum;
197 char pal;
198
199 _prmaterial material;
200 int32_t invalidmaterial;
201
202 // geom indices
203 GLuint* indices;
204 uint32_t count;
205 uint32_t buffersize;
206 GLuint* indiceoffset;
207
208 struct s_prbucket* next;
209 } _prbucket;
210
211 #include "prlights.h"
212
213 // RENDER TARGETS
214 typedef struct s_prrt {
215 GLenum target;
216 GLuint color;
217 GLuint z;
218 GLuint fbo;
219 int32_t xdim, ydim;
220 } _prrt;
221
222 // BUILD DATA
223
224 typedef struct s_prvert {
225 GLfloat x;
226 GLfloat y;
227 GLfloat z;
228 GLfloat u;
229 GLfloat v;
230 GLubyte r;
231 GLubyte g;
232 GLubyte b;
233 GLubyte a;
234 } _prvert;
235
236 typedef struct s_prplane {
237 // geometry
238 _prvert* buffer;
239 int32_t vertcount;
240 GLuint vbo;
241 uint32_t mapvbo_vertoffset;
242 _prbucket* bucket;
243 // attributes
244 GLfloat tbn[3][3];
245 GLfloat plane[4];
246 _prmaterial material;
247 // elements
248 GLushort* indices;
249 int32_t indicescount;
250 GLuint ivbo;
251 // lights
252 int16_t lights[PR_MAXLIGHTS];
253 uint16_t lightcount;
254 } _prplane;
255
256 typedef struct s_prsector {
257 // polymer data
258 GLdouble* verts;
259 _prplane floor;
260 _prplane ceil;
261 int16_t curindice;
262 int32_t indicescount;
263 int32_t oldindicescount;
264 // stuff
265 float wallsproffset;
266 float floorsproffset;
267 // build sector data
268 int32_t ceilingz, floorz;
269 uint16_t ceilingstat, floorstat;
270 int16_t ceilingpicnum, ceilingheinum;
271 int8_t ceilingshade;
272 uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
273 int16_t floorpicnum, floorheinum;
274 int8_t floorshade;
275 uint8_t floorpal, floorxpanning, floorypanning;
276 uint8_t visibility;
277
278 int16_t floorpicnum_anim, ceilingpicnum_anim;
279
280 struct {
281 int32_t empty : 1;
282 int32_t uptodate : 1;
283 int32_t invalidtex : 1;
284 } flags;
285 uint32_t invalidid;
286 uint32_t trackedrev;
287 } _prsector;
288
289 typedef struct s_prwall {
290 _prplane wall;
291 _prplane over;
292 _prplane mask;
293
294 // stuff
295 GLfloat* bigportal;
296 //GLfloat* cap;
297 GLuint stuffvbo;
298
299 // build wall data
300 uint16_t cstat;
301 int16_t picnum, overpicnum;
302 int8_t shade;
303 uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
304
305 // nextwall data
306 int16_t nwallpicnum, nwallcstat;
307 int8_t nwallxpanning, nwallypanning;
308 int8_t nwallshade;
309
310 int16_t picnum_anim, overpicnum_anim;
311
312 char underover;
313 uint32_t invalidid;
314 struct {
315 int32_t empty : 1;
316 int32_t uptodate : 1;
317 int32_t invalidtex : 1;
318 } flags;
319 uint32_t trackedrev;
320 } _prwall;
321
322 typedef struct s_prsprite {
323 _prplane plane;
324 uint32_t hash;
325 } _prsprite;
326
327 typedef struct s_prmirror {
328 _prplane *plane;
329 int16_t sectnum;
330 int16_t wallnum;
331 int8_t rorstat;
332 } _prmirror;
333
334 typedef struct s_prhighpalookup {
335 char *data;
336 GLuint map;
337 } _prhighpalookup;
338
339 typedef void (*animatespritesptr)(int32_t, int32_t, int32_t, int32_t, int32_t);
340
341 typedef struct s_pranimatespritesinfo {
342 animatespritesptr animatesprites;
343 int32_t x, y, z, a, smoothratio;
344 } _pranimatespritesinfo;
345
346 typedef void (*rorcallback)(int16_t sectnum, int16_t wallnum, int8_t rorstat, int16_t *msectnum, int32_t *gx, int32_t *gy, int32_t *gz);
347
348 // this one has to be provided by the application
349 extern void G_Polymer_UnInit(void);
350
351 // EXTERNAL FUNCTIONS
352 int32_t polymer_init(void);
353 void polymer_uninit(void);
354 void polymer_setaspect(int32_t);
355 void polymer_glinit(void);
356 void polymer_resetlights(void);
357 void polymer_loadboard(void);
358 int32_t polymer_printtext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize);
359 void polymer_fillpolygon(int32_t npoints);
360 void polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t daposz, fix16_t daang, int32_t dahoriz, int16_t dacursectnum);
361 void polymer_drawmasks(void);
362 void polymer_editorpick(void);
363 void polymer_inb4rotatesprite(int16_t tilenum, char pal, int8_t shade, int32_t method);
364 void polymer_postrotatesprite(void);
365 void polymer_drawmaskwall(int32_t damaskwallcnt);
366 void polymer_drawsprite(int32_t snum);
367 void polymer_setanimatesprites(animatespritesptr animatesprites, int32_t x, int32_t y, int32_t z, int32_t a, int32_t smoothratio);
368 int16_t polymer_addlight(_prlight* light);
369 void polymer_deletelight(int16_t lighti);
370 void polymer_invalidatelights(void);
371 void polymer_texinvalidate(void);
372 void polymer_definehighpalookup(char basepalnum, char palnum, char *data);
373 int32_t polymer_havehighpalookup(int32_t basepalnum, int32_t palnum);
374 void polymer_setrorcallback(rorcallback callback);
375
376
377 extern _prsprite *prsprites[MAXSPRITES];
polymer_invalidatesprite(int32_t i)378 static inline void polymer_invalidatesprite(int32_t i)
379 {
380 if (prsprites[i])
381 prsprites[i]->hash = 0xDEADBEEF;
382 }
383
384 extern GLuint prartmaps[MAXTILES];
polymer_invalidateartmap(int32_t tilenum)385 static inline void polymer_invalidateartmap(int32_t tilenum)
386 {
387 if (prartmaps[tilenum])
388 {
389 glDeleteTextures(1, &prartmaps[tilenum]);
390 prartmaps[tilenum] = 0;
391 }
392 }
393
394 // Compare with eligible_for_tileshades()
polymer_eligible_for_artmap(int32_t tilenum,const pthtyp * pth)395 static inline int32_t polymer_eligible_for_artmap(int32_t tilenum, const pthtyp *pth)
396 {
397 return ((!pth || !pth->hicr) && tilenum < (MAXTILES - 4));
398 }
399
400 # ifdef POLYMER_C
401
402 // CORE
403 static void polymer_displayrooms(int16_t sectnum);
404 static void polymer_emptybuckets(void);
405 static _prbucket* polymer_findbucket(int16_t tilenum, char pal);
406 static void polymer_bucketplane(_prplane* plane);
407 static void polymer_drawplane(_prplane* plane);
408 static inline void polymer_inb4mirror(_prvert* buffer, const GLfloat* plane);
409 static void polymer_animatesprites(void);
410 static void polymer_freeboard(void);
411 // SECTORS
412 static int32_t polymer_initsector(int16_t sectnum);
413 static int32_t polymer_updatesector(int16_t sectnum);
414 void PR_CALLBACK polymer_tesserror(GLenum error);
415 void PR_CALLBACK polymer_tessedgeflag(GLenum error);
416 void PR_CALLBACK polymer_tessvertex(void* vertex, void* sector);
417 static int32_t polymer_buildfloor(int16_t sectnum);
418 static void polymer_drawsector(int16_t sectnum, int32_t domasks);
419 // WALLS
420 static int32_t polymer_initwall(int16_t wallnum);
421 static void polymer_updatewall(int16_t wallnum);
422 static void polymer_drawwall(int16_t sectnum, int16_t wallnum);
423 // HSR
424 static void polymer_computeplane(_prplane* p);
425 static inline void polymer_crossproduct(const GLfloat* in_a, const GLfloat* in_b, GLfloat* out);
426 static inline void polymer_transformpoint(const float* inpos, float* pos, const float* matrix);
427 static inline void polymer_normalize(float* vec);
428 static inline void polymer_pokesector(int16_t sectnum);
429 static void polymer_extractfrustum(GLfloat* modelview, GLfloat* projection, float* frustum);
430 static inline int32_t polymer_planeinfrustum(_prplane *plane, const float* frustum);
431 static inline void polymer_scansprites(int16_t sectnum, tspriteptr_t tsprite, int32_t* spritesortcnt);
432 static void polymer_updatesprite(int32_t snum);
433 // SKIES
434 static void polymer_getsky(void);
435 static void polymer_drawsky(int16_t tilenum, char palnum, int8_t shade);
436 static void polymer_initartsky(void);
437 static void polymer_drawartsky(int16_t tilenum, char palnum, int8_t shade);
438 static void polymer_drawartskyquad(int32_t p1, int32_t p2, GLfloat height);
439 static void polymer_drawskybox(int16_t tilenum, char palnum, int8_t shade);
440 // MDSPRITES
441 static void polymer_drawmdsprite(tspriteptr_t tspr);
442 static void polymer_loadmodelvbos(md3model_t* m);
443 // MATERIALS
444 static void polymer_getscratchmaterial(_prmaterial* material);
445 static _prbucket* polymer_getbuildmaterial(_prmaterial* material, int16_t tilenum, char pal, int8_t shade, int8_t vis, int32_t cmeth);
446 static int32_t polymer_bindmaterial(const _prmaterial *material, const int16_t* lights, int lightcount);
447 static void polymer_unbindmaterial(int32_t programbits);
448 static void polymer_compileprogram(int32_t programbits);
449 // LIGHTS
450 static void polymer_removelight(int16_t lighti);
451 static void polymer_updatelights(void);
452 static inline void polymer_resetplanelights(_prplane* plane);
453 static void polymer_addplanelight(_prplane* plane, int16_t lighti);
454 static inline void polymer_deleteplanelight(_prplane* plane, int16_t lighti);
455 static int32_t polymer_planeinlight(_prplane* plane, _prlight* light);
456 static void polymer_invalidateplanelights(_prplane* plane);
457 static void polymer_invalidatesectorlights(int16_t sectnum);
458 static void polymer_processspotlight(_prlight* light);
459 static inline void polymer_culllight(int16_t lighti);
460 static void polymer_prepareshadows(void);
461 // RENDER TARGETS
462 static void polymer_initrendertargets(int32_t count);
463 // DEBUG OUTPUT
464 void PR_CALLBACK polymer_debugoutputcallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
465
466 #define INDICE(n) ((p->indices) ? (p->indices[(i+n)%p->indicescount]) : (((i+n)%p->vertcount)))
467
468 #define SWITCH_CULL_DIRECTION { culledface = (culledface == GL_FRONT) ? GL_BACK : GL_FRONT; glCullFace(culledface); }
469
dot2f(const GLfloat * v1,const GLfloat * v2)470 static inline GLfloat dot2f(const GLfloat *v1, const GLfloat *v2)
471 {
472 return v1[0]*v2[0] + v1[1]*v2[1];
473 }
474
dot3f(const GLfloat * v1,const GLfloat * v2)475 static inline GLfloat dot3f(const GLfloat *v1, const GLfloat *v2)
476 {
477 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
478 }
479
relvec2f(const GLfloat * v1,const GLfloat * v2,GLfloat * out)480 static inline void relvec2f(const GLfloat *v1, const GLfloat *v2, GLfloat *out)
481 {
482 out[0] = v2[0]-v1[0];
483 out[1] = v2[1]-v1[1];
484 }
485
486 // the following from gle/vvector.h
487
488 /* ========================================================== */
489 /* determinant of matrix
490 *
491 * Computes determinant of matrix m, returning d
492 */
493
494 #define DETERMINANT_3X3(d,m) \
495 { \
496 d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]); \
497 d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]); \
498 d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]); \
499 }
500
501 /* ========================================================== */
502 /* i,j,th cofactor of a 4x4 matrix
503 *
504 */
505
506 #define COFACTOR_4X4_IJ(fac,m,i,j) \
507 { \
508 int ii[4], jj[4], k; \
509 \
510 /* compute which row, columnt to skip */ \
511 for (k=0; k<i; k++) ii[k] = k; \
512 for (k=i; k<3; k++) ii[k] = k+1; \
513 for (k=0; k<j; k++) jj[k] = k; \
514 for (k=j; k<3; k++) jj[k] = k+1; \
515 \
516 (fac) = m[ii[0]][jj[0]] * (m[ii[1]][jj[1]]*m[ii[2]][jj[2]] \
517 - m[ii[1]][jj[2]]*m[ii[2]][jj[1]]); \
518 (fac) -= m[ii[0]][jj[1]] * (m[ii[1]][jj[0]]*m[ii[2]][jj[2]] \
519 - m[ii[1]][jj[2]]*m[ii[2]][jj[0]]);\
520 (fac) += m[ii[0]][jj[2]] * (m[ii[1]][jj[0]]*m[ii[2]][jj[1]] \
521 - m[ii[1]][jj[1]]*m[ii[2]][jj[0]]);\
522 \
523 /* compute sign */ \
524 k = i+j; \
525 if ( k != (k/2)*2) { \
526 (fac) = -(fac); \
527 } \
528 }
529
530 /* ========================================================== */
531 /* determinant of matrix
532 *
533 * Computes determinant of matrix m, returning d
534 */
535
536 #define DETERMINANT_4X4(d,m) \
537 { \
538 double cofac; \
539 COFACTOR_4X4_IJ (cofac, m, 0, 0); \
540 d = m[0][0] * cofac; \
541 COFACTOR_4X4_IJ (cofac, m, 0, 1); \
542 d += m[0][1] * cofac; \
543 COFACTOR_4X4_IJ (cofac, m, 0, 2); \
544 d += m[0][2] * cofac; \
545 COFACTOR_4X4_IJ (cofac, m, 0, 3); \
546 d += m[0][3] * cofac; \
547 }
548
549 /* ========================================================== */
550 /* compute adjoint of matrix and scale
551 *
552 * Computes adjoint of matrix m, scales it by s, returning a
553 */
554
555 #define SCALE_ADJOINT_3X3(a,s,m) \
556 { \
557 a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
558 a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); \
559 a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
560 \
561 a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); \
562 a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); \
563 a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); \
564 \
565 a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); \
566 a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); \
567 a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); \
568 }
569
570 /* ========================================================== */
571 /* compute adjoint of matrix and scale
572 *
573 * Computes adjoint of matrix m, scales it by s, returning a
574 */
575
576 #define SCALE_ADJOINT_4X4(a,s,m) \
577 { \
578 int i,j; \
579 \
580 for (i=0; i<4; i++) { \
581 for (j=0; j<4; j++) { \
582 COFACTOR_4X4_IJ (a[j][i], m, i, j); \
583 a[j][i] *= s; \
584 } \
585 } \
586 }
587
588 /* ========================================================== */
589 /* inverse of matrix
590 *
591 * Compute inverse of matrix a, returning determinant m and
592 * inverse b
593 */
594
595 #define INVERT_3X3(b,det,a) \
596 { \
597 double tmp; \
598 DETERMINANT_3X3 (det, a); \
599 tmp = 1.0 / (det); \
600 SCALE_ADJOINT_3X3 (b, tmp, a); \
601 }
602
603 /* ========================================================== */
604 /* inverse of matrix
605 *
606 * Compute inverse of matrix a, returning determinant m and
607 * inverse b
608 */
609
610 #define INVERT_4X4(b,det,a) \
611 { \
612 double tmp; \
613 DETERMINANT_4X4 (det, a); \
614 tmp = 1.0 / (det); \
615 SCALE_ADJOINT_4X4 (b, tmp, a); \
616 }
617
618 # endif // !POLYMER_C
619
620 #ifdef __cplusplus
621 }
622 #endif
623
624 #endif // !polymer_h_
625