mirror of
https://github.com/ZDoom/Raze.git
synced 2024-12-15 07:01:15 +00:00
922aa3ca8b
Implemented using GL_LINEAR fog. The only source of difference (besides the obvious indexed vs. true color) should now be the distance constant, which still had to be determined experimentally. Polymer implements this mode in its fog fragment program part. Parallaxed skies are always drawn with full visibility, I'm not sure if there are any maps that expect otherwise. Also, accidentally committed: factor out initialization code from polymost_printext256() into gen_font_glyph_tex(), small game.c changes. git-svn-id: https://svn.eduke32.com/eduke32@3301 1a8010ca-5511-0410-912e-c29ae57300e0
537 lines
19 KiB
C
537 lines
19 KiB
C
// here lies the GREAT JUSTICE RENDERER
|
|
// TODO :
|
|
// - CORE STUFF
|
|
// o there's also the texture alignment problem Hunter reported (san andreas fault)
|
|
// o RTT portals (water)
|
|
// o clip mirrors/portals to their planes
|
|
// o merge mirrors/portals from the same plane
|
|
// - SPRITES
|
|
// o sprite panning
|
|
// - SKIES
|
|
// o skyview
|
|
// - MDSPRITES
|
|
// o need full translation and rotation support from CON to attach to game world or tags
|
|
//
|
|
// the renderer should hopefully be pretty solid after all that
|
|
// the rest will be a bliss :)
|
|
|
|
#ifndef _polymer_h_
|
|
# define _polymer_h_
|
|
|
|
# include "compat.h"
|
|
# include "baselayer.h"
|
|
# include "build.h"
|
|
# include "glbuild.h"
|
|
# include "osd.h"
|
|
# include "hightile.h"
|
|
# include "mdsprite.h"
|
|
# include "polymost.h"
|
|
# include "pragmas.h"
|
|
|
|
#define PR_LINEAR_FOG
|
|
|
|
// CVARS
|
|
extern int32_t pr_lighting;
|
|
extern int32_t pr_normalmapping;
|
|
extern int32_t pr_specularmapping;
|
|
extern int32_t pr_shadows;
|
|
extern int32_t pr_shadowcount;
|
|
extern int32_t pr_shadowdetail;
|
|
extern int32_t pr_shadowfiltering;
|
|
extern int32_t pr_maxlightpasses;
|
|
extern int32_t pr_maxlightpriority;
|
|
extern int32_t pr_fov;
|
|
extern float pr_customaspect;
|
|
extern int32_t pr_billboardingmode;
|
|
extern int32_t pr_verbosity;
|
|
extern int32_t pr_wireframe;
|
|
extern int32_t pr_vbos;
|
|
extern int32_t pr_gpusmoothing;
|
|
extern int32_t pr_overrideparallax;
|
|
extern float pr_parallaxscale;
|
|
extern float pr_parallaxbias;
|
|
extern int32_t pr_overridespecular;
|
|
extern float pr_specularpower;
|
|
extern float pr_specularfactor;
|
|
extern int32_t pr_highpalookups;
|
|
extern int32_t pr_overridehud;
|
|
extern float pr_hudxadd;
|
|
extern float pr_hudyadd;
|
|
extern float pr_hudzadd;
|
|
extern int32_t pr_hudangadd;
|
|
extern int32_t pr_hudfov;
|
|
extern float pr_overridemodelscale;
|
|
extern int32_t pr_ati_fboworkaround;
|
|
extern int32_t pr_ati_nodepthoffset;
|
|
#ifdef __APPLE__
|
|
extern int32_t pr_ati_textureformat_one;
|
|
#endif
|
|
|
|
extern int32_t r_pr_maxlightpasses;
|
|
|
|
// MATERIAL
|
|
typedef enum {
|
|
PR_BIT_HEADER, // must be first
|
|
PR_BIT_ANIM_INTERPOLATION,
|
|
PR_BIT_LIGHTING_PASS,
|
|
PR_BIT_NORMAL_MAP,
|
|
PR_BIT_DIFFUSE_MAP,
|
|
PR_BIT_DIFFUSE_DETAIL_MAP,
|
|
PR_BIT_DIFFUSE_MODULATION,
|
|
PR_BIT_DIFFUSE_MAP2,
|
|
PR_BIT_HIGHPALOOKUP_MAP,
|
|
PR_BIT_SPECULAR_MAP,
|
|
PR_BIT_SPECULAR_MATERIAL,
|
|
PR_BIT_MIRROR_MAP,
|
|
PR_BIT_FOG,
|
|
PR_BIT_GLOW_MAP,
|
|
PR_BIT_PROJECTION_MAP,
|
|
PR_BIT_SHADOW_MAP,
|
|
PR_BIT_LIGHT_MAP,
|
|
PR_BIT_SPOT_LIGHT,
|
|
PR_BIT_POINT_LIGHT,
|
|
PR_BIT_FOOTER, // must be just before last
|
|
PR_BIT_COUNT // must be last
|
|
} prbittype;
|
|
|
|
typedef struct s_prmaterial {
|
|
// PR_BIT_ANIM_INTERPOLATION
|
|
GLfloat frameprogress;
|
|
GLfloat* nextframedata;
|
|
// PR_BIT_NORMAL_MAP
|
|
GLuint normalmap;
|
|
GLfloat normalbias[2];
|
|
GLfloat* tbn;
|
|
// PR_BIT_DIFFUSE_MAP
|
|
GLuint diffusemap;
|
|
GLfloat diffusescale[2];
|
|
// PR_BIT_HIGHPALOOKUP_MAP
|
|
GLuint highpalookupmap;
|
|
// PR_BIT_DIFFUSE_DETAIL_MAP
|
|
GLuint detailmap;
|
|
GLfloat detailscale[2];
|
|
// PR_BIT_DIFFUSE_MODULATION
|
|
GLubyte diffusemodulation[4];
|
|
// PR_BIT_SPECULAR_MAP
|
|
GLuint specmap;
|
|
// PR_BIT_SPECULAR_MATERIAL
|
|
GLfloat specmaterial[2];
|
|
// PR_BIT_MIRROR_MAP
|
|
GLuint mirrormap;
|
|
// PR_BIT_GLOW_MAP
|
|
GLuint glowmap;
|
|
// PR_BIT_SHADOW_MAP
|
|
GLboolean mdspritespace;
|
|
} _prmaterial;
|
|
|
|
typedef struct s_prrograminfo {
|
|
GLhandleARB handle;
|
|
// PR_BIT_ANIM_INTERPOLATION
|
|
GLint attrib_nextFrameData;
|
|
GLint attrib_nextFrameNormal;
|
|
GLint uniform_frameProgress;
|
|
// PR_BIT_NORMAL_MAP
|
|
GLint attrib_T;
|
|
GLint attrib_B;
|
|
GLint attrib_N;
|
|
GLint uniform_eyePosition;
|
|
GLint uniform_normalMap;
|
|
GLint uniform_normalBias;
|
|
// PR_BIT_DIFFUSE_MAP
|
|
GLint uniform_diffuseMap;
|
|
GLint uniform_diffuseScale;
|
|
// PR_BIT_HIGHPALOOKUP_MAP
|
|
GLuint uniform_highPalookupMap;
|
|
// PR_BIT_DIFFUSE_DETAIL_MAP
|
|
GLint uniform_detailMap;
|
|
GLint uniform_detailScale;
|
|
// PR_BIT_SPECULAR_MAP
|
|
GLint uniform_specMap;
|
|
// PR_BIT_SPECULAR_MATERIAL
|
|
GLint uniform_specMaterial;
|
|
// PR_BIT_MIRROR_MAP
|
|
GLint uniform_mirrorMap;
|
|
#ifdef PR_LINEAR_FOG
|
|
// PR_BIT_FOG
|
|
GLint uniform_linearFog;
|
|
#endif
|
|
// PR_BIT_GLOW_MAP
|
|
GLint uniform_glowMap;
|
|
// PR_BIT_PROJECTION_MAP
|
|
GLint uniform_shadowProjMatrix;
|
|
// PR_BIT_SHADOW_MAP
|
|
GLint uniform_shadowMap;
|
|
// PR_BIT_LIGHT_MAP
|
|
GLint uniform_lightMap;
|
|
// PR_BIT_SPOT_LIGHT
|
|
GLint uniform_spotDir;
|
|
GLint uniform_spotRadius;
|
|
} _prprograminfo;
|
|
|
|
#define PR_INFO_LOG_BUFFER_SIZE 8192
|
|
|
|
// Think about changing highPal[Scale|Bias] in the program bit if you change this
|
|
#define PR_HIGHPALOOKUP_BIT_DEPTH 6
|
|
#define PR_HIGHPALOOKUP_DIM (1 << PR_HIGHPALOOKUP_BIT_DEPTH)
|
|
#define PR_HIGHPALOOKUP_DATA_SIZE (4 * PR_HIGHPALOOKUP_DIM * \
|
|
PR_HIGHPALOOKUP_DIM * \
|
|
PR_HIGHPALOOKUP_DIM)
|
|
|
|
typedef struct s_prprogrambit {
|
|
int32_t bit;
|
|
const char* vert_def;
|
|
const char* vert_prog;
|
|
const char* frag_def;
|
|
const char* frag_prog;
|
|
} _prprogrambit;
|
|
|
|
#include "prlights.h"
|
|
|
|
// RENDER TARGETS
|
|
typedef struct s_prrt {
|
|
GLenum target;
|
|
GLuint color;
|
|
GLuint z;
|
|
GLuint fbo;
|
|
int32_t xdim, ydim;
|
|
} _prrt;
|
|
|
|
// BUILD DATA
|
|
typedef struct s_prplane {
|
|
// geometry
|
|
GLfloat* buffer;
|
|
int32_t vertcount;
|
|
GLuint vbo;
|
|
// attributes
|
|
GLfloat tbn[3][3];
|
|
GLfloat plane[4];
|
|
_prmaterial material;
|
|
// elements
|
|
GLushort* indices;
|
|
int32_t indicescount;
|
|
GLuint ivbo;
|
|
// lights
|
|
int16_t lights[PR_MAXLIGHTS];
|
|
uint16_t lightcount;
|
|
} _prplane;
|
|
|
|
typedef struct s_prsector {
|
|
// polymer data
|
|
GLdouble* verts;
|
|
_prplane floor;
|
|
_prplane ceil;
|
|
int16_t curindice;
|
|
int32_t indicescount;
|
|
int32_t oldindicescount;
|
|
// stuff
|
|
float wallsproffset;
|
|
float floorsproffset;
|
|
// build sector data
|
|
int32_t ceilingz, floorz;
|
|
int16_t ceilingstat, floorstat;
|
|
int16_t ceilingpicnum, ceilingheinum;
|
|
int8_t ceilingshade;
|
|
char ceilingpal, ceilingxpanning, ceilingypanning;
|
|
int16_t floorpicnum, floorheinum;
|
|
int8_t floorshade;
|
|
char floorpal, floorxpanning, floorypanning;
|
|
|
|
struct {
|
|
int32_t empty : 1;
|
|
int32_t uptodate : 1;
|
|
int32_t invalidtex : 1;
|
|
} flags;
|
|
uint32_t invalidid;
|
|
} _prsector;
|
|
|
|
typedef struct s_prwall {
|
|
_prplane wall;
|
|
_prplane over;
|
|
_prplane mask;
|
|
// stuff
|
|
GLfloat* bigportal;
|
|
GLfloat* cap;
|
|
GLuint stuffvbo;
|
|
// build wall data
|
|
int16_t cstat, nwallcstat;
|
|
int16_t picnum, overpicnum, nwallpicnum;
|
|
int8_t shade;
|
|
char pal, xrepeat, yrepeat, xpanning, ypanning;
|
|
char nwallxpanning, nwallypanning;
|
|
int8_t nwallshade;
|
|
|
|
char underover;
|
|
uint32_t invalidid;
|
|
struct {
|
|
int32_t empty : 1;
|
|
int32_t uptodate : 1;
|
|
int32_t invalidtex : 1;
|
|
} flags;
|
|
} _prwall;
|
|
|
|
typedef struct s_prsprite {
|
|
_prplane plane;
|
|
uint32_t crc;
|
|
} _prsprite;
|
|
|
|
typedef struct s_prmirror {
|
|
_prplane *plane;
|
|
int16_t sectnum;
|
|
int16_t wallnum;
|
|
} _prmirror;
|
|
|
|
typedef struct s_prhighpalookup {
|
|
char *data;
|
|
GLuint map;
|
|
} _prhighpalookup;
|
|
|
|
typedef void (*animatespritesptr)(int32_t, int32_t, int32_t, int32_t);
|
|
|
|
typedef struct s_pranimatespritesinfo {
|
|
animatespritesptr animatesprites;
|
|
int32_t x, y, a, smoothratio;
|
|
} _pranimatespritesinfo;
|
|
|
|
// this one has to be provided by the application
|
|
extern void G_Polymer_UnInit(void);
|
|
|
|
// EXTERNAL FUNCTIONS
|
|
int32_t polymer_init(void);
|
|
void polymer_uninit(void);
|
|
void polymer_setaspect(int32_t);
|
|
void polymer_glinit(void);
|
|
void polymer_resetlights(void);
|
|
void polymer_loadboard(void);
|
|
void polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t daposz, int16_t daang, int32_t dahoriz, int16_t dacursectnum);
|
|
void polymer_drawmasks(void);
|
|
void polymer_editorpick(void);
|
|
void polymer_inb4rotatesprite(int16_t tilenum, char pal, int8_t shade);
|
|
void polymer_postrotatesprite(void);
|
|
void polymer_drawmaskwall(int32_t damaskwallcnt);
|
|
void polymer_drawsprite(int32_t snum);
|
|
void polymer_setanimatesprites(animatespritesptr animatesprites, int32_t x, int32_t y, int32_t a, int32_t smoothratio);
|
|
int16_t polymer_addlight(_prlight* light);
|
|
void polymer_deletelight(int16_t lighti);
|
|
void polymer_invalidatelights(void);
|
|
void polymer_texinvalidate(void);
|
|
void polymer_definehighpalookup(char basepalnum, char palnum, char *fn);
|
|
int32_t polymer_havehighpalookup(int32_t basepalnum, int32_t palnum);
|
|
|
|
# ifdef POLYMER_C
|
|
|
|
// CORE
|
|
static void polymer_displayrooms(int16_t sectnum);
|
|
static void polymer_drawplane(_prplane* plane);
|
|
static inline void polymer_inb4mirror(GLfloat* buffer, GLfloat* plane);
|
|
static void polymer_animatesprites(void);
|
|
static void polymer_freeboard(void);
|
|
// SECTORS
|
|
static int32_t polymer_initsector(int16_t sectnum);
|
|
static int32_t polymer_updatesector(int16_t sectnum);
|
|
void PR_CALLBACK polymer_tesserror(GLenum error);
|
|
void PR_CALLBACK polymer_tessedgeflag(GLenum error);
|
|
void PR_CALLBACK polymer_tessvertex(void* vertex, void* sector);
|
|
static int32_t polymer_buildfloor(int16_t sectnum);
|
|
static void polymer_drawsector(int16_t sectnum, int32_t domasks);
|
|
// WALLS
|
|
static int32_t polymer_initwall(int16_t wallnum);
|
|
static void polymer_updatewall(int16_t wallnum);
|
|
static void polymer_drawwall(int16_t sectnum, int16_t wallnum);
|
|
// HSR
|
|
static void polymer_computeplane(_prplane* p);
|
|
static inline void polymer_crossproduct(GLfloat* in_a, GLfloat* in_b, GLfloat* out);
|
|
static inline void polymer_transformpoint(const float* inpos, float* pos, float* matrix);
|
|
static inline void polymer_normalize(float* vec);
|
|
static inline void polymer_pokesector(int16_t sectnum);
|
|
static void polymer_extractfrustum(GLfloat* modelview, GLfloat* projection, float* frustum);
|
|
static inline int32_t polymer_planeinfrustum(_prplane *plane, float* frustum);
|
|
static inline void polymer_scansprites(int16_t sectnum, spritetype* tsprite, int32_t* spritesortcnt);
|
|
static void polymer_updatesprite(int32_t snum);
|
|
// SKIES
|
|
static void polymer_getsky(void);
|
|
static void polymer_drawsky(int16_t tilenum, char palnum, int8_t shade);
|
|
static void polymer_initartsky(void);
|
|
static void polymer_drawartsky(int16_t tilenum, char palnum, int8_t shade);
|
|
static void polymer_drawartskyquad(int32_t p1, int32_t p2, GLfloat height);
|
|
static void polymer_drawskybox(int16_t tilenum, char palnum, int8_t shade);
|
|
// MDSPRITES
|
|
static void polymer_drawmdsprite(spritetype *tspr);
|
|
static void polymer_loadmodelvbos(md3model_t* m);
|
|
// MATERIALS
|
|
static void polymer_getscratchmaterial(_prmaterial* material);
|
|
static void polymer_getbuildmaterial(_prmaterial* material, int16_t tilenum, char pal, int8_t shade, int32_t cmeth);
|
|
static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights, int lightcount);
|
|
static void polymer_unbindmaterial(int32_t programbits);
|
|
static void polymer_compileprogram(int32_t programbits);
|
|
// LIGHTS
|
|
static void polymer_removelight(int16_t lighti);
|
|
static void polymer_updatelights(void);
|
|
static inline void polymer_resetplanelights(_prplane* plane);
|
|
static void polymer_addplanelight(_prplane* plane, int16_t lighti);
|
|
static inline void polymer_deleteplanelight(_prplane* plane, int16_t lighti);
|
|
static int32_t polymer_planeinlight(_prplane* plane, _prlight* light);
|
|
static void polymer_invalidateplanelights(_prplane* plane);
|
|
static void polymer_invalidatesectorlights(int16_t sectnum);
|
|
static void polymer_processspotlight(_prlight* light);
|
|
static inline void polymer_culllight(int16_t lighti);
|
|
static void polymer_prepareshadows(void);
|
|
// RENDER TARGETS
|
|
static void polymer_initrendertargets(int32_t count);
|
|
// DEBUG OUTPUT
|
|
void PR_CALLBACK polymer_debugoutputcallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
|
|
|
|
#define INDICE(n) ((p->indices) ? (p->indices[(i+n)%p->indicescount]*5) : (((i+n)%p->vertcount)*5))
|
|
|
|
#define SWITCH_CULL_DIRECTION { culledface = (culledface == GL_FRONT) ? GL_BACK : GL_FRONT; bglCullFace(culledface); }
|
|
|
|
static inline GLfloat dot2f(GLfloat *v1, GLfloat *v2)
|
|
{
|
|
return v1[0]*v2[0] + v1[1]*v2[1];
|
|
}
|
|
|
|
static inline GLfloat dot3f(GLfloat *v1, GLfloat *v2)
|
|
{
|
|
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
|
|
}
|
|
|
|
static inline void relvec2f(GLfloat *v1, GLfloat *v2, GLfloat *out)
|
|
{
|
|
out[0] = v2[0]-v1[0];
|
|
out[1] = v2[1]-v1[1];
|
|
}
|
|
|
|
// the following from gle/vvector.h
|
|
|
|
/* ========================================================== */
|
|
/* determinant of matrix
|
|
*
|
|
* Computes determinant of matrix m, returning d
|
|
*/
|
|
|
|
#define DETERMINANT_3X3(d,m) \
|
|
{ \
|
|
d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]); \
|
|
d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]); \
|
|
d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]); \
|
|
}
|
|
|
|
/* ========================================================== */
|
|
/* i,j,th cofactor of a 4x4 matrix
|
|
*
|
|
*/
|
|
|
|
#define COFACTOR_4X4_IJ(fac,m,i,j) \
|
|
{ \
|
|
int ii[4], jj[4], k; \
|
|
\
|
|
/* compute which row, columnt to skip */ \
|
|
for (k=0; k<i; k++) ii[k] = k; \
|
|
for (k=i; k<3; k++) ii[k] = k+1; \
|
|
for (k=0; k<j; k++) jj[k] = k; \
|
|
for (k=j; k<3; k++) jj[k] = k+1; \
|
|
\
|
|
(fac) = m[ii[0]][jj[0]] * (m[ii[1]][jj[1]]*m[ii[2]][jj[2]] \
|
|
- m[ii[1]][jj[2]]*m[ii[2]][jj[1]]); \
|
|
(fac) -= m[ii[0]][jj[1]] * (m[ii[1]][jj[0]]*m[ii[2]][jj[2]] \
|
|
- m[ii[1]][jj[2]]*m[ii[2]][jj[0]]);\
|
|
(fac) += m[ii[0]][jj[2]] * (m[ii[1]][jj[0]]*m[ii[2]][jj[1]] \
|
|
- m[ii[1]][jj[1]]*m[ii[2]][jj[0]]);\
|
|
\
|
|
/* compute sign */ \
|
|
k = i+j; \
|
|
if ( k != (k/2)*2) { \
|
|
(fac) = -(fac); \
|
|
} \
|
|
}
|
|
|
|
/* ========================================================== */
|
|
/* determinant of matrix
|
|
*
|
|
* Computes determinant of matrix m, returning d
|
|
*/
|
|
|
|
#define DETERMINANT_4X4(d,m) \
|
|
{ \
|
|
double cofac; \
|
|
COFACTOR_4X4_IJ (cofac, m, 0, 0); \
|
|
d = m[0][0] * cofac; \
|
|
COFACTOR_4X4_IJ (cofac, m, 0, 1); \
|
|
d += m[0][1] * cofac; \
|
|
COFACTOR_4X4_IJ (cofac, m, 0, 2); \
|
|
d += m[0][2] * cofac; \
|
|
COFACTOR_4X4_IJ (cofac, m, 0, 3); \
|
|
d += m[0][3] * cofac; \
|
|
}
|
|
|
|
/* ========================================================== */
|
|
/* compute adjoint of matrix and scale
|
|
*
|
|
* Computes adjoint of matrix m, scales it by s, returning a
|
|
*/
|
|
|
|
#define SCALE_ADJOINT_3X3(a,s,m) \
|
|
{ \
|
|
a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
|
|
a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); \
|
|
a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
|
|
\
|
|
a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); \
|
|
a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); \
|
|
a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); \
|
|
\
|
|
a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); \
|
|
a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); \
|
|
a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); \
|
|
}
|
|
|
|
/* ========================================================== */
|
|
/* compute adjoint of matrix and scale
|
|
*
|
|
* Computes adjoint of matrix m, scales it by s, returning a
|
|
*/
|
|
|
|
#define SCALE_ADJOINT_4X4(a,s,m) \
|
|
{ \
|
|
int i,j; \
|
|
\
|
|
for (i=0; i<4; i++) { \
|
|
for (j=0; j<4; j++) { \
|
|
COFACTOR_4X4_IJ (a[j][i], m, i, j); \
|
|
a[j][i] *= s; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
/* ========================================================== */
|
|
/* inverse of matrix
|
|
*
|
|
* Compute inverse of matrix a, returning determinant m and
|
|
* inverse b
|
|
*/
|
|
|
|
#define INVERT_3X3(b,det,a) \
|
|
{ \
|
|
double tmp; \
|
|
DETERMINANT_3X3 (det, a); \
|
|
tmp = 1.0 / (det); \
|
|
SCALE_ADJOINT_3X3 (b, tmp, a); \
|
|
}
|
|
|
|
/* ========================================================== */
|
|
/* inverse of matrix
|
|
*
|
|
* Compute inverse of matrix a, returning determinant m and
|
|
* inverse b
|
|
*/
|
|
|
|
#define INVERT_4X4(b,det,a) \
|
|
{ \
|
|
double tmp; \
|
|
DETERMINANT_4X4 (det, a); \
|
|
tmp = 1.0 / (det); \
|
|
SCALE_ADJOINT_4X4 (b, tmp, a); \
|
|
}
|
|
|
|
# endif // !POLYMER_C
|
|
|
|
#endif // !_polymer_h_
|