Model normal mapping support. This calculates the averaged texture-tangent basis for every face of every model when loading them, so this change will make startup times a lot worse until we implement a way to cache the computed models to disk.

git-svn-id: https://svn.eduke32.com/eduke32@1594 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
plagman 2010-01-24 05:57:43 +00:00
parent e65891aad6
commit 0d6dc3a531
3 changed files with 407 additions and 111 deletions

View file

@ -86,10 +86,10 @@ typedef struct s_prmaterial {
// PR_BIT_ANIM_INTERPOLATION // PR_BIT_ANIM_INTERPOLATION
GLfloat frameprogress; GLfloat frameprogress;
GLfloat* nextframedata; GLfloat* nextframedata;
GLsizei nextframedatastride;
// PR_BIT_NORMAL_MAP // PR_BIT_NORMAL_MAP
GLuint normalmap; GLuint normalmap;
GLfloat normalbias[2]; GLfloat normalbias[2];
GLfloat* tbn;
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
GLuint diffusemap; GLuint diffusemap;
GLfloat diffusescale[2]; GLfloat diffusescale[2];
@ -212,7 +212,7 @@ typedef struct s_prplane {
int32_t vertcount; int32_t vertcount;
GLuint vbo; GLuint vbo;
// attributes // attributes
GLfloat tbn[9]; GLfloat tbn[3][3];
GLfloat plane[4]; GLfloat plane[4];
_prmaterial material; _prmaterial material;
// elements // elements
@ -331,7 +331,6 @@ static void polymer_drawwall(int16_t sectnum, int16_t wallnum);
static void polymer_computeplane(_prplane* p); static void polymer_computeplane(_prplane* p);
static inline void polymer_crossproduct(GLfloat* in_a, GLfloat* in_b, GLfloat* out); static inline void polymer_crossproduct(GLfloat* in_a, GLfloat* in_b, GLfloat* out);
static inline void polymer_transformpoint(float* inpos, float* pos, float* matrix); static inline void polymer_transformpoint(float* inpos, float* pos, float* matrix);
static inline void polymer_invertmatrix(float* m, float* out);
static inline void polymer_normalize(float* vec); static inline void polymer_normalize(float* vec);
static inline void polymer_pokesector(int16_t sectnum); static inline void polymer_pokesector(int16_t sectnum);
static void polymer_extractfrustum(GLfloat* modelview, GLfloat* projection, float* frustum); static void polymer_extractfrustum(GLfloat* modelview, GLfloat* projection, float* frustum);
@ -369,6 +368,138 @@ static void polymer_prepareshadows(void);
// RENDER TARGETS // RENDER TARGETS
static void polymer_initrendertargets(int32_t count); static void polymer_initrendertargets(int32_t count);
// 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_C
#endif // !_polymer_h_ #endif // !_polymer_h_

View file

@ -1437,11 +1437,50 @@ static md3model_t *md3load(int32_t fil)
return(m); return(m);
} }
static inline void invertmatrix(float* m, float* out)
{
float det;
det = m[0] * (m[4]*m[8] - m[5] * m[7]);
det -= m[1] * (m[3]*m[8] - m[5] * m[6]);
det += m[2] * (m[3]*m[7] - m[4] * m[6]);
det = 1.0f / det;
out[0] = det * (m[4] * m[8] - m[5] * m[7]);
out[3] = det * (m[5] * m[6] - m[3] * m[8]);
out[6] = det * (m[3] * m[7] - m[1] * m[6]);
out[1] = det * (m[2] * m[7] - m[1] * m[8]);
out[4] = det * (m[0] * m[8] - m[2] * m[6]);
out[7] = det * (m[1] * m[6] - m[0] * m[7]);
out[2] = det * (m[1] * m[5] - m[2] * m[4]);
out[5] = det * (m[2] * m[3] - m[0] * m[5]);
out[8] = det * (m[0] * m[4] - m[1] * m[3]);
}
static inline void normalize(float* vec)
{
double norm;
norm = vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2];
norm = sqrt(norm);
norm = 1.0 / norm;
vec[0] *= norm;
vec[1] *= norm;
vec[2] *= norm;
}
static void md3postload(md3model_t* m) static void md3postload(md3model_t* m)
{ {
int framei, surfi, verti; int framei, surfi, verti, trii, i;
md3surf_t *s;
md3frame_t *frame;
md3xyzn_t *frameverts; md3xyzn_t *frameverts;
float dist, lat, lng, vec[3]; int *numtris;
float dist, lat, lng, vec1[5], vec2[5], mat[9], r;
// apparently we can't trust loaded models bounding box/sphere information, // apparently we can't trust loaded models bounding box/sphere information,
// so let's compute it ourselves // so let's compute it ourselves
@ -1450,15 +1489,17 @@ static void md3postload(md3model_t* m)
while (framei < m->head.numframes) while (framei < m->head.numframes)
{ {
m->head.frames[framei].min.x = 0.0f; frame = &m->head.frames[framei];
m->head.frames[framei].min.y = 0.0f;
m->head.frames[framei].min.z = 0.0f;
m->head.frames[framei].max.x = 0.0f; frame->min.x = 0.0f;
m->head.frames[framei].max.y = 0.0f; frame->min.y = 0.0f;
m->head.frames[framei].max.z = 0.0f; frame->min.z = 0.0f;
m->head.frames[framei].r = 0.0f; frame->max.x = 0.0f;
frame->max.y = 0.0f;
frame->max.z = 0.0f;
frame->r = 0.0f;
surfi = 0; surfi = 0;
while (surfi < m->head.numsurfs) while (surfi < m->head.numsurfs)
@ -1470,30 +1511,30 @@ static void md3postload(md3model_t* m)
{ {
if (!verti && !surfi) if (!verti && !surfi)
{ {
m->head.frames[framei].min.x = frameverts[verti].x; frame->min.x = frameverts[verti].x;
m->head.frames[framei].min.y = frameverts[verti].y; frame->min.y = frameverts[verti].y;
m->head.frames[framei].min.z = frameverts[verti].z; frame->min.z = frameverts[verti].z;
m->head.frames[framei].max.x = frameverts[verti].x; frame->max.x = frameverts[verti].x;
m->head.frames[framei].max.y = frameverts[verti].y; frame->max.y = frameverts[verti].y;
m->head.frames[framei].max.z = frameverts[verti].z; frame->max.z = frameverts[verti].z;
} }
else else
{ {
if (m->head.frames[framei].min.x > frameverts[verti].x) if (frame->min.x > frameverts[verti].x)
m->head.frames[framei].min.x = frameverts[verti].x; frame->min.x = frameverts[verti].x;
if (m->head.frames[framei].max.x < frameverts[verti].x) if (frame->max.x < frameverts[verti].x)
m->head.frames[framei].max.x = frameverts[verti].x; frame->max.x = frameverts[verti].x;
if (m->head.frames[framei].min.y > frameverts[verti].y) if (frame->min.y > frameverts[verti].y)
m->head.frames[framei].min.y = frameverts[verti].y; frame->min.y = frameverts[verti].y;
if (m->head.frames[framei].max.y < frameverts[verti].y) if (frame->max.y < frameverts[verti].y)
m->head.frames[framei].max.y = frameverts[verti].y; frame->max.y = frameverts[verti].y;
if (m->head.frames[framei].min.z > frameverts[verti].z) if (frame->min.z > frameverts[verti].z)
m->head.frames[framei].min.z = frameverts[verti].z; frame->min.z = frameverts[verti].z;
if (m->head.frames[framei].max.z < frameverts[verti].z) if (frame->max.z < frameverts[verti].z)
m->head.frames[framei].max.z = frameverts[verti].z; frame->max.z = frameverts[verti].z;
} }
verti++; verti++;
@ -1501,9 +1542,9 @@ static void md3postload(md3model_t* m)
surfi++; surfi++;
} }
m->head.frames[framei].cen.x = (m->head.frames[framei].min.x + m->head.frames[framei].max.x) / 2.0f; frame->cen.x = (frame->min.x + frame->max.x) / 2.0f;
m->head.frames[framei].cen.y = (m->head.frames[framei].min.y + m->head.frames[framei].max.y) / 2.0f; frame->cen.y = (frame->min.y + frame->max.y) / 2.0f;
m->head.frames[framei].cen.z = (m->head.frames[framei].min.z + m->head.frames[framei].max.z) / 2.0f; frame->cen.z = (frame->min.z + frame->max.z) / 2.0f;
surfi = 0; surfi = 0;
while (surfi < m->head.numsurfs) while (surfi < m->head.numsurfs)
@ -1513,21 +1554,21 @@ static void md3postload(md3model_t* m)
verti = 0; verti = 0;
while (verti < m->head.surfs[surfi].numverts) while (verti < m->head.surfs[surfi].numverts)
{ {
vec[0] = frameverts[verti].x - m->head.frames[framei].cen.x; vec1[0] = frameverts[verti].x - frame->cen.x;
vec[1] = frameverts[verti].y - m->head.frames[framei].cen.y; vec1[1] = frameverts[verti].y - frame->cen.y;
vec[2] = frameverts[verti].z - m->head.frames[framei].cen.z; vec1[2] = frameverts[verti].z - frame->cen.z;
dist = vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]; dist = vec1[0] * vec1[0] + vec1[1] * vec1[1] + vec1[2] * vec1[2];
if (dist > m->head.frames[framei].r) if (dist > frame->r)
m->head.frames[framei].r = dist; frame->r = dist;
verti++; verti++;
} }
surfi++; surfi++;
} }
m->head.frames[framei].r = sqrt(m->head.frames[framei].r); frame->r = sqrt(frame->r);
framei++; framei++;
} }
@ -1537,29 +1578,117 @@ static void md3postload(md3model_t* m)
surfi = 0; surfi = 0;
while (surfi < m->head.numsurfs) while (surfi < m->head.numsurfs)
{ {
m->head.surfs[surfi].geometry = nedpmalloc(model_data_pool, m->head.numframes * m->head.surfs[surfi].numverts * sizeof(float) * 6); s = &m->head.surfs[surfi];
s->geometry = nedpcalloc(model_data_pool, m->head.numframes * s->numverts * sizeof(float), 15);
numtris = nedpcalloc(model_data_pool, s->numverts, sizeof(int));
verti = 0; verti = 0;
while (verti < (m->head.numframes * m->head.surfs[surfi].numverts)) while (verti < (m->head.numframes * s->numverts))
{ {
m->head.surfs[surfi].geometry[(verti * 6) + 0] = m->head.surfs[surfi].xyzn[verti].x; s->geometry[(verti * 15) + 0] = s->xyzn[verti].x;
m->head.surfs[surfi].geometry[(verti * 6) + 1] = m->head.surfs[surfi].xyzn[verti].y; s->geometry[(verti * 15) + 1] = s->xyzn[verti].y;
m->head.surfs[surfi].geometry[(verti * 6) + 2] = m->head.surfs[surfi].xyzn[verti].z; s->geometry[(verti * 15) + 2] = s->xyzn[verti].z;
// normal extraction from packed spherical coordinates // normal extraction from packed spherical coordinates
// FIXME: swapping lat and lng because of npherno's compiler // FIXME: swapping lat and lng because of npherno's compiler
lat = m->head.surfs[surfi].xyzn[verti].nlng * (2 * PI) / 255.0f; lat = s->xyzn[verti].nlng * (2 * PI) / 255.0f;
lng = m->head.surfs[surfi].xyzn[verti].nlat * (2 * PI) / 255.0f; lng = s->xyzn[verti].nlat * (2 * PI) / 255.0f;
m->head.surfs[surfi].geometry[(verti * 6) + 3] = cos(lat) * sin(lng); s->geometry[(verti * 15) + 3] = cos(lat) * sin(lng);
m->head.surfs[surfi].geometry[(verti * 6) + 4] = sin(lat) * sin(lng); s->geometry[(verti * 15) + 4] = sin(lat) * sin(lng);
m->head.surfs[surfi].geometry[(verti * 6) + 5] = cos(lng); s->geometry[(verti * 15) + 5] = cos(lng);
verti++; verti++;
} }
trii = 0;
while (trii < s->numtris)
{
// let the vertices know they're being referenced by a triangle
numtris[s->tris[trii].i[0]]++;
numtris[s->tris[trii].i[1]]++;
numtris[s->tris[trii].i[2]]++;
framei = 0;
while (framei < m->head.numframes)
{
vec1[0] = s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[1] * 15) + 0] -
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[0] * 15) + 0];
vec1[1] = s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[1] * 15) + 1] -
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[0] * 15) + 1];
vec1[2] = s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[1] * 15) + 2] -
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[0] * 15) + 2];
vec1[3] = s->uv[s->tris[trii].i[1]].u - s->uv[s->tris[trii].i[0]].u;
vec1[4] = s->uv[s->tris[trii].i[1]].v - s->uv[s->tris[trii].i[0]].v;
vec2[0] = s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[2] * 15) + 0] -
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[1] * 15) + 0];
vec2[1] = s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[2] * 15) + 1] -
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[1] * 15) + 1];
vec2[2] = s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[2] * 15) + 2] -
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[1] * 15) + 2];
vec2[3] = s->uv[s->tris[trii].i[2]].u - s->uv[s->tris[trii].i[1]].u;
vec2[4] = s->uv[s->tris[trii].i[2]].v - s->uv[s->tris[trii].i[1]].v;
r = 1.0 / (vec1[3] * vec2[4] - vec2[3] * vec1[4]);
// tangent
mat[0] = (vec2[4] * vec1[0] - vec1[4] * vec2[0]) * r;
mat[1] = (vec2[4] * vec1[1] - vec1[4] * vec2[1]) * r;
mat[2] = (vec2[4] * vec1[2] - vec1[4] * vec2[2]) * r;
normalize(&mat[0]);
// bitangent
mat[3] = (vec1[3] * vec2[0] - vec2[3] * vec1[0]) * r;
mat[4] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r;
mat[5] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r;
normalize(&mat[3]);
// T and B are shared for the three vertices in that triangle
i = 0;
while (i < 6)
{
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[0] * 15) + 6 + i] += mat[i];
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[1] * 15) + 6 + i] += mat[i];
s->geometry[(framei * s->numverts * 15) + (s->tris[trii].i[2] * 15) + 6 + i] += mat[i];
i++;
}
framei++;
}
trii++;
}
// now that we accumulated the TBNs, average and invert them for each vertex
verti = 0;
while (verti < (m->head.numframes * s->numverts))
{
i = 6;
while (i < 12)
{
s->geometry[(verti * 15) + i] /= numtris[verti % s->numverts];
i++;
}
// copy N over
s->geometry[(verti * 15) + 12] = s->geometry[(verti * 15) + 3];
s->geometry[(verti * 15) + 13] = s->geometry[(verti * 15) + 4];
s->geometry[(verti * 15) + 14] = s->geometry[(verti * 15) + 5];
invertmatrix(&s->geometry[(verti * 15) + 6], mat);
memcpy(&s->geometry[(verti * 15) + 6], mat, sizeof(float) * 9);
verti++;
}
nedpfree(model_data_pool, numtris);
surfi++; surfi++;
} }
} }
static int32_t md3draw(md3model_t *m, spritetype *tspr) static int32_t md3draw(md3model_t *m, spritetype *tspr)

