From 0d6dc3a531312b8b72bd8ab4c4416ed5dde4f581 Mon Sep 17 00:00:00 2001 From: plagman Date: Sun, 24 Jan 2010 05:57:43 +0000 Subject: [PATCH] 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 --- polymer/eduke32/build/include/polymer.h | 137 ++++++++++++++- polymer/eduke32/build/src/mdsprite.c | 225 +++++++++++++++++++----- polymer/eduke32/build/src/polymer.c | 156 +++++++++------- 3 files changed, 407 insertions(+), 111 deletions(-) diff --git a/polymer/eduke32/build/include/polymer.h b/polymer/eduke32/build/include/polymer.h index 0dfc95302..e6dfceafe 100644 --- a/polymer/eduke32/build/include/polymer.h +++ b/polymer/eduke32/build/include/polymer.h @@ -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; khead.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++; } + + 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) diff --git a/polymer/eduke32/build/src/polymer.c b/polymer/eduke32/build/src/polymer.c index 3f1f7abf8..62b8121ac 100644 --- a/polymer/eduke32/build/src/polymer.c +++ b/polymer/eduke32/build/src/polymer.c @@ -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;surfihead.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,7 +3937,12 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights, bglActiveTextureARB(texunit + GL_TEXTURE0_ARB); 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); if (pr_overrideparallax) { bias[0] = pr_parallaxscale; @@ -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); - 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]); } @@ -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); }