-int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
-{
- int i;
- float lerp1, lerp2, lerp3, lerp4;
- zymbonematrix *out, rootmatrix, m;
- const zymbonematrix *bone1, *bone2, *bone3, *bone4;
-
- rootmatrix.m[0][0] = 1;
- rootmatrix.m[0][1] = 0;
- rootmatrix.m[0][2] = 0;
- rootmatrix.m[0][3] = 0;
- rootmatrix.m[1][0] = 0;
- rootmatrix.m[1][1] = 1;
- rootmatrix.m[1][2] = 0;
- rootmatrix.m[1][3] = 0;
- rootmatrix.m[2][0] = 0;
- rootmatrix.m[2][1] = 0;
- rootmatrix.m[2][2] = 1;
- rootmatrix.m[2][3] = 0;
-
- bone1 = bonebase + blend[0].frame * count;
- lerp1 = blend[0].lerp;
- if (blend[1].lerp)
- {
- bone2 = bonebase + blend[1].frame * count;
- lerp2 = blend[1].lerp;
- if (blend[2].lerp)
- {
- bone3 = bonebase + blend[2].frame * count;
- lerp3 = blend[2].lerp;
- if (blend[3].lerp)
- {
- // 4 poses
- bone4 = bonebase + blend[3].frame * count;
- lerp4 = blend[3].lerp;
- for (i = 0, out = zymbonepose;i < count;i++, out++)
- {
- // interpolate matrices
- m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4;
- m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4;
- m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4;
- m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4;
- m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4;
- m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4;
- m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4;
- m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4;
- m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4;
- m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4;
- m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4;
- m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4;
- if (bone->parent >= 0)
- R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
- else
- R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
- bone1++;
- bone2++;
- bone3++;
- bone4++;
- bone++;
- }
- }
- else
- {
- // 3 poses
- for (i = 0, out = zymbonepose;i < count;i++, out++)
- {
- // interpolate matrices
- m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3;
- m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3;
- m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3;
- m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3;
- m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3;
- m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3;
- m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3;
- m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3;
- m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3;
- m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3;
- m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3;
- m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3;
- if (bone->parent >= 0)
- R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
- else
- R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
- bone1++;
- bone2++;
- bone3++;
- bone++;
- }
- }
- }
- else
- {
- // 2 poses
- for (i = 0, out = zymbonepose;i < count;i++, out++)
- {
- // interpolate matrices
- m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
- m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
- m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
- m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
- m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
- m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
- m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
- m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
- m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
- m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
- m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
- m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
- if (bone->parent >= 0)
- R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
- else
- R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
- bone1++;
- bone2++;
- bone++;
- }
- }
- }
- else
- {
- // 1 pose
- if (lerp1 != 1)
- {
- // lerp != 1.0
- for (i = 0, out = zymbonepose;i < count;i++, out++)
- {
- // interpolate matrices
- m.m[0][0] = bone1->m[0][0] * lerp1;
- m.m[0][1] = bone1->m[0][1] * lerp1;
- m.m[0][2] = bone1->m[0][2] * lerp1;
- m.m[0][3] = bone1->m[0][3] * lerp1;
- m.m[1][0] = bone1->m[1][0] * lerp1;
- m.m[1][1] = bone1->m[1][1] * lerp1;
- m.m[1][2] = bone1->m[1][2] * lerp1;
- m.m[1][3] = bone1->m[1][3] * lerp1;
- m.m[2][0] = bone1->m[2][0] * lerp1;
- m.m[2][1] = bone1->m[2][1] * lerp1;
- m.m[2][2] = bone1->m[2][2] * lerp1;
- m.m[2][3] = bone1->m[2][3] * lerp1;
- if (bone->parent >= 0)
- R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
- else
- R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
- bone1++;
- bone++;
- }
- }
- else
- {
- // lerp == 1.0
- for (i = 0, out = zymbonepose;i < count;i++, out++)
- {
- if (bone->parent >= 0)
- R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &bone1->m[0][0], &out->m[0][0]);
- else
- R_ConcatTransforms(&rootmatrix.m[0][0], &bone1->m[0][0], &out->m[0][0]);
- bone1++;
- bone++;
- }
- }
- }
- return true;
-}
-
-void ZymoticTransformVerts(int vertcount, float *vertex, int *bonecounts, zymvertex_t *vert)
-{
- int c;
- float *out = vertex;
- zymbonematrix *matrix;
- while(vertcount--)
- {
- c = *bonecounts++;
- // FIXME: validate bonecounts at load time (must be >= 1)
- // FIXME: need 4th component in origin, for how much of the translate to blend in
- if (c == 1)
- {
- matrix = &zymbonepose[vert->bonenum];
- out[0] = vert->origin[0] * matrix->m[0][0] + vert->origin[1] * matrix->m[0][1] + vert->origin[2] * matrix->m[0][2] + matrix->m[0][3];
- out[1] = vert->origin[0] * matrix->m[1][0] + vert->origin[1] * matrix->m[1][1] + vert->origin[2] * matrix->m[1][2] + matrix->m[1][3];
- out[2] = vert->origin[0] * matrix->m[2][0] + vert->origin[1] * matrix->m[2][1] + vert->origin[2] * matrix->m[2][2] + matrix->m[2][3];
- vert++;
- }
- else
- {
- VectorClear(out);
- while(c--)
- {
- matrix = &zymbonepose[vert->bonenum];
- out[0] += vert->origin[0] * matrix->m[0][0] + vert->origin[1] * matrix->m[0][1] + vert->origin[2] * matrix->m[0][2] + matrix->m[0][3];
- out[1] += vert->origin[0] * matrix->m[1][0] + vert->origin[1] * matrix->m[1][1] + vert->origin[2] * matrix->m[1][2] + matrix->m[1][3];
- out[2] += vert->origin[0] * matrix->m[2][0] + vert->origin[1] * matrix->m[2][1] + vert->origin[2] * matrix->m[2][2] + matrix->m[2][3];
- vert++;
- }
- }
- out += 3;
- }
-}
-
-void ZymoticCalcNormal3f(int vertcount, float *vertex3f, float *normal3f, int shadercount, int *renderlist)
-{
- int a, b, c, d;
- float *out, v1[3], v2[3], normal[3], s;
- int *u;
- // clear normals
- memset(normal3f, 0, sizeof(float) * vertcount * 3);
- memset(aliasvertusage, 0, sizeof(int) * vertcount);
- // parse render list and accumulate surface normals
- while(shadercount--)
- {
- d = *renderlist++;
- while (d--)
- {
- a = renderlist[0]*4;
- b = renderlist[1]*4;
- c = renderlist[2]*4;
- v1[0] = vertex3f[a+0] - vertex3f[b+0];
- v1[1] = vertex3f[a+1] - vertex3f[b+1];
- v1[2] = vertex3f[a+2] - vertex3f[b+2];
- v2[0] = vertex3f[c+0] - vertex3f[b+0];
- v2[1] = vertex3f[c+1] - vertex3f[b+1];
- v2[2] = vertex3f[c+2] - vertex3f[b+2];
- CrossProduct(v1, v2, normal);
- VectorNormalizeFast(normal);
- // add surface normal to vertices
- a = renderlist[0] * 3;
- normal3f[a+0] += normal[0];
- normal3f[a+1] += normal[1];
- normal3f[a+2] += normal[2];
- aliasvertusage[renderlist[0]]++;
- a = renderlist[1] * 3;
- normal3f[a+0] += normal[0];
- normal3f[a+1] += normal[1];
- normal3f[a+2] += normal[2];
- aliasvertusage[renderlist[1]]++;
- a = renderlist[2] * 3;
- normal3f[a+0] += normal[0];
- normal3f[a+1] += normal[1];
- normal3f[a+2] += normal[2];
- aliasvertusage[renderlist[2]]++;
- renderlist += 3;
- }
- }
- // FIXME: precalc this
- // average surface normals
- out = normal3f;
- u = aliasvertusage;
- while(vertcount--)
- {
- if (*u > 1)
- {
- s = ixtable[*u];
- out[0] *= s;
- out[1] *= s;
- out[2] *= s;
- }
- u++;
- out += 3;
- }
-}
-
-void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
-{
- float fog, ifog, colorscale;
- vec3_t diff;
- int i, *renderlist, *elements;
- rtexture_t *texture;
- rmeshstate_t mstate;
- const entity_render_t *ent = calldata1;
- int shadernum = calldata2;
- int numverts, numtriangles;
-
- R_Mesh_Matrix(&ent->matrix);
-
- // find the vertex index list and texture
- renderlist = ent->model->zymdata_renderlist;
- for (i = 0;i < shadernum;i++)
- renderlist += renderlist[0] * 3 + 1;
- texture = ent->model->zymdata_textures[shadernum];
-
- numverts = ent->model->zymnum_verts;
- numtriangles = *renderlist++;
- elements = renderlist;
-
- expandaliasvert(numverts);
-
- fog = 0;
- if (fogenabled)
- {
- VectorSubtract(ent->origin, r_origin, diff);
- fog = DotProduct(diff,diff);
- if (fog < 0.01f)
- fog = 0.01f;
- fog = exp(fogdensity/fog);
- if (fog > 1)
- fog = 1;
- if (fog < 0.01f)
- fog = 0;
- // fog method: darken, additive fog
- // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
- // 2. render fog as additive
- }
- ifog = 1 - fog;
-
- memset(&mstate, 0, sizeof(mstate));
- if (ent->effects & EF_ADDITIVE)
- {
- mstate.blendfunc1 = GL_SRC_ALPHA;
- mstate.blendfunc2 = GL_ONE;
- }
- else if (ent->alpha != 1.0 || R_TextureHasAlpha(texture))
- {
- mstate.blendfunc1 = GL_SRC_ALPHA;
- mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
- }
- else
- {
- mstate.blendfunc1 = GL_ONE;
- mstate.blendfunc2 = GL_ZERO;
- }
- colorscale = r_colorscale;
- if (gl_combine.integer)
- {
- mstate.texrgbscale[0] = 4;
- colorscale *= 0.25f;
- }
- mstate.tex[0] = R_GetTexture(texture);
- R_Mesh_State(&mstate);
- ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones);
-
- R_Mesh_GetSpace(numverts);
- ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
- R_Mesh_CopyTexCoord2f(0, ent->model->zymdata_texcoords, ent->model->zymnum_verts);
- ZymoticCalcNormal3f(numverts, varray_vertex3f, aliasvert_normal3f, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
- R_LightModel(ent, numverts, varray_vertex3f, aliasvert_normal3f, varray_color4f, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
- R_Mesh_Draw(numverts, numtriangles, elements);
- c_alias_polys += numtriangles;
-
- if (fog)
- {
- memset(&mstate, 0, sizeof(mstate));
- mstate.blendfunc1 = GL_SRC_ALPHA;
- mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
- // FIXME: need alpha mask for fogging...
- //mstate.tex[0] = R_GetTexture(texture);
- R_Mesh_State(&mstate);
- GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, ent->alpha * fog);
- R_Mesh_GetSpace(numverts);
- ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
- R_Mesh_Draw(numverts, numtriangles, elements);
- c_alias_polys += numtriangles;
- }
-}
-
-void R_Model_Zymotic_Draw(entity_render_t *ent)
-{
- int i;
-
- if (ent->alpha < (1.0f / 64.0f))
- return; // basically completely transparent
-
- c_models++;
-
- for (i = 0;i < ent->model->zymnum_shaders;i++)
- {
- if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_TextureHasAlpha(ent->model->zymdata_textures[i]))
- R_MeshQueue_AddTransparent(ent->origin, R_DrawZymoticModelMeshCallback, ent, i);
- else
- R_DrawZymoticModelMeshCallback(ent, i);
- }
-}
-
-void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent)
-{
- // FIXME
-}
-
-void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
-{
- // FIXME
-}
-
-void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent)
-{
- // FIXME
-}
-