cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
+cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
float mod_md3_sin[320];
Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
+ Cvar_RegisterVariable(&mod_alias_supporttagscale);
for (i = 0;i < 320;i++)
mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
}
-void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
{
#define MAX_BONES 256
- if (model->surfmesh.data_vertexweightindex4i)
- {
- // vertex weighted skeletal
- int i, k;
- float boneposerelative[MAX_BONES][12];
- // interpolate matrices and concatenate them to their parents
- for (i = 0;i < model->num_bones;i++)
+ // vertex weighted skeletal
+ int i, k;
+ int blends;
+ float desiredscale[3];
+ float boneposerelative[MAX_BONES][12];
+ float *matrix, m[12], bonepose[MAX_BONES][12];
+
+ // interpolate matrices and concatenate them to their parents
+ for (i = 0;i < model->num_bones;i++)
+ {
+ for (k = 0;k < 12;k++)
+ m[k] = 0;
+ VectorClear(desiredscale);
+ for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
{
- int blends;
- float *matrix, m[12], bonepose[MAX_BONES][12];
+ matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
+ for (k = 0;k < 12;k++)
+ m[k] += matrix[k] * frameblend[blends].lerp;
+ desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
+ desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
+ desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
+ }
+ VectorNormalize(m );
+ VectorNormalize(m + 4);
+ VectorNormalize(m + 8);
+ VectorScale(m , desiredscale[0], m );
+ VectorScale(m + 4, desiredscale[1], m + 4);
+ VectorScale(m + 8, desiredscale[2], m + 8);
+ if (i == r_skeletal_debugbone.integer)
+ m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
+ m[3] *= r_skeletal_debugtranslatex.value;
+ m[7] *= r_skeletal_debugtranslatey.value;
+ m[11] *= r_skeletal_debugtranslatez.value;
+ if (model->data_bones[i].parent >= 0)
+ R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
+ else
for (k = 0;k < 12;k++)
- m[k] = 0;
- for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++)
+ bonepose[i][k] = m[k];
+ // create a relative deformation matrix to describe displacement
+ // from the base mesh, which is used by the actual weighting
+ R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
+ }
+ // blend the vertex bone weights
+ // special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases)
+ // special case for the first bone because it avoids the need to memset the arrays before filling
+ if (vertex3f)
+ {
+ const float *v = model->surfmesh.data_vertex3f;
+ const int *wi = model->surfmesh.data_vertexweightindex4i;
+ const float *wf = model->surfmesh.data_vertexweightinfluence4f;
+ memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
+ for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
+ {
+ if (wf[0] == 1)
{
- matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12;
- for (k = 0;k < 12;k++)
- m[k] += matrix[k] * frameblend[blends].lerp;
+ const float *m = boneposerelative[wi[0]];
+ vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
+ vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
+ vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
}
- if (i == r_skeletal_debugbone.integer)
- m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
- m[3] *= r_skeletal_debugtranslatex.value;
- m[7] *= r_skeletal_debugtranslatey.value;
- m[11] *= r_skeletal_debugtranslatez.value;
- if (model->data_bones[i].parent >= 0)
- R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
else
- for (k = 0;k < 12;k++)
- bonepose[i][k] = m[k];
- // create a relative deformation matrix to describe displacement
- // from the base mesh, which is used by the actual weighting
- R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
- }
- // blend the vertex bone weights
- // special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases)
- // special case for the first bone because it avoids the need to memset the arrays before filling
- {
- const float *v = model->surfmesh.data_vertex3f;
- const int *wi = model->surfmesh.data_vertexweightindex4i;
- const float *wf = model->surfmesh.data_vertexweightinfluence4f;
- memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
- for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
{
- if (wf[0] == 1)
+ const float *m = boneposerelative[wi[0]];
+ float f = wf[0];
+ vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
+ vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
+ vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
+ for (k = 1;k < 4 && wf[k];k++)
{
- const float *m = boneposerelative[wi[0]];
- vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
- vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
- vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
- }
- else
- {
- const float *m = boneposerelative[wi[0]];
- float f = wf[0];
- vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
- vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
- vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
- for (k = 1;k < 4 && wf[k];k++)
- {
- const float *m = boneposerelative[wi[k]];
- float f = wf[k];
- vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
- vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
- vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
- }
+ const float *m = boneposerelative[wi[k]];
+ float f = wf[k];
+ vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
+ vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
+ vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
}
}
}
- if (normal3f)
+ }
+ if (normal3f)
+ {
+ const float *n = model->surfmesh.data_normal3f;
+ const int *wi = model->surfmesh.data_vertexweightindex4i;
+ const float *wf = model->surfmesh.data_vertexweightinfluence4f;
+ memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
+ for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
{
- const float *n = model->surfmesh.data_normal3f;
- const int *wi = model->surfmesh.data_vertexweightindex4i;
- const float *wf = model->surfmesh.data_vertexweightinfluence4f;
- memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
- for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
+ if (wf[0] == 1)
{
- if (wf[0] == 1)
- {
- const float *m = boneposerelative[wi[0]];
- normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
- normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
- normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
- }
- else
+ const float *m = boneposerelative[wi[0]];
+ normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
+ normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
+ normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
+ }
+ else
+ {
+ const float *m = boneposerelative[wi[0]];
+ float f = wf[0];
+ normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
+ normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
+ normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
+ for (k = 1;k < 4 && wf[k];k++)
{
- const float *m = boneposerelative[wi[0]];
- float f = wf[0];
- normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
- normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
- normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
- for (k = 1;k < 4 && wf[k];k++)
- {
- const float *m = boneposerelative[wi[k]];
- float f = wf[k];
- normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
- normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
- normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
- }
+ const float *m = boneposerelative[wi[k]];
+ float f = wf[k];
+ normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
+ normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
+ normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
}
}
}
- if (svector3f)
+ }
+ if (svector3f)
+ {
+ const float *sv = model->surfmesh.data_svector3f;
+ const int *wi = model->surfmesh.data_vertexweightindex4i;
+ const float *wf = model->surfmesh.data_vertexweightinfluence4f;
+ memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
+ for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
{
- const float *sv = model->surfmesh.data_svector3f;
- const int *wi = model->surfmesh.data_vertexweightindex4i;
- const float *wf = model->surfmesh.data_vertexweightinfluence4f;
- memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
- for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
+ if (wf[0] == 1)
{
- if (wf[0] == 1)
- {
- const float *m = boneposerelative[wi[0]];
- svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
- svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
- svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
- }
- else
+ const float *m = boneposerelative[wi[0]];
+ svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
+ svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
+ svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
+ }
+ else
+ {
+ const float *m = boneposerelative[wi[0]];
+ float f = wf[0];
+ svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
+ svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
+ svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
+ for (k = 1;k < 4 && wf[k];k++)
{
- const float *m = boneposerelative[wi[0]];
- float f = wf[0];
- svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
- svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
- svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
- for (k = 1;k < 4 && wf[k];k++)
- {
- const float *m = boneposerelative[wi[k]];
- float f = wf[k];
- svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
- svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
- svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
- }
+ const float *m = boneposerelative[wi[k]];
+ float f = wf[k];
+ svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
+ svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
+ svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
}
}
}
- if (tvector3f)
+ }
+ if (tvector3f)
+ {
+ const float *tv = model->surfmesh.data_tvector3f;
+ const int *wi = model->surfmesh.data_vertexweightindex4i;
+ const float *wf = model->surfmesh.data_vertexweightinfluence4f;
+ memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
+ for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
{
- const float *tv = model->surfmesh.data_tvector3f;
- const int *wi = model->surfmesh.data_vertexweightindex4i;
- const float *wf = model->surfmesh.data_vertexweightinfluence4f;
- memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
- for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
+ if (wf[0] == 1)
{
- if (wf[0] == 1)
- {
- const float *m = boneposerelative[wi[0]];
- tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
- tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
- tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
- }
- else
+ const float *m = boneposerelative[wi[0]];
+ tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
+ tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
+ tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
+ }
+ else
+ {
+ const float *m = boneposerelative[wi[0]];
+ float f = wf[0];
+ tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
+ tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
+ tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
+ for (k = 1;k < 4 && wf[k];k++)
{
- const float *m = boneposerelative[wi[0]];
- float f = wf[0];
- tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
- tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
- tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
- for (k = 1;k < 4 && wf[k];k++)
- {
- const float *m = boneposerelative[wi[k]];
- float f = wf[k];
- tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
- tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
- tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
- }
+ const float *m = boneposerelative[wi[k]];
+ float f = wf[k];
+ tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
+ tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
+ tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
}
}
}
}
- else if (model->surfmesh.data_morphmd3vertex)
+}
+
+void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+{
+ // vertex morph
+ int i, numblends, blendnum;
+ int numverts = model->surfmesh.num_vertices;
+ numblends = 0;
+ for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
{
- // vertex morph
- int i, numblends, blendnum;
- int numverts = model->surfmesh.num_vertices;
- numblends = 0;
- for (blendnum = 0;blendnum < 4;blendnum++)
- {
- //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
- if (frameblend[blendnum].lerp > 0)
- numblends = blendnum + 1;
- }
- // special case for the first blend because it avoids some adds and the need to memset the arrays first
- for (blendnum = 0;blendnum < numblends;blendnum++)
+ //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
+ if (frameblend[blendnum].lerp > 0)
+ numblends = blendnum + 1;
+ }
+ // special case for the first blend because it avoids some adds and the need to memset the arrays first
+ for (blendnum = 0;blendnum < numblends;blendnum++)
+ {
+ const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
+ if (vertex3f)
{
- const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame;
float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
if (blendnum == 0)
{
vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
}
}
- // the yaw and pitch stored in md3 models are 8bit quantized angles
- // (0-255), and as such a lookup table is very well suited to
- // decoding them, and since cosine is equivilant to sine with an
- // extra 45 degree rotation, this uses one lookup table for both
- // sine and cosine with a +64 bias to get cosine.
- if (normal3f)
+ }
+ // the yaw and pitch stored in md3 models are 8bit quantized angles
+ // (0-255), and as such a lookup table is very well suited to
+ // decoding them, and since cosine is equivilant to sine with an
+ // extra 45 degree rotation, this uses one lookup table for both
+ // sine and cosine with a +64 bias to get cosine.
+ if (normal3f)
+ {
+ float lerp = frameblend[blendnum].lerp;
+ if (blendnum == 0)
{
- float lerp = frameblend[blendnum].lerp;
- if (blendnum == 0)
+ for (i = 0;i < numverts;i++)
{
- for (i = 0;i < numverts;i++)
- {
- normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
- normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
- normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
- }
+ normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
+ normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
+ normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
}
- else
+ }
+ else
+ {
+ for (i = 0;i < numverts;i++)
{
- for (i = 0;i < numverts;i++)
- {
- normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
- normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
- normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
- }
+ normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
+ normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
+ normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
}
}
- if (svector3f)
+ }
+ if (svector3f)
+ {
+ const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
+ float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
+ if (blendnum == 0)
{
- const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
- float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
- if (blendnum == 0)
+ for (i = 0;i < numverts;i++, texvecvert++)
{
- for (i = 0;i < numverts;i++, texvecvert++)
- {
- VectorScale(texvecvert->svec, f, svector3f + i*3);
- VectorScale(texvecvert->tvec, f, tvector3f + i*3);
- }
+ VectorScale(texvecvert->svec, f, svector3f + i*3);
+ VectorScale(texvecvert->tvec, f, tvector3f + i*3);
}
- else
+ }
+ else
+ {
+ for (i = 0;i < numverts;i++, texvecvert++)
{
- for (i = 0;i < numverts;i++, texvecvert++)
- {
- VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
- VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
- }
+ VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
+ VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
}
}
}
}
- else if (model->surfmesh.data_morphmdlvertex)
- {
- // vertex morph
- int i, numblends, blendnum;
- int numverts = model->surfmesh.num_vertices;
- float translate[3];
- VectorClear(translate);
- numblends = 0;
- // blend the frame translates to avoid redundantly doing so on each vertex
- // (a bit of a brain twister but it works)
- for (blendnum = 0;blendnum < 4;blendnum++)
- {
- if (model->surfmesh.data_morphmd2framesize6f)
- VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6 + 3, translate);
- else
- VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
- if (frameblend[blendnum].lerp > 0)
- numblends = blendnum + 1;
- }
- // special case for the first blend because it avoids some adds and the need to memset the arrays first
- for (blendnum = 0;blendnum < numblends;blendnum++)
+}
+
+void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+{
+ // vertex morph
+ int i, numblends, blendnum;
+ int numverts = model->surfmesh.num_vertices;
+ float translate[3];
+ VectorClear(translate);
+ numblends = 0;
+ // blend the frame translates to avoid redundantly doing so on each vertex
+ // (a bit of a brain twister but it works)
+ for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
+ {
+ if (model->surfmesh.data_morphmd2framesize6f)
+ VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
+ else
+ VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
+ if (frameblend[blendnum].lerp > 0)
+ numblends = blendnum + 1;
+ }
+ // special case for the first blend because it avoids some adds and the need to memset the arrays first
+ for (blendnum = 0;blendnum < numblends;blendnum++)
+ {
+ const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
+ if (vertex3f)
{
- const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame;
float scale[3];
if (model->surfmesh.data_morphmd2framesize6f)
- VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale);
+ VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
else
VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
if (blendnum == 0)
vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
}
}
- // the vertex normals in mdl models are an index into a table of
- // 162 unique values, this very crude quantization reduces the
- // vertex normal to only one byte, which saves a lot of space but
- // also makes lighting pretty coarse
- if (normal3f)
+ }
+ // the vertex normals in mdl models are an index into a table of
+ // 162 unique values, this very crude quantization reduces the
+ // vertex normal to only one byte, which saves a lot of space but
+ // also makes lighting pretty coarse
+ if (normal3f)
+ {
+ float lerp = frameblend[blendnum].lerp;
+ if (blendnum == 0)
{
- float lerp = frameblend[blendnum].lerp;
- if (blendnum == 0)
+ for (i = 0;i < numverts;i++)
{
- for (i = 0;i < numverts;i++)
- {
- const float *vn = m_bytenormals[verts[i].lightnormalindex];
- VectorScale(vn, lerp, normal3f + i*3);
- }
+ const float *vn = m_bytenormals[verts[i].lightnormalindex];
+ VectorScale(vn, lerp, normal3f + i*3);
}
- else
+ }
+ else
+ {
+ for (i = 0;i < numverts;i++)
{
- for (i = 0;i < numverts;i++)
- {
- const float *vn = m_bytenormals[verts[i].lightnormalindex];
- VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
- }
+ const float *vn = m_bytenormals[verts[i].lightnormalindex];
+ VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
}
}
- if (svector3f)
+ }
+ if (svector3f)
+ {
+ const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
+ float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
+ if (blendnum == 0)
{
- const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
- float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
- if (blendnum == 0)
+ for (i = 0;i < numverts;i++, texvecvert++)
{
- for (i = 0;i < numverts;i++, texvecvert++)
- {
- VectorScale(texvecvert->svec, f, svector3f + i*3);
- VectorScale(texvecvert->tvec, f, tvector3f + i*3);
- }
+ VectorScale(texvecvert->svec, f, svector3f + i*3);
+ VectorScale(texvecvert->tvec, f, tvector3f + i*3);
}
- else
+ }
+ else
+ {
+ for (i = 0;i < numverts;i++, texvecvert++)
{
- for (i = 0;i < numverts;i++, texvecvert++)
- {
- VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
- VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
- }
+ VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
+ VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
}
}
}
}
- else
- Host_Error("model %s has no skeletal or vertex morph animation data", model->name);
}
-int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
+int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
{
const float *boneframe;
float tempbonematrix[12], bonematrix[12];
return 6;
Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
}
+
+ if(!mod_alias_supporttagscale.integer)
+ Matrix4x4_Normalize3(outmatrix, outmatrix);
+
return 0;
}
-int Mod_Alias_GetTagIndexForName(const model_t *model, unsigned int skin, const char *tagname)
+int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, int poseframe, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
+{
+ const float *boneframe;
+
+ if(skin >= (unsigned int)model->numskins)
+ skin = 0;
+
+ if (model->num_bones)
+ {
+ if(tagindex >= model->num_bones || tagindex < 0)
+ return 1;
+ if (poseframe >= model->num_poses)
+ return 2;
+
+ boneframe = model->data_poses + poseframe * model->num_bones * 12;
+ *parentindex = model->data_bones[tagindex].parent;
+ *tagname = model->data_bones[tagindex].name;
+ Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12);
+ return 0;
+ }
+
+ if (model->num_tags)
+ {
+ if(tagindex >= model->num_tags || tagindex < 0)
+ return 1;
+ if (poseframe >= model->num_tagframes)
+ return 2;
+ *tagname = model->data_tags[tagindex].name;
+ Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
+ return 0;
+ }
+
+ return 2;
+}
+
+int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
{
int i;
if(skin >= (unsigned int)model->numskins)
skin = 0;
- if (model->data_overridetagnamesforskin && skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)skin].num_overridetagnames)
- for (i = 0;i < model->data_overridetagnamesforskin[skin].num_overridetagnames;i++)
- if (!strcasecmp(tagname, model->data_overridetagnamesforskin[skin].data_overridetagnames[i].name))
- return i + 1;
if (model->num_bones)
for (i = 0;i < model->num_bones;i++)
if (!strcasecmp(tagname, model->data_bones[i].name))
{
int i, k;
double scale;
- float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
+ float *basebonepose;
float *in12f = loadmodel->data_poses;
- float *out12f = basebonepose;
+ float *out12f;
float *outinv12f = loadmodel->data_baseboneposeinverse;
+ if (!loadmodel->num_bones)
+ return;
+ out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
{
if (loadmodel->data_bones[i].parent >= 0)
static void Mod_Alias_CalculateBoundingBox(void)
{
- int i, j;
int vnum;
qboolean firstvertex = true;
float dist, yawradius, radius;
float *v;
float *vertex3f;
- frameblend_t frameblend[4];
+ frameblend_t frameblend[MAX_FRAMEBLENDS];
memset(frameblend, 0, sizeof(frameblend));
frameblend[0].lerp = 1;
- vertex3f = Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
+ vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
VectorClear(loadmodel->normalmins);
VectorClear(loadmodel->normalmaxs);
yawradius = 0;
radius = 0;
- for (i = 0;i < loadmodel->numframes;i++)
+ for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
{
- for (j = 0, frameblend[0].frame = loadmodel->animscenes[i].firstframe;j < loadmodel->animscenes[i].framecount;j++, frameblend[0].frame++)
+ loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
+ for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
{
- Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
- for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
+ if (firstvertex)
{
- if (firstvertex)
- {
- firstvertex = false;
- VectorCopy(v, loadmodel->normalmins);
- VectorCopy(v, loadmodel->normalmaxs);
- }
- else
- {
- if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
- if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
- if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
- if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
- if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
- if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
- }
- dist = v[0] * v[0] + v[1] * v[1];
- if (yawradius < dist)
- yawradius = dist;
- dist += v[2] * v[2];
- if (radius < dist)
- radius = dist;
+ firstvertex = false;
+ VectorCopy(v, loadmodel->normalmins);
+ VectorCopy(v, loadmodel->normalmaxs);
+ }
+ else
+ {
+ if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
+ if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
+ if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
+ if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
+ if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
+ if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
}
+ dist = v[0] * v[0] + v[1] * v[1];
+ if (yawradius < dist)
+ yawradius = dist;
+ dist += v[2] * v[2];
+ if (radius < dist)
+ radius = dist;
}
}
- Mem_Free(vertex3f);
+ if (vertex3f)
+ Mem_Free(vertex3f);
radius = sqrt(radius);
yawradius = sqrt(yawradius);
loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
static void Mod_Alias_MorphMesh_CompileFrames(void)
{
int i, j;
- frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
+ frameblend_t frameblend[MAX_FRAMEBLENDS];
unsigned char *datapointer;
+ memset(frameblend, 0, sizeof(frameblend));
+ frameblend[0].lerp = 1;
datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
// this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
{
- frameblend[0].frame = i;
- Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
- Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer);
+ frameblend[0].subframe = i;
+ loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
+ Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
// encode the svector and tvector in 3 byte format for permanent storage
for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
{
- VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
- VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
+ VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
+ VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
}
}
}
-static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
{
int i;
+ vec3_t shiftstart, shiftend;
float segmentmins[3], segmentmaxs[3];
- frameblend_t frameblend[4];
+ frameblend_t frameblend[MAX_FRAMEBLENDS];
msurface_t *surface;
static int maxvertices = 0;
static float *vertex3f = NULL;
trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
memset(frameblend, 0, sizeof(frameblend));
- frameblend[0].frame = frame;
+ frameblend[0].subframe = frame;
frameblend[0].lerp = 1;
if (maxvertices < model->surfmesh.num_vertices)
{
maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
}
- if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
+ if (VectorCompare(boxmins, boxmaxs))
{
// line trace
- segmentmins[0] = min(start[0], end[0]) - 1;
- segmentmins[1] = min(start[1], end[1]) - 1;
- segmentmins[2] = min(start[2], end[2]) - 1;
- segmentmaxs[0] = max(start[0], end[0]) + 1;
- segmentmaxs[1] = max(start[1], end[1]) + 1;
- segmentmaxs[2] = max(start[2], end[2]) + 1;
+ VectorAdd(start, boxmins, shiftstart);
+ VectorAdd(end, boxmins, shiftend);
+ segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
+ segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
+ segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
+ segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
+ segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
+ segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
{
- Mod_Alias_GetMesh_Vertices(model, frameblend, vertex3f, NULL, NULL, NULL);
- Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
+ model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
+ Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
}
}
else
maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
}
- Mod_Alias_GetMesh_Vertices(model, frameblend, vertex3f, NULL, NULL, NULL);
- Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
+ model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
+ Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
}
}
}
texture->currentmaterialflags = texture->basematerialflags;
}
-static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
+static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
{
int i;
skinfileitem_t *skinfileitem;
- skinframe_t *tempskinframe;
if (skinfile)
{
// the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
{
// leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
- if (!strcmp(skinfileitem->name, meshname) && strcmp(skinfileitem->replacement, "common/nodraw") && strcmp(skinfileitem->replacement, "textures/common/nodraw"))
+ if (!strcmp(skinfileitem->name, meshname))
{
- if (!Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, false, false, true))
- {
- tempskinframe = R_SkinFrame_LoadExternal(skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
- if (!tempskinframe)
- if (cls.state != ca_dedicated)
- Con_Printf("mesh \"%s\": failed to load skin #%i \"%s\"\n", meshname, i, skinfileitem->replacement);
- Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe);
- }
+ Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
break;
}
}
{
// don't render unmentioned meshes
Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
- skin->basematerialflags = skin->currentmaterialflags = 0;
+ skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
}
}
}
else
- {
- if (!Mod_LoadTextureFromQ3Shader(skin, shadername, false, false, true))
- {
- tempskinframe = R_SkinFrame_LoadExternal(shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
- if (!tempskinframe)
- if (cls.state != ca_dedicated)
- Con_Printf("Can't find texture \"%s\" for mesh \"%s\", using grey checkerboard\n", shadername, meshname);
- Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe);
- }
- }
+ Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
}
#define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);
#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
-void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
float scales, scalet, interval;
loadmodel->modeldatatypestring = "MDL";
loadmodel->type = mod_alias;
+ loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
- loadmodel->surfacelist[0] = 0;
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces[0] = 0;
loadmodel->numskins = LittleLong(pinmodel->numskins);
BOUNDI(loadmodel->numskins,0,65536);
loadmodel->surfmesh.num_morphframes++;
}
}
+ loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
// store texture coordinates into temporary array, they will be stored
// after usage is determined (triangle data)
loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
}
+ // generate ushort elements array if possible
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
+
// load the frames
loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
// load the skins
skinfiles = Mod_LoadSkinFiles();
- loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
- loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
- loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
if (skinfiles)
{
+ loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
+ loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
Mod_FreeSkinFiles(skinfiles);
for (i = 0;i < loadmodel->numskins;i++)
}
else
{
+ loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
+ loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
totalskins = 0;
datapointer = startskins;
for (i = 0;i < loadmodel->numskins;i++)
}
}
- sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
+ dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
loadmodel->skinscenes[i].firstframe = totalskins;
loadmodel->skinscenes[i].framecount = groupskins;
loadmodel->skinscenes[i].framerate = 1.0f / interval;
for (j = 0;j < groupskins;j++)
{
if (groupskins > 1)
- sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
+ dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
else
- sprintf (name, "%s_%i", loadmodel->name, i);
- if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, true))
- {
- tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false);
- if (!tempskinframe)
- tempskinframe = R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight);
- Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
- }
+ dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
+ if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
+ Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
datapointer += skinwidth * skinheight;
totalskins++;
}
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
}
-void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
float iskinwidth, iskinheight;
unsigned short st;
}
*hash, **md2verthash, *md2verthashdata;
- skinframe_t *tempskinframe;
skinfile_t *skinfiles;
pinmodel = (md2_t *)buffer;
loadmodel->modeldatatypestring = "MD2";
loadmodel->type = mod_alias;
+ loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
loadmodel->numframes = LittleLong(pinmodel->num_frames);
loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
+ loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
skinwidth = LittleLong(pinmodel->skinwidth);
skinheight = LittleLong(pinmodel->skinheight);
iskinwidth = 1.0f / skinwidth;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
- loadmodel->surfacelist[0] = 0;
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces[0] = 0;
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
- {
- if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, false, false, true))
- {
- tempskinframe = R_SkinFrame_LoadExternal(inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
- if (!tempskinframe)
- Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin);
- Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, tempskinframe);
- }
- }
+ Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
}
else
{
Mem_Free(md2verthash);
Mem_Free(md2verthashdata);
+ // generate ushort elements array if possible
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
+
// load the frames
datapointer = (base + LittleLong(pinmodel->ofs_frames));
for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
}
-void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, k, version, meshvertices, meshtriangles;
unsigned char *data;
loadmodel->modeldatatypestring = "MD3";
loadmodel->type = mod_alias;
+ loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
+ loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
+ if (meshvertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
meshvertices = 0;
meshtriangles = 0;
{
if (memcmp(pinmesh->identifier, "IDP3", 4))
Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
- loadmodel->surfacelist[i] = i;
+ loadmodel->sortedmodelsurfaces[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
}
}
- if (LittleLong(pinmesh->num_shaders) >= 1)
- Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name);
- else
- for (j = 0;j < loadmodel->numskins;j++)
- Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
+ Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
}
Mod_Alias_MorphMesh_CompileFrames();
Mod_Alias_CalculateBoundingBox();
Mod_FreeSkinFiles(skinfiles);
+ Mod_MakeSortedSurfaces(loadmodel);
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
+ loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
+ || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
}
-void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
zymtype1header_t *pinmodel, *pheader;
unsigned char *pbase;
return;
}
+ loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
//zymlump_t lump_bones; // zymbone_t bone[numbones];
loadmodel->num_bones = pheader->numbones;
- loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
+ loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
for (i = 0;i < pheader->numbones;i++)
{
Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
}
- loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
+ loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
meshvertices = pheader->numverts;
meshtriangles = pheader->numtris;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
+ loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
//zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
poses = (float *) (pheader->lump_poses.start + pbase);
if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
- loadmodel->surfacelist[i] = i;
+ loadmodel->sortedmodelsurfaces[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
// since zym models do not have named sections, reuse their shader
// name as the section name
shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
- if (shadername[0])
- Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
- else
- for (j = 0;j < loadmodel->numskins;j++)
- Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
+ Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
}
Mod_FreeSkinFiles(skinfiles);
Mem_Free(vertbonecounts);
Mem_Free(verts);
+ Mod_MakeSortedSurfaces(loadmodel);
// compute all the mesh information that was not loaded from the file
Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
}
-void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
dpmheader_t *pheader;
dpmframe_t *frame;
return;
}
+ loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
for (i = 0;i < (int)pheader->num_meshs;i++)
{
int numverts = BigLong(dpmmesh->num_verts);
- meshvertices += numverts;;
+ meshvertices += numverts;
meshtriangles += BigLong(dpmmesh->num_tris);
dpmmesh++;
}
loadmodel->numframes = pheader->num_frames;
loadmodel->num_bones = pheader->num_bones;
- loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
+ loadmodel->num_poses = loadmodel->numframes;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
// do most allocations as one merged chunk
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
+ loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
+ if (meshvertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
for (i = 0;i < loadmodel->numskins;i++)
{
const float *intexcoord;
msurface_t *surface;
- loadmodel->surfacelist[i] = i;
+ loadmodel->sortedmodelsurfaces[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
}
// since dpm models do not have named sections, reuse their shader name as the section name
- if (dpmmesh->shadername[0])
- Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
- else
- for (j = 0;j < loadmodel->numskins;j++)
- Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
+ Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
}
Z_Free(bonepose);
Mod_FreeSkinFiles(skinfiles);
+ Mod_MakeSortedSurfaces(loadmodel);
// compute all the mesh information that was not loaded from the file
Mod_BuildBaseBonePoses();
// no idea why PSK/PSA files contain weird quaternions but they do...
#define PSKQUATNEGATIONS
-void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
pskchunk_t *pchunk;
skinfile_t *skinfiles;
char animname[MAX_QPATH];
+ size_t size;
pchunk = (pskchunk_t *)buffer;
if (strcmp(pchunk->id, "ACTRHEAD"))
loadmodel->modeldatatypestring = "PSK";
loadmodel->type = mod_alias;
+ loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
if (loadmodel->numskins < 1)
loadmodel->numskins = 1;
loadmodel->num_bones = numbones;
- loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
+ loadmodel->num_poses = loadmodel->numframes;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->surfmesh.num_vertices = meshvertices;
+ loadmodel->surfmesh.num_triangles = meshtriangles;
// do most allocations as one merged chunk
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
- loadmodel->surfmesh.num_vertices = meshvertices;
- loadmodel->surfmesh.num_triangles = meshtriangles;
- loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
- loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
- loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
- loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
- loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
+ loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
+ loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
+ loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
+ loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
+ loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
+ loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
for (i = 0;i < loadmodel->numskins;i++)
{
for (index = 0, i = 0;index < nummatts;index++)
{
// since psk models do not have named sections, reuse their shader name as the section name
- if (matts[index].name[0])
- Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
- else
- for (j = 0;j < loadmodel->numskins;j++)
- Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + index + j * loadmodel->num_surfaces, NULL);
- loadmodel->surfacelist[index] = index;
+ Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
+ loadmodel->sortedmodelsurfaces[index] = index;
loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
loadmodel->data_surfaces[index].num_firstvertex = 0;
loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
}
Mod_FreeSkinFiles(skinfiles);
Mem_Free(animfilebuffer);
+ Mod_MakeSortedSurfaces(loadmodel);
// compute all the mesh information that was not loaded from the file
// TODO: honor smoothing groups somehow?
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
}
+void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
+{
+#if 0
+ const char *textbase = (char *)buffer, *text = textbase;
+ char *s;
+ char *argv[512];
+ char line[1024];
+ char materialname[MAX_QPATH];
+ int j, index1, index2, index3, first, prev, index;
+ int argc;
+ int linelen;
+ int numtriangles = 0;
+ int maxtriangles = 32768;
+ int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
+ int *oldelement3i;
+ int numsurfaces = 0;
+ int maxsurfaces = 0;
+ msurface_t *surfaces = NULL;
+ int linenumber = 0;
+ int hashindex;
+ float *v, *vt, *vn;
+ float *oldv, *oldvt, *oldvn;
+ int maxv = 65536, numv = 1;
+ int maxvt = 65536, numvt = 1;
+ int maxvn = 65536, numvn = 1;
+ int maxverthash = 65536, numverthash = 0;
+ int numhashindex = 65536;
+ struct objverthash_s
+ {
+ struct objverthash_s *next;
+ int s;
+ int v;
+ int vt;
+ int vn;
+ }
+ *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
+ skinfile_t *skinfiles;
+
+ dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
+
+ skinfiles = Mod_LoadSkinFiles();
+
+ loadmodel->modeldatatypestring = "OBJ";
+
+ loadmodel->type = mod_alias;
+ loadmodel->AnimateVertices = NULL;
+ loadmodel->DrawSky = NULL;
+ loadmodel->DrawAddWaterPlanes = NULL;
+ loadmodel->Draw = R_Q1BSP_Draw;
+ loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
+ loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
+ loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
+ loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
+ loadmodel->DrawLight = R_Q1BSP_DrawLight;
+ loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+ loadmodel->PointSuperContents = NULL;
+
+ // parse the OBJ text now
+ for(;;)
+ {
+ if (!*text)
+ break;
+ linenumber++;
+ linelen = 0;
+ for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
+ line[linelen] = text[linelen];
+ line[linelen] = 0;
+ for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
+ argv[argc] = "";
+ argc = 0;
+ s = line;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ while (*s)
+ {
+ argv[argc++] = s;
+ while (*s > ' ')
+ s++;
+ if (!*s)
+ break;
+ *s++ = 0;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ }
+ if (!argc)
+ continue;
+ if (argv[0][0] == '#')
+ continue;
+ if (!strcmp(argv[0], "v"))
+ {
+ if (maxv <= numv)
+ {
+ maxv *= 2;
+ oldv = v;
+ v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
+ if (oldv)
+ {
+ memcpy(v, oldv, numv * sizeof(float[3]));
+ Mem_Free(oldv);
+ }
+ }
+ v[numv*3+0] = atof(argv[1]);
+ v[numv*3+1] = atof(argv[2]);
+ v[numv*3+2] = atof(argv[3]);
+ numv++;
+ }
+ else if (!strcmp(argv[0], "vt"))
+ {
+ if (maxvt <= numvt)
+ {
+ maxvt *= 2;
+ oldvt = vt;
+ vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
+ if (oldvt)
+ {
+ memcpy(vt, oldvt, numvt * sizeof(float[2]));
+ Mem_Free(oldvt);
+ }
+ }
+ vt[numvt*2+0] = atof(argv[1]);
+ vt[numvt*2+1] = atof(argv[2]);
+ numvt++;
+ }
+ else if (!strcmp(argv[0], "vn"))
+ {
+ if (maxvn <= numvn)
+ {
+ maxvn *= 2;
+ oldvn = vn;
+ vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
+ if (oldvn)
+ {
+ memcpy(vn, oldvn, numvn * sizeof(float[3]));
+ Mem_Free(oldvn);
+ }
+ }
+ vn[numvn*3+0] = atof(argv[1]);
+ vn[numvn*3+1] = atof(argv[2]);
+ vn[numvn*3+2] = atof(argv[3]);
+ numvn++;
+ }
+ else if (!strcmp(argv[0], "f"))
+ {
+ if (!surface)
+ {
+ if (maxsurfaces <= numsurfaces)
+ {
+ maxsurfaces++;
+ oldsurfaces = surfaces;
+ surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
+ if (oldsurfaces)
+ {
+ memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
+ Mem_Free(oldsurfaces);
+ }
+ }
+ surface = surfaces + numsurfaces++;
+ surface->
+ }
+ for (j = 1;j < argc;j++)
+ {
+ index1 = atoi(argv[j]);
+ while(argv[j][0] && argv[j][0] != '/')
+ argv[j]++;
+ if (argv[j][0])
+ argv[j]++;
+ if (index1 < 0)
+ index1 = numv + 1 - index1;
+ index2 = atoi(argv[j]);
+ if (index2 < 0)
+ index2 = numvt + 1 - index2;
+ while(argv[j][0] && argv[j][0] != '/')
+ argv[j]++;
+ if (argv[j][0])
+ argv[j]++;
+ index3 = atoi(argv[j]);
+ if (index3 < 0)
+ index3 = numvn + 1 - index3;
+ hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
+ for (hash = verthash[hashindex];hash;hash = hash->next)
+ if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
+ break;
+ if (!hash)
+ {
+ if (maxverthash <= numverthash)
+ {
+ maxverthash *= 2;
+ oldverthashdata = verthashdata;
+ verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
+ if (oldverthashdata)
+ {
+ memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
+ Mem_Free(oldverthashdata);
+ }
+ }
+ hash = verthashdata + numverthash++;
+ hash->next = verthash[hashindex];
+ hash->s = numsurfaces;
+ hash->v = index1;
+ hash->vt = index2;
+ hash->vn = index3;
+ verthash[hashindex] = hash;
+ }
+ index = (int)((size_t)(hash - verthashdata));
+ if (j == 1)
+ first = index;
+ else if (j >= 3)
+ {
+ if (maxtriangles <= numtriangles)
+ {
+ maxtriangles *= 2;
+ oldelement3i = element3i;
+ element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
+ if (oldelement3i)
+ {
+ memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
+ Mem_Free(oldelement3i);
+ }
+ }
+ element3i[numtriangles*3+0] = first;
+ element3i[numtriangles*3+1] = prev;
+ element3i[numtriangles*3+2] = index;
+ numtriangles++;
+ }
+ prev = index;
+ }
+ }
+ else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
+ surface = NULL;
+ else if (!!strcmp(argv[0], "usemtl"))
+ {
+ surface = NULL;
+ strlcpy(materialname, argv[1], sizeof(materialname);
+ }
+ text += linelen;
+ if (*text == '\r')
+ text++;
+ if (*text == '\n')
+ text++;
+ }
+
+ if (skinfiles)
+ Mod_FreeSkinFiles(skinfiles);
+
+ // now that we have the OBJ data loaded as-is, we can convert it
+ loadmodel->numskins = LittleLong(pinmodel->num_skins);
+ numxyz = LittleLong(pinmodel->num_xyz);
+ numst = LittleLong(pinmodel->num_st);
+ loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
+ loadmodel->numframes = LittleLong(pinmodel->num_frames);
+ loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
+ loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
+ skinwidth = LittleLong(pinmodel->skinwidth);
+ skinheight = LittleLong(pinmodel->skinheight);
+ iskinwidth = 1.0f / skinwidth;
+ iskinheight = 1.0f / skinheight;
+
+ loadmodel->num_surfaces = 1;
+ loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
+ loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces[0] = 0;
+ loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
+ loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
+ loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
+ loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
+
+ loadmodel->synctype = ST_RAND;
+
+ // load the skins
+ inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
+ skinfiles = Mod_LoadSkinFiles();
+ if (skinfiles)
+ {
+ loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
+ Mod_FreeSkinFiles(skinfiles);
+ }
+ else if (loadmodel->numskins)
+ {
+ // skins found (most likely not a player model)
+ loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
+ Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
+ }
+ else
+ {
+ // no skins (most likely a player model)
+ loadmodel->numskins = 1;
+ loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
+ }
+
+ loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
+ for (i = 0;i < loadmodel->numskins;i++)
+ {
+ loadmodel->skinscenes[i].firstframe = i;
+ loadmodel->skinscenes[i].framecount = 1;
+ loadmodel->skinscenes[i].loop = true;
+ loadmodel->skinscenes[i].framerate = 10;
+ }
+
+ // load the triangles and stvert data
+ inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
+ intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
+ md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
+ md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
+ // swap the triangle list
+ loadmodel->surfmesh.num_vertices = 0;
+ for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
+ {
+ for (j = 0;j < 3;j++)
+ {
+ xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
+ st = (unsigned short) LittleShort (intri[i].index_st[j]);
+ if (xyz >= numxyz)
+ {
+ Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
+ xyz = 0;
+ }
+ if (st >= numst)
+ {
+ Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
+ st = 0;
+ }
+ hashindex = (xyz * 256 + st) & 65535;
+ for (hash = md2verthash[hashindex];hash;hash = hash->next)
+ if (hash->xyz == xyz && hash->st == st)
+ break;
+ if (hash == NULL)
+ {
+ hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
+ hash->xyz = xyz;
+ hash->st = st;
+ hash->next = md2verthash[hashindex];
+ md2verthash[hashindex] = hash;
+ }
+ loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
+ }
+ }
+
+ vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t));
+ loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
+ loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
+ for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
+ {
+ int sts, stt;
+ hash = md2verthashdata + i;
+ vertremap[i] = hash->xyz;
+ sts = LittleShort(inst[hash->st*2+0]);
+ stt = LittleShort(inst[hash->st*2+1]);
+ if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
+ {
+ Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
+ sts = 0;
+ stt = 0;
+ }
+ loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
+ loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
+ }
+
+ Mem_Free(md2verthash);
+ Mem_Free(md2verthashdata);
+
+ // generate ushort elements array if possible
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
+
+ // load the frames
+ datapointer = (base + LittleLong(pinmodel->ofs_frames));
+ for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
+ {
+ int k;
+ trivertx_t *v;
+ trivertx_t *out;
+ pinframe = (md2frame_t *)datapointer;
+ datapointer += sizeof(md2frame_t);
+ // store the frame scale/translate into the appropriate array
+ for (j = 0;j < 3;j++)
+ {
+ loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
+ loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
+ }
+ // convert the vertices
+ v = (trivertx_t *)datapointer;
+ out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
+ for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
+ out[k] = v[vertremap[k]];
+ datapointer += numxyz * sizeof(trivertx_t);
+
+ strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
+ loadmodel->animscenes[i].firstframe = i;
+ loadmodel->animscenes[i].framecount = 1;
+ loadmodel->animscenes[i].framerate = 10;
+ loadmodel->animscenes[i].loop = true;
+ }
+
+ Mem_Free(vertremap);
+
+ Mod_MakeSortedSurfaces(loadmodel);
+ Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
+ Mod_Alias_CalculateBoundingBox();
+ Mod_Alias_MorphMesh_CompileFrames();
+
+ surface = loadmodel->data_surfaces;
+ surface->texture = loadmodel->data_textures;
+ surface->num_firsttriangle = 0;
+ surface->num_triangles = loadmodel->surfmesh.num_triangles;
+ surface->num_firstvertex = 0;
+ surface->num_vertices = loadmodel->surfmesh.num_vertices;
+
+ loadmodel->surfmesh.isanimated = false;
+#endif
+}