View file

@ -547,6 +547,7 @@ _prrt *prrts;
// CONTROL // CONTROL
GLfloat spritemodelview[16]; GLfloat spritemodelview[16];
GLfloat mdspritespace[4][4];
GLfloat rootmodelviewmatrix[16]; GLfloat rootmodelviewmatrix[16];
GLfloat *curmodelviewmatrix; GLfloat *curmodelviewmatrix;
GLfloat rootskymodelviewmatrix[16]; GLfloat rootskymodelviewmatrix[16];
@ -1706,9 +1707,9 @@ static void polymer_drawplane(_prplane* plane)
if (materialbits & prprogrambits[PR_BIT_NORMAL_MAP].bit) if (materialbits & prprogrambits[PR_BIT_NORMAL_MAP].bit)
{ {
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_T, &plane->tbn[0]); bglVertexAttrib3fvARB(prprograms[materialbits].attrib_T, &plane->tbn[0][0]);
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_B, &plane->tbn[3]); bglVertexAttrib3fvARB(prprograms[materialbits].attrib_B, &plane->tbn[1][0]);
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_N, &plane->tbn[6]); bglVertexAttrib3fvARB(prprograms[materialbits].attrib_N, &plane->tbn[2][0]);
} }
if (plane->indices) if (plane->indices)
@ -2905,7 +2906,8 @@ static void polymer_computeplane(_prplane* p)
// hack to work around a precision issue with slopes // hack to work around a precision issue with slopes
if (norm >= 15000) if (norm >= 15000)
{ {
float tangent[9]; float tangent[3][3];
double det;
// normalize the normal/plane equation and calculate its plane norm // normalize the normal/plane equation and calculate its plane norm
norm = -sqrt(norm); norm = -sqrt(norm);
@ -2919,25 +2921,25 @@ static void polymer_computeplane(_prplane* p)
r = 1.0 / (vec1[3] * vec2[4] - vec2[3] * vec1[4]); r = 1.0 / (vec1[3] * vec2[4] - vec2[3] * vec1[4]);
// tangent // tangent
tangent[0] = (vec2[4] * vec1[0] - vec1[4] * vec2[0]) * r; tangent[0][0] = (vec2[4] * vec1[0] - vec1[4] * vec2[0]) * r;
tangent[1] = (vec2[4] * vec1[1] - vec1[4] * vec2[1]) * r; tangent[0][1] = (vec2[4] * vec1[1] - vec1[4] * vec2[1]) * r;
tangent[2] = (vec2[4] * vec1[2] - vec1[4] * vec2[2]) * r; tangent[0][2] = (vec2[4] * vec1[2] - vec1[4] * vec2[2]) * r;
polymer_normalize(&tangent[0]); polymer_normalize(&tangent[0][0]);
// bitangent // bitangent
tangent[3] = (vec1[3] * vec2[0] - vec2[3] * vec1[0]) * r; tangent[1][0] = (vec1[3] * vec2[0] - vec2[3] * vec1[0]) * r;
tangent[4] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r; tangent[1][1] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r;
tangent[5] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r; tangent[1][2] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r;
polymer_normalize(&tangent[3]); polymer_normalize(&tangent[1][0]);
// normal // normal
tangent[6] = plane[0]; tangent[2][0] = plane[0];
tangent[7] = plane[1]; tangent[2][1] = plane[1];
tangent[8] = plane[2]; tangent[2][2] = plane[2];
polymer_invertmatrix(tangent, p->tbn); INVERT_3X3(p->tbn, det, tangent);
break; break;
} }
@ -2970,29 +2972,6 @@ static inline void polymer_transformpoint(float* inpos, float* pos, float* matr
+ matrix[14]; + matrix[14];
} }
static inline void polymer_invertmatrix(float* m, float* out)
{
float det;
det = m[0] * (m[4]*m[8] - m[5] * m[7]);
det -= m[1] * (m[3]*m[8] - m[5] * m[6]);
det += m[2] * (m[3]*m[7] - m[4] * m[6]);
det = 1.0f / det;
out[0] = det * (m[4] * m[8] - m[5] * m[7]);
out[3] = det * (m[5] * m[6] - m[3] * m[8]);
out[6] = det * (m[3] * m[7] - m[1] * m[6]);
out[1] = det * (m[2] * m[7] - m[1] * m[8]);
out[4] = det * (m[0] * m[8] - m[2] * m[6]);
out[7] = det * (m[1] * m[6] - m[0] * m[7]);
out[2] = det * (m[1] * m[5] - m[2] * m[4]);
out[5] = det * (m[2] * m[3] - m[0] * m[5]);
out[8] = det * (m[0] * m[4] - m[1] * m[3]);
}
static inline void polymer_normalize(float* vec) static inline void polymer_normalize(float* vec)
{ {
double norm; double norm;
@ -3313,9 +3292,10 @@ static void polymer_drawmdsprite(spritetype *tspr)
float *v0, *v1; float *v0, *v1;
md3surf_t *s; md3surf_t *s;
char lpal; char lpal;
float spos[3], tspos[3], lpos[3], tlpos[3], vec[3]; float spos[3], tspos[3], lpos[3], tlpos[3], vec[3], mat[4][4];
float ang; float ang;
float scale; float scale;
double det;
int32_t surfi, i, j; int32_t surfi, i, j;
GLubyte* color; GLubyte* color;
int32_t materialbits; int32_t materialbits;
@ -3398,6 +3378,10 @@ static void polymer_drawmdsprite(spritetype *tspr)
bglPushMatrix(); bglPushMatrix();
bglMultMatrixf(spritemodelview); bglMultMatrixf(spritemodelview);
// invert this matrix to get the polymer -> mdsprite space
memcpy(mat, spritemodelview, sizeof(float) * 16);
INVERT_4X4(mdspritespace, det, mat);
// debug code for drawing the model bounding sphere // debug code for drawing the model bounding sphere
// bglDisable(GL_TEXTURE_2D); // bglDisable(GL_TEXTURE_2D);
// bglBegin(GL_LINES); // bglBegin(GL_LINES);
@ -3545,8 +3529,8 @@ static void polymer_drawmdsprite(spritetype *tspr)
for (surfi=0;surfi<m->head.numsurfs;surfi++) for (surfi=0;surfi<m->head.numsurfs;surfi++)
{ {
s = &m->head.surfs[surfi]; s = &m->head.surfs[surfi];
v0 = &s->geometry[m->cframe*s->numverts*6]; v0 = &s->geometry[m->cframe*s->numverts*15];
v1 = &s->geometry[m->nframe*s->numverts*6]; v1 = &s->geometry[m->nframe*s->numverts*15];
// debug code for drawing model normals // debug code for drawing model normals
// bglDisable(GL_TEXTURE_2D); // bglDisable(GL_TEXTURE_2D);
@ -3585,6 +3569,20 @@ static void polymer_drawmdsprite(spritetype *tspr)
mdspritematerial.detailscale[0] = mdspritematerial.detailscale[1] = sk->param; mdspritematerial.detailscale[0] = mdspritematerial.detailscale[1] = sk->param;
} }
if (!(tspr->cstat&1024))
{
mdspritematerial.normalmap =
mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,NORMALPAL,surfi);
for (sk = m->skinmap; sk; sk = sk->next)
if ((int32_t)sk->palette == NORMALPAL &&
sk->skinnum == tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum &&
sk->surfnum == surfi) {
mdspritematerial.normalbias[0] = sk->specpower;
mdspritematerial.normalbias[1] = sk->specfactor;
}
}
for (sk = m->skinmap; sk; sk = sk->next) for (sk = m->skinmap; sk; sk = sk->next)
if ((int32_t)sk->palette == tspr->pal && if ((int32_t)sk->palette == tspr->pal &&
sk->skinnum == tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum && sk->skinnum == tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum &&
@ -3609,13 +3607,13 @@ static void polymer_drawmdsprite(spritetype *tspr)
bglTexCoordPointer(2, GL_FLOAT, 0, 0); bglTexCoordPointer(2, GL_FLOAT, 0, 0);
bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->geometry[surfi]); bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->geometry[surfi]);
bglVertexPointer(3, GL_FLOAT, sizeof(float) * 6, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 6)); bglVertexPointer(3, GL_FLOAT, sizeof(float) * 15, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15));
bglNormalPointer(GL_FLOAT, sizeof(float) * 6, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 6) + 3); bglNormalPointer(GL_FLOAT, sizeof(float) * 15, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15) + 3);
if (pr_gpusmoothing) mdspritematerial.tbn = (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15) + 6;
{
mdspritematerial.nextframedata = (GLfloat*)(m->nframe * s->numverts * sizeof(float) * 6); if (pr_gpusmoothing) {
mdspritematerial.nextframedatastride = sizeof(float) * 6; mdspritematerial.nextframedata = (GLfloat*)(m->nframe * s->numverts * sizeof(float) * 15);
} }
bglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m->indices[surfi]); bglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m->indices[surfi]);
@ -3634,14 +3632,14 @@ static void polymer_drawmdsprite(spritetype *tspr)
} }
else else
{ {
bglVertexPointer(3, GL_FLOAT, sizeof(float) * 6, v0); bglVertexPointer(3, GL_FLOAT, sizeof(float) * 15, v0);
bglNormalPointer(GL_FLOAT, sizeof(float) * 6, v0 + 3); bglNormalPointer(GL_FLOAT, sizeof(float) * 15, v0 + 3);
bglTexCoordPointer(2, GL_FLOAT, 0, s->uv); bglTexCoordPointer(2, GL_FLOAT, 0, s->uv);
if (pr_gpusmoothing) mdspritematerial.tbn = v0 + 6;
{
if (pr_gpusmoothing) {
mdspritematerial.nextframedata = (GLfloat*)(v1); mdspritematerial.nextframedata = (GLfloat*)(v1);
mdspritematerial.nextframedatastride = sizeof(float) * 6;
} }
curlight = 0; curlight = 0;
@ -3689,7 +3687,7 @@ static void polymer_loadmodelvbos(md3model_t* m)
bglBufferDataARB(GL_ARRAY_BUFFER_ARB, s->numverts * sizeof(md3uv_t), s->uv, modelvbousage); bglBufferDataARB(GL_ARRAY_BUFFER_ARB, s->numverts * sizeof(md3uv_t), s->uv, modelvbousage);
bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->geometry[i]); bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->geometry[i]);
bglBufferDataARB(GL_ARRAY_BUFFER_ARB, s->numframes * s->numverts * sizeof(float) * 6, s->geometry, modelvbousage); bglBufferDataARB(GL_ARRAY_BUFFER_ARB, s->numframes * s->numverts * sizeof(float) * (15), s->geometry, modelvbousage);
bglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); bglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
i++; i++;
@ -3705,10 +3703,10 @@ static void polymer_getscratchmaterial(_prmaterial* material)
// PR_BIT_ANIM_INTERPOLATION // PR_BIT_ANIM_INTERPOLATION
material->frameprogress = 0.0f; material->frameprogress = 0.0f;
material->nextframedata = NULL; material->nextframedata = NULL;
material->nextframedatastride = 0;
// PR_BIT_NORMAL_MAP // PR_BIT_NORMAL_MAP
material->normalmap = 0; material->normalmap = 0;
material->normalbias[0] = material->normalbias[1] = 0.0f; material->normalbias[0] = material->normalbias[1] = 0.0f;
material->tbn = NULL;
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
material->diffusemap = 0; material->diffusemap = 0;
material->diffusescale[0] = material->diffusescale[1] = 1.0f; material->diffusescale[0] = material->diffusescale[1] = 1.0f;
@ -3827,7 +3825,7 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
// --------- bit validation // --------- bit validation
// PR_BIT_ANIM_INTERPOLATION // PR_BIT_ANIM_INTERPOLATION
if (material.nextframedatastride) if (material.nextframedata)
programbits |= prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit; programbits |= prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit;
// PR_BIT_LIGHTING_PASS // PR_BIT_LIGHTING_PASS
@ -3909,12 +3907,12 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
bglEnableVertexAttribArrayARB(prprograms[programbits].attrib_nextFrameNormal); bglEnableVertexAttribArrayARB(prprograms[programbits].attrib_nextFrameNormal);
bglVertexAttribPointerARB(prprograms[programbits].attrib_nextFrameData, bglVertexAttribPointerARB(prprograms[programbits].attrib_nextFrameData,
3, GL_FLOAT, GL_FALSE, 3, GL_FLOAT, GL_FALSE,
material.nextframedatastride, sizeof(float) * 15,
material.nextframedata); material.nextframedata);
if (prprograms[programbits].attrib_nextFrameNormal != -1) if (prprograms[programbits].attrib_nextFrameNormal != -1)
bglVertexAttribPointerARB(prprograms[programbits].attrib_nextFrameNormal, bglVertexAttribPointerARB(prprograms[programbits].attrib_nextFrameNormal,
3, GL_FLOAT, GL_FALSE, 3, GL_FLOAT, GL_FALSE,
material.nextframedatastride, sizeof(float) * 15,
material.nextframedata + 3); material.nextframedata + 3);
bglUniform1fARB(prprograms[programbits].uniform_frameProgress, material.frameprogress); bglUniform1fARB(prprograms[programbits].uniform_frameProgress, material.frameprogress);
@ -3939,7 +3937,12 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
bglActiveTextureARB(texunit + GL_TEXTURE0_ARB); bglActiveTextureARB(texunit + GL_TEXTURE0_ARB);
bglBindTexture(GL_TEXTURE_2D, material.normalmap); bglBindTexture(GL_TEXTURE_2D, material.normalmap);
bglUniform3fvARB(prprograms[programbits].uniform_eyePosition, 1, pos); if (material.mdspritespace == GL_TRUE) {
float mdspritespacepos[3];
polymer_transformpoint(pos, mdspritespacepos, (float *)mdspritespace);
bglUniform3fvARB(prprograms[programbits].uniform_eyePosition, 1, mdspritespacepos);
} else
bglUniform3fvARB(prprograms[programbits].uniform_eyePosition, 1, pos);
bglUniform1iARB(prprograms[programbits].uniform_normalMap, texunit); bglUniform1iARB(prprograms[programbits].uniform_normalMap, texunit);
if (pr_overrideparallax) { if (pr_overrideparallax) {
bias[0] = pr_parallaxscale; bias[0] = pr_parallaxscale;
@ -3948,6 +3951,25 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
} else } else
bglUniform2fvARB(prprograms[programbits].uniform_normalBias, 1, material.normalbias); bglUniform2fvARB(prprograms[programbits].uniform_normalBias, 1, material.normalbias);
if (material.tbn) {
bglEnableVertexAttribArrayARB(prprograms[programbits].attrib_T);
bglEnableVertexAttribArrayARB(prprograms[programbits].attrib_B);
bglEnableVertexAttribArrayARB(prprograms[programbits].attrib_N);
bglVertexAttribPointerARB(prprograms[programbits].attrib_T,
3, GL_FLOAT, GL_FALSE,
sizeof(float) * 15,
material.tbn);
bglVertexAttribPointerARB(prprograms[programbits].attrib_B,
3, GL_FLOAT, GL_FALSE,
sizeof(float) * 15,
material.tbn + 3);
bglVertexAttribPointerARB(prprograms[programbits].attrib_N,
3, GL_FLOAT, GL_FALSE,
sizeof(float) * 15,
material.tbn + 6);
}
texunit++; texunit++;
} }
@ -4128,7 +4150,13 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
bglLightfv(GL_LIGHT0, GL_AMBIENT, pos); bglLightfv(GL_LIGHT0, GL_AMBIENT, pos);
bglLightfv(GL_LIGHT0, GL_DIFFUSE, color); bglLightfv(GL_LIGHT0, GL_DIFFUSE, color);
bglLightfv(GL_LIGHT0, GL_SPECULAR, inpos); if (material.mdspritespace == GL_TRUE) {
float mdspritespacepos[3];
polymer_transformpoint(inpos, mdspritespacepos, (float *)mdspritespace);
bglLightfv(GL_LIGHT0, GL_SPECULAR, mdspritespacepos);
} else {
bglLightfv(GL_LIGHT0, GL_SPECULAR, inpos);
}
bglLightfv(GL_LIGHT0, GL_LINEAR_ATTENUATION, &range[1]); bglLightfv(GL_LIGHT0, GL_LINEAR_ATTENUATION, &range[1]);
} }
@ -4156,6 +4184,14 @@ static void polymer_unbindmaterial(int32_t programbits)
bglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); bglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
} }
// PR_BIT_NORMAL_MAP
if (programbits & prprogrambits[PR_BIT_NORMAL_MAP].bit)
{
bglDisableVertexAttribArrayARB(prprograms[programbits].attrib_T);
bglDisableVertexAttribArrayARB(prprograms[programbits].attrib_B);
bglDisableVertexAttribArrayARB(prprograms[programbits].attrib_N);
}
bglUseProgramObjectARB(0); bglUseProgramObjectARB(0);
} }