mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 10:40:46 +00:00
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:
parent
e65891aad6
commit
0d6dc3a531
3 changed files with 407 additions and 111 deletions
|
@ -86,10 +86,10 @@ typedef struct s_prmaterial {
|
|||
// PR_BIT_ANIM_INTERPOLATION
|
||||
GLfloat frameprogress;
|
||||
GLfloat* nextframedata;
|
||||
GLsizei nextframedatastride;
|
||||
// PR_BIT_NORMAL_MAP
|
||||
GLuint normalmap;
|
||||
GLfloat normalbias[2];
|
||||
GLfloat* tbn;
|
||||
// PR_BIT_DIFFUSE_MAP
|
||||
GLuint diffusemap;
|
||||
GLfloat diffusescale[2];
|
||||
|
@ -212,7 +212,7 @@ typedef struct s_prplane {
|
|||
int32_t vertcount;
|
||||
GLuint vbo;
|
||||
// attributes
|
||||
GLfloat tbn[9];
|
||||
GLfloat tbn[3][3];
|
||||
GLfloat plane[4];
|
||||
_prmaterial material;
|
||||
// elements
|
||||
|
@ -331,7 +331,6 @@ static void polymer_drawwall(int16_t sectnum, int16_t wallnum);
|
|||
static void polymer_computeplane(_prplane* p);
|
||||
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_invertmatrix(float* m, float* out);
|
||||
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);
|
||||
|
@ -369,6 +368,138 @@ static void polymer_prepareshadows(void);
|
|||
// RENDER TARGETS
|
||||
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_h_
|
||||
|
|
|
@ -1437,11 +1437,50 @@ static md3model_t *md3load(int32_t fil)
|
|||
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)
|
||||
{
|
||||
int framei, surfi, verti;
|
||||
int framei, surfi, verti, trii, i;
|
||||
md3surf_t *s;
|
||||
md3frame_t *frame;
|
||||
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,
|
||||
// so let's compute it ourselves
|
||||
|
@ -1450,15 +1489,17 @@ static void md3postload(md3model_t* m)
|
|||
|
||||
while (framei < m->head.numframes)
|
||||
{
|
||||
m->head.frames[framei].min.x = 0.0f;
|
||||
m->head.frames[framei].min.y = 0.0f;
|
||||
m->head.frames[framei].min.z = 0.0f;
|
||||
frame = &m->head.frames[framei];
|
||||
|
||||
m->head.frames[framei].max.x = 0.0f;
|
||||
m->head.frames[framei].max.y = 0.0f;
|
||||
m->head.frames[framei].max.z = 0.0f;
|
||||
frame->min.x = 0.0f;
|
||||
frame->min.y = 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;
|
||||
while (surfi < m->head.numsurfs)
|
||||
|
@ -1470,30 +1511,30 @@ static void md3postload(md3model_t* m)
|
|||
{
|
||||
if (!verti && !surfi)
|
||||
{
|
||||
m->head.frames[framei].min.x = frameverts[verti].x;
|
||||
m->head.frames[framei].min.y = frameverts[verti].y;
|
||||
m->head.frames[framei].min.z = frameverts[verti].z;
|
||||
frame->min.x = frameverts[verti].x;
|
||||
frame->min.y = frameverts[verti].y;
|
||||
frame->min.z = frameverts[verti].z;
|
||||
|
||||
m->head.frames[framei].max.x = frameverts[verti].x;
|
||||
m->head.frames[framei].max.y = frameverts[verti].y;
|
||||
m->head.frames[framei].max.z = frameverts[verti].z;
|
||||
frame->max.x = frameverts[verti].x;
|
||||
frame->max.y = frameverts[verti].y;
|
||||
frame->max.z = frameverts[verti].z;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m->head.frames[framei].min.x > frameverts[verti].x)
|
||||
m->head.frames[framei].min.x = frameverts[verti].x;
|
||||
if (m->head.frames[framei].max.x < frameverts[verti].x)
|
||||
m->head.frames[framei].max.x = frameverts[verti].x;
|
||||
if (frame->min.x > frameverts[verti].x)
|
||||
frame->min.x = frameverts[verti].x;
|
||||
if (frame->max.x < frameverts[verti].x)
|
||||
frame->max.x = frameverts[verti].x;
|
||||
|
||||
if (m->head.frames[framei].min.y > frameverts[verti].y)
|
||||
m->head.frames[framei].min.y = frameverts[verti].y;
|
||||
if (m->head.frames[framei].max.y < frameverts[verti].y)
|
||||
m->head.frames[framei].max.y = frameverts[verti].y;
|
||||
if (frame->min.y > frameverts[verti].y)
|
||||
frame->min.y = frameverts[verti].y;
|
||||
if (frame->max.y < frameverts[verti].y)
|
||||
frame->max.y = frameverts[verti].y;
|
||||
|
||||
if (m->head.frames[framei].min.z > frameverts[verti].z)
|
||||
m->head.frames[framei].min.z = frameverts[verti].z;
|
||||
if (m->head.frames[framei].max.z < frameverts[verti].z)
|
||||
m->head.frames[framei].max.z = frameverts[verti].z;
|
||||
if (frame->min.z > frameverts[verti].z)
|
||||
frame->min.z = frameverts[verti].z;
|
||||
if (frame->max.z < frameverts[verti].z)
|
||||
frame->max.z = frameverts[verti].z;
|
||||
}
|
||||
|
||||
verti++;
|
||||
|
@ -1501,9 +1542,9 @@ static void md3postload(md3model_t* m)
|
|||
surfi++;
|
||||
}
|
||||
|
||||
m->head.frames[framei].cen.x = (m->head.frames[framei].min.x + m->head.frames[framei].max.x) / 2.0f;
|
||||
m->head.frames[framei].cen.y = (m->head.frames[framei].min.y + m->head.frames[framei].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.x = (frame->min.x + frame->max.x) / 2.0f;
|
||||
frame->cen.y = (frame->min.y + frame->max.y) / 2.0f;
|
||||
frame->cen.z = (frame->min.z + frame->max.z) / 2.0f;
|
||||
|
||||
surfi = 0;
|
||||
while (surfi < m->head.numsurfs)
|
||||
|
@ -1513,21 +1554,21 @@ static void md3postload(md3model_t* m)
|
|||
verti = 0;
|
||||
while (verti < m->head.surfs[surfi].numverts)
|
||||
{
|
||||
vec[0] = frameverts[verti].x - m->head.frames[framei].cen.x;
|
||||
vec[1] = frameverts[verti].y - m->head.frames[framei].cen.y;
|
||||
vec[2] = frameverts[verti].z - m->head.frames[framei].cen.z;
|
||||
vec1[0] = frameverts[verti].x - frame->cen.x;
|
||||
vec1[1] = frameverts[verti].y - frame->cen.y;
|
||||
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)
|
||||
m->head.frames[framei].r = dist;
|
||||
if (dist > frame->r)
|
||||
frame->r = dist;
|
||||
|
||||
verti++;
|
||||
}
|
||||
surfi++;
|
||||
}
|
||||
|
||||
m->head.frames[framei].r = sqrt(m->head.frames[framei].r);
|
||||
frame->r = sqrt(frame->r);
|
||||
|
||||
framei++;
|
||||
}
|
||||
|
@ -1537,29 +1578,117 @@ static void md3postload(md3model_t* m)
|
|||
surfi = 0;
|
||||
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;
|
||||
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;
|
||||
m->head.surfs[surfi].geometry[(verti * 6) + 1] = m->head.surfs[surfi].xyzn[verti].y;
|
||||
m->head.surfs[surfi].geometry[(verti * 6) + 2] = m->head.surfs[surfi].xyzn[verti].z;
|
||||
s->geometry[(verti * 15) + 0] = s->xyzn[verti].x;
|
||||
s->geometry[(verti * 15) + 1] = s->xyzn[verti].y;
|
||||
s->geometry[(verti * 15) + 2] = s->xyzn[verti].z;
|
||||
|
||||
// normal extraction from packed spherical coordinates
|
||||
// FIXME: swapping lat and lng because of npherno's compiler
|
||||
lat = m->head.surfs[surfi].xyzn[verti].nlng * (2 * PI) / 255.0f;
|
||||
lng = m->head.surfs[surfi].xyzn[verti].nlat * (2 * PI) / 255.0f;
|
||||
lat = s->xyzn[verti].nlng * (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);
|
||||
m->head.surfs[surfi].geometry[(verti * 6) + 4] = sin(lat) * sin(lng);
|
||||
m->head.surfs[surfi].geometry[(verti * 6) + 5] = cos(lng);
|
||||
s->geometry[(verti * 15) + 3] = cos(lat) * sin(lng);
|
||||
s->geometry[(verti * 15) + 4] = sin(lat) * sin(lng);
|
||||
s->geometry[(verti * 15) + 5] = cos(lng);
|
||||
|
||||
verti++;
|
||||
}
|
||||
surfi++;
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t md3draw(md3model_t *m, spritetype *tspr)
|
||||
|
|
|
@ -547,6 +547,7 @@ _prrt *prrts;
|
|||
|
||||
// CONTROL
|
||||
GLfloat spritemodelview[16];
|
||||
GLfloat mdspritespace[4][4];
|
||||
GLfloat rootmodelviewmatrix[16];
|
||||
GLfloat *curmodelviewmatrix;
|
||||
GLfloat rootskymodelviewmatrix[16];
|
||||
|
@ -1706,9 +1707,9 @@ static void polymer_drawplane(_prplane* plane)
|
|||
|
||||
if (materialbits & prprogrambits[PR_BIT_NORMAL_MAP].bit)
|
||||
{
|
||||
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_T, &plane->tbn[0]);
|
||||
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_B, &plane->tbn[3]);
|
||||
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_N, &plane->tbn[6]);
|
||||
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_T, &plane->tbn[0][0]);
|
||||
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_B, &plane->tbn[1][0]);
|
||||
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_N, &plane->tbn[2][0]);
|
||||
}
|
||||
|
||||
if (plane->indices)
|
||||
|
@ -2905,7 +2906,8 @@ static void polymer_computeplane(_prplane* p)
|
|||
// hack to work around a precision issue with slopes
|
||||
if (norm >= 15000)
|
||||
{
|
||||
float tangent[9];
|
||||
float tangent[3][3];
|
||||
double det;
|
||||
|
||||
// normalize the normal/plane equation and calculate its plane 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]);
|
||||
|
||||
// tangent
|
||||
tangent[0] = (vec2[4] * vec1[0] - vec1[4] * vec2[0]) * r;
|
||||
tangent[1] = (vec2[4] * vec1[1] - vec1[4] * vec2[1]) * r;
|
||||
tangent[2] = (vec2[4] * vec1[2] - vec1[4] * vec2[2]) * r;
|
||||
tangent[0][0] = (vec2[4] * vec1[0] - vec1[4] * vec2[0]) * r;
|
||||
tangent[0][1] = (vec2[4] * vec1[1] - vec1[4] * vec2[1]) * r;
|
||||
tangent[0][2] = (vec2[4] * vec1[2] - vec1[4] * vec2[2]) * r;
|
||||
|
||||
polymer_normalize(&tangent[0]);
|
||||
polymer_normalize(&tangent[0][0]);
|
||||
|
||||
// bitangent
|
||||
tangent[3] = (vec1[3] * vec2[0] - vec2[3] * vec1[0]) * r;
|
||||
tangent[4] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r;
|
||||
tangent[5] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r;
|
||||
tangent[1][0] = (vec1[3] * vec2[0] - vec2[3] * vec1[0]) * r;
|
||||
tangent[1][1] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r;
|
||||
tangent[1][2] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r;
|
||||
|
||||
polymer_normalize(&tangent[3]);
|
||||
polymer_normalize(&tangent[1][0]);
|
||||
|
||||
// normal
|
||||
tangent[6] = plane[0];
|
||||
tangent[7] = plane[1];
|
||||
tangent[8] = plane[2];
|
||||
tangent[2][0] = plane[0];
|
||||
tangent[2][1] = plane[1];
|
||||
tangent[2][2] = plane[2];
|
||||
|
||||
polymer_invertmatrix(tangent, p->tbn);
|
||||
INVERT_3X3(p->tbn, det, tangent);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2970,29 +2972,6 @@ static inline void polymer_transformpoint(float* inpos, float* pos, float* matr
|
|||
+ 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)
|
||||
{
|
||||
double norm;
|
||||
|
@ -3313,9 +3292,10 @@ static void polymer_drawmdsprite(spritetype *tspr)
|
|||
float *v0, *v1;
|
||||
md3surf_t *s;
|
||||
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 scale;
|
||||
double det;
|
||||
int32_t surfi, i, j;
|
||||
GLubyte* color;
|
||||
int32_t materialbits;
|
||||
|
@ -3398,6 +3378,10 @@ static void polymer_drawmdsprite(spritetype *tspr)
|
|||
bglPushMatrix();
|
||||
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
|
||||
// bglDisable(GL_TEXTURE_2D);
|
||||
// bglBegin(GL_LINES);
|
||||
|
@ -3545,8 +3529,8 @@ static void polymer_drawmdsprite(spritetype *tspr)
|
|||
for (surfi=0;surfi<m->head.numsurfs;surfi++)
|
||||
{
|
||||
s = &m->head.surfs[surfi];
|
||||
v0 = &s->geometry[m->cframe*s->numverts*6];
|
||||
v1 = &s->geometry[m->nframe*s->numverts*6];
|
||||
v0 = &s->geometry[m->cframe*s->numverts*15];
|
||||
v1 = &s->geometry[m->nframe*s->numverts*15];
|
||||
|
||||
// debug code for drawing model normals
|
||||
// bglDisable(GL_TEXTURE_2D);
|
||||
|
@ -3585,6 +3569,20 @@ static void polymer_drawmdsprite(spritetype *tspr)
|
|||
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)
|
||||
if ((int32_t)sk->palette == tspr->pal &&
|
||||
sk->skinnum == tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum &&
|
||||
|
@ -3609,13 +3607,13 @@ static void polymer_drawmdsprite(spritetype *tspr)
|
|||
bglTexCoordPointer(2, GL_FLOAT, 0, 0);
|
||||
|
||||
bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->geometry[surfi]);
|
||||
bglVertexPointer(3, GL_FLOAT, sizeof(float) * 6, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 6));
|
||||
bglNormalPointer(GL_FLOAT, sizeof(float) * 6, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 6) + 3);
|
||||
bglVertexPointer(3, GL_FLOAT, sizeof(float) * 15, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15));
|
||||
bglNormalPointer(GL_FLOAT, sizeof(float) * 15, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15) + 3);
|
||||
|
||||
if (pr_gpusmoothing)
|
||||
{
|
||||
mdspritematerial.nextframedata = (GLfloat*)(m->nframe * s->numverts * sizeof(float) * 6);
|
||||
mdspritematerial.nextframedatastride = sizeof(float) * 6;
|
||||
mdspritematerial.tbn = (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15) + 6;
|
||||
|
||||
if (pr_gpusmoothing) {
|
||||
mdspritematerial.nextframedata = (GLfloat*)(m->nframe * s->numverts * sizeof(float) * 15);
|
||||
}
|
||||
|
||||
bglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m->indices[surfi]);
|
||||
|
@ -3634,14 +3632,14 @@ static void polymer_drawmdsprite(spritetype *tspr)
|
|||
}
|
||||
else
|
||||
{
|
||||
bglVertexPointer(3, GL_FLOAT, sizeof(float) * 6, v0);
|
||||
bglNormalPointer(GL_FLOAT, sizeof(float) * 6, v0 + 3);
|
||||
bglVertexPointer(3, GL_FLOAT, sizeof(float) * 15, v0);
|
||||
bglNormalPointer(GL_FLOAT, sizeof(float) * 15, v0 + 3);
|
||||
bglTexCoordPointer(2, GL_FLOAT, 0, s->uv);
|
||||
|
||||
if (pr_gpusmoothing)
|
||||
{
|
||||
mdspritematerial.tbn = v0 + 6;
|
||||
|
||||
if (pr_gpusmoothing) {
|
||||
mdspritematerial.nextframedata = (GLfloat*)(v1);
|
||||
mdspritematerial.nextframedatastride = sizeof(float) * 6;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
i++;
|
||||
|
@ -3705,10 +3703,10 @@ static void polymer_getscratchmaterial(_prmaterial* material)
|
|||
// PR_BIT_ANIM_INTERPOLATION
|
||||
material->frameprogress = 0.0f;
|
||||
material->nextframedata = NULL;
|
||||
material->nextframedatastride = 0;
|
||||
// PR_BIT_NORMAL_MAP
|
||||
material->normalmap = 0;
|
||||
material->normalbias[0] = material->normalbias[1] = 0.0f;
|
||||
material->tbn = NULL;
|
||||
// PR_BIT_DIFFUSE_MAP
|
||||
material->diffusemap = 0;
|
||||
material->diffusescale[0] = material->diffusescale[1] = 1.0f;
|
||||
|
@ -3827,7 +3825,7 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
|
|||
// --------- bit validation
|
||||
|
||||
// PR_BIT_ANIM_INTERPOLATION
|
||||
if (material.nextframedatastride)
|
||||
if (material.nextframedata)
|
||||
programbits |= prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit;
|
||||
|
||||
// PR_BIT_LIGHTING_PASS
|
||||
|
@ -3909,12 +3907,12 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
|
|||
bglEnableVertexAttribArrayARB(prprograms[programbits].attrib_nextFrameNormal);
|
||||
bglVertexAttribPointerARB(prprograms[programbits].attrib_nextFrameData,
|
||||
3, GL_FLOAT, GL_FALSE,
|
||||
material.nextframedatastride,
|
||||
sizeof(float) * 15,
|
||||
material.nextframedata);
|
||||
if (prprograms[programbits].attrib_nextFrameNormal != -1)
|
||||
bglVertexAttribPointerARB(prprograms[programbits].attrib_nextFrameNormal,
|
||||
3, GL_FLOAT, GL_FALSE,
|
||||
material.nextframedatastride,
|
||||
sizeof(float) * 15,
|
||||
material.nextframedata + 3);
|
||||
|
||||
bglUniform1fARB(prprograms[programbits].uniform_frameProgress, material.frameprogress);
|
||||
|
@ -3939,6 +3937,11 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
|
|||
bglActiveTextureARB(texunit + GL_TEXTURE0_ARB);
|
||||
bglBindTexture(GL_TEXTURE_2D, material.normalmap);
|
||||
|
||||
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);
|
||||
if (pr_overrideparallax) {
|
||||
|
@ -3948,6 +3951,25 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
|
|||
} else
|
||||
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++;
|
||||
}
|
||||
|
||||
|
@ -4128,7 +4150,13 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
|
|||
|
||||
bglLightfv(GL_LIGHT0, GL_AMBIENT, pos);
|
||||
bglLightfv(GL_LIGHT0, GL_DIFFUSE, color);
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -4156,6 +4184,14 @@ static void polymer_unbindmaterial(int32_t programbits)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue