Page 1 of 1

NEW GZDoom tool called md2modeldef

Posted: Mon Nov 04, 2019 3:47 am
by CBM
Hi..

I was wondering if there might be some usefull applications out there that can do one or more of the following:

1) automatically write modeldef code for a given md2 model

- could be done by reading the MD2 file and getting the list of animations as well as framecount etc then output to a text file

2) automatically convert an OBJ file to an MD2 file with animations (standard humanoid Quake 2 animations)

- could be done by making it look for groups with names such as "RightLegUpper1...n", "RightLegLower1...n", "RightArmUpper1...n" etc
- then make it create a number of frames where it moves and/or rotates the meshes in the groups according to some predefined pattern

3) automatically combine textures to a single texture and update texture coordinates?

- could be done by reading all materials and their images, then create a new image and update materials and texture mapping

I am looking in to some c code that should be able to load MD2 files, when I figure out how to get all dependencies installed correctly and it compiles with GCC, then I am going to experiment with the above if no such tool(s) exists yet

Re: usefull applications

Posted: Mon Nov 04, 2019 8:24 am
by Kinsie
1.) There isn't.
2.) OBJ files don't have animations, and Quake 2 doesn't have skeletal animations, so there's nothing here to work with.
3.) I dunno.

Re: usefull applications

Posted: Mon Nov 04, 2019 8:45 am
by CBM
Kinsie wrote:1.) There isn't.
2.) OBJ files don't have animations, and Quake 2 doesn't have skeletal animations, so there's nothing here to work with.
3.) I dunno.
I Know obj files do not have animations and that md2 only support mesh based animation

Some tools can Translate skeleton anims to mesh anims though

But

If the obj was Edited such that limb meshes were in groups with predefined Known names, then a humanoid mesh could be animated if the tool read ie an xml file that could specify how to make an animated md2 model from a static obj file

An xml that specify the changes needed on a frame by frame basis

Lets Say the tool want to make a Walk anim

It then could read an xml that tells it that the meshes in Group RightLegUpper and RightLegLower and RightFoot must make the following movements and so on ...

That could Also aloow for using the same animation def for multiple similar static objs

Just like skeletal animations

Re: usefull applications

Posted: Mon Nov 04, 2019 9:10 am
by Kinsie
That's a lot of effort to try and get out of rigging a model rip you found on models-resource up to a skeleton.

Re: usefull applications

Posted: Mon Nov 04, 2019 10:57 am
by CBM
Kinsie wrote:That's a lot of effort to try and get out of rigging a model rip you found on models-resource up to a skeleton.
True

And it Will take Some time

My first goal is to make the tool able to output a modeldef when fed an md2 file

....that Should be easy

I got the md2 example code Running in gcc today

Re: usefull applications

Posted: Mon Nov 04, 2019 11:27 am
by Graf Zahl
Why MD2? Unless your data is already in that format, stay away from it, the vertex resolution is far too low for any decent result.

Re: usefull applications

Posted: Mon Nov 04, 2019 1:10 pm
by Enjay
Absolutely. MD2 has awful vertex resolution - saving the model will usually end up with vertices moving versus what you could see in the editor and all your nicely placed fine details will just end up looking a mess.

Even more, if the model is animated, vertices can wobble around all over the place between animation frames - even if it is a vertex that isn't supposed to move, another part of the model moving can cause wobble in the supposedly stationary one. And, again, it doesn't usually become obvious until you save and by that time it may be too late.

Re: usefull applications

Posted: Mon Nov 04, 2019 1:28 pm
by CBM
well

MD2 has named animations and it is easy to read.. plus I have a lot of md2models stored (mainly old Q2 player models)

and it seems there is a gap regarding tools targeted at using models with GZDoom

the MD2 reading source code example I found was easy to use (had to throw out the rendering stuff though since I could not get it satisfied with all dependencies.. but thats ok.. it is not for displaying models anyway)

I might do an MD3 version once I get this tool to function as I need it to

progress report

Code: Select all

C:\gcc-prj\md2modeldef\bin\Debug>md2modeldef.exe
usage: md2modeldef.exe <filename.md2>

C:\gcc-prj\md2modeldef\bin\Debug>md2modeldef.exe monstercartest.md2
---------------------------------------
HEADER MD2 FILE monstercartest.md2
---------------------------------------
ident 844121161
version 8
---------------------------------------
skinwidth 512
skinheight 512
---------------------------------------
framesize 1620
---------------------------------------
num_skins 2
num_vertices 395
num_st 2310
num_tris 770
num_glcmds 7701
num_frames 1
---------------------------------------
offset_skins 68
offset_st 196
offset_tris 9436
offset_frames 18676
offset_glcmds 20296
offset_end 51100
---------------------------------------

C:\gcc-prj\md2modeldef\bin\Debug>
it can display a header now.. yaaay

next step.. to make it write out a modeldef to fit the MD2 model


NOTE

this project is based on
md2.c -- md2 model loader, last modification: aug. 14, 2007, Copyright (c) 2005-2007 David HENRY


source so far..

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/*
 * md2.c -- md2 model loader
 * last modification: aug. 14, 2007
 *
 * Copyright (c) 2005-2007 David HENRY
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * gcc -Wall -ansi -lGL -lGLU -lglut md2.c -o md2
 */



/* Vector */
typedef float vec3_t[3];

/* MD2 header */
struct md2_header_t
{
  int ident;
  int version;

  int skinwidth;
  int skinheight;

  int framesize;

  int num_skins;
  int num_vertices;
  int num_st;
  int num_tris;
  int num_glcmds;
  int num_frames;

  int offset_skins;
  int offset_st;
  int offset_tris;
  int offset_frames;
  int offset_glcmds;
  int offset_end;
};

/* Texture name */
struct md2_skin_t
{
  char name[64];
};

/* Texture coords */
struct md2_texCoord_t
{
  short s;
  short t;
};

/* Triangle info */
struct md2_triangle_t
{
  unsigned short vertex[3];
  unsigned short st[3];
};

/* Compressed vertex */
struct md2_vertex_t
{
  unsigned char v[3];
  unsigned char normalIndex;
};

/* Model frame */
struct md2_frame_t
{
  vec3_t scale;
  vec3_t translate;
  char name[16];
  struct md2_vertex_t *verts;
};

/* GL command packet */
struct md2_glcmd_t
{
  float s;
  float t;
  int index;
};

/* MD2 model structure */
struct md2_model_t
{
  struct md2_header_t header;

  struct md2_skin_t *skins;
  struct md2_texCoord_t *texcoords;
  struct md2_triangle_t *triangles;
  struct md2_frame_t *frames;
  int *glcmds;

  //GLuint tex_id;
};

/* Table of precalculated normals */
vec3_t anorms_table[162] = {
#include "anorms.h"
};

/*** An MD2 model ***/
struct md2_model_t md2file;


/**
 * Load an MD2 model from file.
 *
 * Note: MD2 format stores model's data in little-endian ordering.  On
 * big-endian machines, you'll have to perform proper conversions.
 */
int
ReadMD2Model (const char *filename, struct md2_model_t *mdl)
{
  FILE *fp;
  int i;

  fp = fopen (filename, "rb");
  if (!fp)
    {
      fprintf (stderr, "Error: couldn't open \"%s\"!\n", filename);
      return 0;
    }

  /* Read header */
  fread (&mdl->header, 1, sizeof (struct md2_header_t), fp);

  if ((mdl->header.ident != 844121161) ||
      (mdl->header.version != 8))
    {
      /* Error! */
      fprintf (stderr, "Error: bad version or identifier\n");
      fclose (fp);
      return 0;
    }

  /* Memory allocations */
  mdl->skins = (struct md2_skin_t *)
    malloc (sizeof (struct md2_skin_t) * mdl->header.num_skins);
  mdl->texcoords = (struct md2_texCoord_t *)
    malloc (sizeof (struct md2_texCoord_t) * mdl->header.num_st);
  mdl->triangles = (struct md2_triangle_t *)
    malloc (sizeof (struct md2_triangle_t) * mdl->header.num_tris);
  mdl->frames = (struct md2_frame_t *)
    malloc (sizeof (struct md2_frame_t) * mdl->header.num_frames);
  mdl->glcmds = (int *)malloc (sizeof (int) * mdl->header.num_glcmds);

  /* Read model data */
  fseek (fp, mdl->header.offset_skins, SEEK_SET);
  fread (mdl->skins, sizeof (struct md2_skin_t),
	 mdl->header.num_skins, fp);

  fseek (fp, mdl->header.offset_st, SEEK_SET);
  fread (mdl->texcoords, sizeof (struct md2_texCoord_t),
	 mdl->header.num_st, fp);

  fseek (fp, mdl->header.offset_tris, SEEK_SET);
  fread (mdl->triangles, sizeof (struct md2_triangle_t),
	 mdl->header.num_tris, fp);

  fseek (fp, mdl->header.offset_glcmds, SEEK_SET);
  fread (mdl->glcmds, sizeof (int), mdl->header.num_glcmds, fp);

  /* Read frames */
  fseek (fp, mdl->header.offset_frames, SEEK_SET);
  for (i = 0; i < mdl->header.num_frames; ++i)
    {
      /* Memory allocation for vertices of this frame */
      mdl->frames[i].verts = (struct md2_vertex_t *)
	malloc (sizeof (struct md2_vertex_t) * mdl->header.num_vertices);

      /* Read frame data */
      fread (mdl->frames[i].scale, sizeof (vec3_t), 1, fp);
      fread (mdl->frames[i].translate, sizeof (vec3_t), 1, fp);
      fread (mdl->frames[i].name, sizeof (char), 16, fp);
      fread (mdl->frames[i].verts, sizeof (struct md2_vertex_t),
	     mdl->header.num_vertices, fp);
    }

  fclose (fp);

  /* Read header */
  fread (&mdl->header, 1, sizeof (struct md2_header_t), fp);

  printf("--------------------------------------- \n");
  printf("HEADER MD2 FILE %s\n", filename);
  printf("--------------------------------------- \n");
  printf("ident %d\n", mdl->header.ident);
  printf("version %d\n", mdl->header.version);
  printf("--------------------------------------- \n");
  printf("skinwidth %d\n", mdl->header.skinwidth);
  printf("skinheight %d\n", mdl->header.skinheight);
  printf("--------------------------------------- \n");
  printf("framesize %d\n", mdl->header.framesize);
  printf("--------------------------------------- \n");
  printf("num_skins %d\n", mdl->header.num_skins);
  printf("num_vertices %d\n", mdl->header.num_vertices);
  printf("num_st %d\n", mdl->header.num_st);
  printf("num_tris %d\n", mdl->header.num_tris);
  printf("num_glcmds %d\n", mdl->header.num_glcmds);
  printf("num_frames %d\n", mdl->header.num_frames);
  printf("--------------------------------------- \n");
  printf("offset_skins %d\n", mdl->header.offset_skins);
  printf("offset_st %d\n", mdl->header.offset_st);
  printf("offset_tris %d\n", mdl->header.offset_tris);
  printf("offset_frames %d\n", mdl->header.offset_frames);
  printf("offset_glcmds %d\n", mdl->header.offset_glcmds);
  printf("offset_end %d\n", mdl->header.offset_end);
  printf("--------------------------------------- \n");

  return 1;
}

/**
 * Free resources allocated for the model.
 */
void
FreeModel (struct md2_model_t *mdl)
{
  int i;

  if (mdl->skins)
    {
      free (mdl->skins);
      mdl->skins = NULL;
    }

  if (mdl->texcoords)
    {
      free (mdl->texcoords);
      mdl->texcoords = NULL;
    }

  if (mdl->triangles)
    {
      free (mdl->triangles);
      mdl->triangles = NULL;
    }

  if (mdl->glcmds)
    {
      free (mdl->glcmds);
      mdl->glcmds = NULL;
    }

  if (mdl->frames)
    {
      for (i = 0; i < mdl->header.num_frames; ++i)
	{
	  free (mdl->frames[i].verts);
	  mdl->frames[i].verts = NULL;
	}

      free (mdl->frames);
      mdl->frames = NULL;
    }
}


/**
 * Calculate the current frame in animation beginning at frame
 * 'start' and ending at frame 'end', given interpolation percent.
 * interp will be reseted to 0.0 if the next frame is reached.
 */
void
Animate (int start, int end, int *frame, float *interp)
{
  if ((*frame < start) || (*frame > end))
    *frame = start;

  if (*interp >= 1.0f)
    {
      /* Move to next frame */
      *interp = 0.0f;
      (*frame)++;

      if (*frame >= end)
	*frame = start;
    }
}

void
init (const char *filename)
{

  /* Load MD2 model file */
  if (!ReadMD2Model (filename, &md2file))
    exit (EXIT_FAILURE);


  cleanup ();

}

void
cleanup ()
{
  FreeModel (&md2file);
}


void
keyboard (unsigned char key, int x, int y)
{
  /* Escape */
  if (key == 27)
    exit (0);
}

int
main (int argc, char *argv[])
{
  if (argc < 2)
    {
      fprintf (stderr, "usage: %s <filename.md2>\n", argv[0]);
      return 0; //-1;
    }
    else
    {
      init (argv[1]);




    }

//  glutInit (&argc, argv);

//  atexit (cleanup);

//  glutReshapeFunc (reshape);
//  glutDisplayFunc (display);
//  glutKeyboardFunc (keyboard);

 // glutMainLoop ();

  return 0;
}

needs the this header file

Code: Select all

/*
 *	anorms.h - header file
 */
{ -0.525731f,  0.000000f,  0.850651f },
{ -0.442863f,  0.238856f,  0.864188f },
{ -0.295242f,  0.000000f,  0.955423f },
{ -0.309017f,  0.500000f,  0.809017f },
{ -0.162460f,  0.262866f,  0.951056f },
{  0.000000f,  0.000000f,  1.000000f },
{  0.000000f,  0.850651f,  0.525731f },
{ -0.147621f,  0.716567f,  0.681718f },
{  0.147621f,  0.716567f,  0.681718f },
{  0.000000f,  0.525731f,  0.850651f },
{  0.309017f,  0.500000f,  0.809017f },
{  0.525731f,  0.000000f,  0.850651f },
{  0.295242f,  0.000000f,  0.955423f },
{  0.442863f,  0.238856f,  0.864188f },
{  0.162460f,  0.262866f,  0.951056f },
{ -0.681718f,  0.147621f,  0.716567f },
{ -0.809017f,  0.309017f,  0.500000f },
{ -0.587785f,  0.425325f,  0.688191f },
{ -0.850651f,  0.525731f,  0.000000f },
{ -0.864188f,  0.442863f,  0.238856f },
{ -0.716567f,  0.681718f,  0.147621f },
{ -0.688191f,  0.587785f,  0.425325f },
{ -0.500000f,  0.809017f,  0.309017f },
{ -0.238856f,  0.864188f,  0.442863f },
{ -0.425325f,  0.688191f,  0.587785f },
{ -0.716567f,  0.681718f, -0.147621f },
{ -0.500000f,  0.809017f, -0.309017f },
{ -0.525731f,  0.850651f,  0.000000f },
{  0.000000f,  0.850651f, -0.525731f },
{ -0.238856f,  0.864188f, -0.442863f },
{  0.000000f,  0.955423f, -0.295242f },
{ -0.262866f,  0.951056f, -0.162460f },
{  0.000000f,  1.000000f,  0.000000f },
{  0.000000f,  0.955423f,  0.295242f },
{ -0.262866f,  0.951056f,  0.162460f },
{  0.238856f,  0.864188f,  0.442863f },
{  0.262866f,  0.951056f,  0.162460f },
{  0.500000f,  0.809017f,  0.309017f },
{  0.238856f,  0.864188f, -0.442863f },
{  0.262866f,  0.951056f, -0.162460f },
{  0.500000f,  0.809017f, -0.309017f },
{  0.850651f,  0.525731f,  0.000000f },
{  0.716567f,  0.681718f,  0.147621f },
{  0.716567f,  0.681718f, -0.147621f },
{  0.525731f,  0.850651f,  0.000000f },
{  0.425325f,  0.688191f,  0.587785f },
{  0.864188f,  0.442863f,  0.238856f },
{  0.688191f,  0.587785f,  0.425325f },
{  0.809017f,  0.309017f,  0.500000f },
{  0.681718f,  0.147621f,  0.716567f },
{  0.587785f,  0.425325f,  0.688191f },
{  0.955423f,  0.295242f,  0.000000f },
{  1.000000f,  0.000000f,  0.000000f },
{  0.951056f,  0.162460f,  0.262866f },
{  0.850651f, -0.525731f,  0.000000f },
{  0.955423f, -0.295242f,  0.000000f },
{  0.864188f, -0.442863f,  0.238856f },
{  0.951056f, -0.162460f,  0.262866f },
{  0.809017f, -0.309017f,  0.500000f },
{  0.681718f, -0.147621f,  0.716567f },
{  0.850651f,  0.000000f,  0.525731f },
{  0.864188f,  0.442863f, -0.238856f },
{  0.809017f,  0.309017f, -0.500000f },
{  0.951056f,  0.162460f, -0.262866f },
{  0.525731f,  0.000000f, -0.850651f },
{  0.681718f,  0.147621f, -0.716567f },
{  0.681718f, -0.147621f, -0.716567f },
{  0.850651f,  0.000000f, -0.525731f },
{  0.809017f, -0.309017f, -0.500000f },
{  0.864188f, -0.442863f, -0.238856f },
{  0.951056f, -0.162460f, -0.262866f },
{  0.147621f,  0.716567f, -0.681718f },
{  0.309017f,  0.500000f, -0.809017f },
{  0.425325f,  0.688191f, -0.587785f },
{  0.442863f,  0.238856f, -0.864188f },
{  0.587785f,  0.425325f, -0.688191f },
{  0.688191f,  0.587785f, -0.425325f },
{ -0.147621f,  0.716567f, -0.681718f },
{ -0.309017f,  0.500000f, -0.809017f },
{  0.000000f,  0.525731f, -0.850651f },
{ -0.525731f,  0.000000f, -0.850651f },
{ -0.442863f,  0.238856f, -0.864188f },
{ -0.295242f,  0.000000f, -0.955423f },
{ -0.162460f,  0.262866f, -0.951056f },
{  0.000000f,  0.000000f, -1.000000f },
{  0.295242f,  0.000000f, -0.955423f },
{  0.162460f,  0.262866f, -0.951056f },
{ -0.442863f, -0.238856f, -0.864188f },
{ -0.309017f, -0.500000f, -0.809017f },
{ -0.162460f, -0.262866f, -0.951056f },
{  0.000000f, -0.850651f, -0.525731f },
{ -0.147621f, -0.716567f, -0.681718f },
{  0.147621f, -0.716567f, -0.681718f },
{  0.000000f, -0.525731f, -0.850651f },
{  0.309017f, -0.500000f, -0.809017f },
{  0.442863f, -0.238856f, -0.864188f },
{  0.162460f, -0.262866f, -0.951056f },
{  0.238856f, -0.864188f, -0.442863f },
{  0.500000f, -0.809017f, -0.309017f },
{  0.425325f, -0.688191f, -0.587785f },
{  0.716567f, -0.681718f, -0.147621f },
{  0.688191f, -0.587785f, -0.425325f },
{  0.587785f, -0.425325f, -0.688191f },
{  0.000000f, -0.955423f, -0.295242f },
{  0.000000f, -1.000000f,  0.000000f },
{  0.262866f, -0.951056f, -0.162460f },
{  0.000000f, -0.850651f,  0.525731f },
{  0.000000f, -0.955423f,  0.295242f },
{  0.238856f, -0.864188f,  0.442863f },
{  0.262866f, -0.951056f,  0.162460f },
{  0.500000f, -0.809017f,  0.309017f },
{  0.716567f, -0.681718f,  0.147621f },
{  0.525731f, -0.850651f,  0.000000f },
{ -0.238856f, -0.864188f, -0.442863f },
{ -0.500000f, -0.809017f, -0.309017f },
{ -0.262866f, -0.951056f, -0.162460f },
{ -0.850651f, -0.525731f,  0.000000f },
{ -0.716567f, -0.681718f, -0.147621f },
{ -0.716567f, -0.681718f,  0.147621f },
{ -0.525731f, -0.850651f,  0.000000f },
{ -0.500000f, -0.809017f,  0.309017f },
{ -0.238856f, -0.864188f,  0.442863f },
{ -0.262866f, -0.951056f,  0.162460f },
{ -0.864188f, -0.442863f,  0.238856f },
{ -0.809017f, -0.309017f,  0.500000f },
{ -0.688191f, -0.587785f,  0.425325f },
{ -0.681718f, -0.147621f,  0.716567f },
{ -0.442863f, -0.238856f,  0.864188f },
{ -0.587785f, -0.425325f,  0.688191f },
{ -0.309017f, -0.500000f,  0.809017f },
{ -0.147621f, -0.716567f,  0.681718f },
{ -0.425325f, -0.688191f,  0.587785f },
{ -0.162460f, -0.262866f,  0.951056f },
{  0.442863f, -0.238856f,  0.864188f },
{  0.162460f, -0.262866f,  0.951056f },
{  0.309017f, -0.500000f,  0.809017f },
{  0.147621f, -0.716567f,  0.681718f },
{  0.000000f, -0.525731f,  0.850651f },
{  0.425325f, -0.688191f,  0.587785f },
{  0.587785f, -0.425325f,  0.688191f },
{  0.688191f, -0.587785f,  0.425325f },
{ -0.955423f,  0.295242f,  0.000000f },
{ -0.951056f,  0.162460f,  0.262866f },
{ -1.000000f,  0.000000f,  0.000000f },
{ -0.850651f,  0.000000f,  0.525731f },
{ -0.955423f, -0.295242f,  0.000000f },
{ -0.951056f, -0.162460f,  0.262866f },
{ -0.864188f,  0.442863f, -0.238856f },
{ -0.951056f,  0.162460f, -0.262866f },
{ -0.809017f,  0.309017f, -0.500000f },
{ -0.864188f, -0.442863f, -0.238856f },
{ -0.951056f, -0.162460f, -0.262866f },
{ -0.809017f, -0.309017f, -0.500000f },
{ -0.681718f,  0.147621f, -0.716567f },
{ -0.681718f, -0.147621f, -0.716567f },
{ -0.850651f,  0.000000f, -0.525731f },
{ -0.688191f,  0.587785f, -0.425325f },
{ -0.587785f,  0.425325f, -0.688191f },
{ -0.425325f,  0.688191f, -0.587785f },
{ -0.425325f, -0.688191f, -0.587785f },
{ -0.587785f, -0.425325f, -0.688191f },
{ -0.688191f, -0.587785f, -0.425325f }

Re: usefull applications

Posted: Mon Nov 04, 2019 1:46 pm
by Enjay
CBM wrote:MD2 has named animations and it is easy to read..
True, and that is one of the few advantages that MD2 has.

But to illustrate the level of inaccuracy in the format, here is the Ravenclaw from Jedi Outcast in MD3 format:
Image


And here is the same engine saved in MD2 format:
Image

Re: usefull applications

Posted: Mon Nov 04, 2019 1:50 pm
by CBM
yes okay, that is .. not optimal

I found some MD3 information on the website for Maverick

https://www.icculus.org/homepages/phaet ... ormat.html

could be interesting to make a plugin for maverick that could output a suggestion to a GZDoom modeldef

Re: usefull applications

Posted: Mon Nov 04, 2019 3:27 pm
by CBM
quick update..now it can yell at you for feeding it md3 models

Code: Select all

C:\gcc-prj\md2modeldef\bin\Debug>md2modeldef.exe upper.md3
Error: bad version or identifier
Quake 3 model identifier

C:\gcc-prj\md2modeldef\bin\Debug>
I think I might make it a tool to handle both md2 and md3... once it can actually do something usefull... I will make a thread about it in the appropiate sub forum (software and ports?)

Re: usefull applications

Posted: Tue Nov 05, 2019 6:09 am
by CBM
update... now it can read md2 frame names

Code: Select all

C:\c-prj\md2test\bin\Debug>md2test.exe bird_final.md2
frame name: fly01
frame number: 0
frame name: fly02
frame number: 1
frame name: fly03
frame number: 2
frame name: fly04
frame number: 3
frame name: fly05
frame number: 4
frame name: fly06
frame number: 5
frame name: fly07
frame number: 6
frame name: fly08
frame number: 7
frame name: fly09
frame number: 8
frame name: fly10
frame number: 9
frame name: fly11
frame number: 10
frame name: fly12
frame number: 11
frame name: fly13
frame number: 12
frame name: fly14
frame number: 13
frame name: fly15
frame number: 14
frame name: fly16
frame number: 15
frame name: fly17
frame number: 16
frame name: fly18
frame number: 17
frame name: fly19
frame number: 18
frame name: fly20
frame number: 19
frame name: fly21
frame number: 20
---------------------------------------
HEADER MD2 FILE bird_final.md2
---------------------------------------
ident 844121161
version 8
---------------------------------------
skinwidth 244
skinheight 249
---------------------------------------
framesize 944
---------------------------------------
num_skins 0
num_vertices 226
num_st 915
num_tris 305
num_glcmds 3051
num_frames 21
---------------------------------------
offset_skins 68
offset_st 68
offset_tris 3728
offset_frames 7388
offset_glcmds 27212
offset_end 39416
---------------------------------------

C:\c-prj\md2test\bin\Debug>md2test.exe tris.md2
frame name: stand01
frame number: 0
frame name: stand02
frame number: 1
frame name: stand03
frame number: 2
frame name: stand04
frame number: 3
frame name: stand05
frame number: 4
frame name: stand06
frame number: 5
frame name: stand07
frame number: 6
frame name: stand08
frame number: 7
frame name: stand09
frame number: 8
frame name: stand10
frame number: 9
frame name: stand11
frame number: 10
frame name: stand12
frame number: 11
frame name: stand13
frame number: 12
frame name: stand14
frame number: 13
frame name: stand15
frame number: 14
frame name: stand16
frame number: 15
frame name: stand17
frame number: 16
frame name: stand18
frame number: 17
frame name: stand19
frame number: 18
frame name: stand20
frame number: 19
frame name: stand21
frame number: 20
frame name: stand22
frame number: 21
frame name: stand23
frame number: 22
frame name: stand24
frame number: 23
frame name: stand25
frame number: 24
frame name: stand26
frame number: 25
frame name: stand27
frame number: 26
frame name: stand28
frame number: 27
frame name: stand29
frame number: 28
frame name: stand30
frame number: 29
frame name: stand31
frame number: 30
frame name: stand32
frame number: 31
frame name: stand33
frame number: 32
frame name: stand34
frame number: 33
frame name: stand35
frame number: 34
frame name: stand36
frame number: 35
frame name: stand37
frame number: 36
frame name: stand38
frame number: 37
frame name: stand39
frame number: 38
frame name: stand40
frame number: 39
frame name: run1
frame number: 40
frame name: run2
frame number: 41
frame name: run3
frame number: 42
frame name: run4
frame number: 43
frame name: run5
frame number: 44
frame name: run6
frame number: 45
frame name: attack1
frame number: 46
frame name: attack2
frame number: 47
frame name: attack3
frame number: 48
frame name: attack4
frame number: 49
frame name: attack5
frame number: 50
frame name: attack6
frame number: 51
frame name: attack7
frame number: 52
frame name: attack8
frame number: 53
frame name: pain101
frame number: 54
frame name: pain102
frame number: 55
frame name: pain103
frame number: 56
frame name: pain104
frame number: 57
frame name: pain201
frame number: 58
frame name: pain202
frame number: 59
frame name: pain203
frame number: 60
frame name: pain204
frame number: 61
frame name: pain301
frame number: 62
frame name: pain302
frame number: 63
frame name: pain303
frame number: 64
frame name: pain304
frame number: 65
frame name: jump1
frame number: 66
frame name: jump2
frame number: 67
frame name: jump3
frame number: 68
frame name: jump4
frame number: 69
frame name: jump5
frame number: 70
frame name: jump6
frame number: 71
frame name: flip01
frame number: 72
frame name: flip02
frame number: 73
frame name: flip03
frame number: 74
frame name: flip04
frame number: 75
frame name: flip05
frame number: 76
frame name: flip06
frame number: 77
frame name: flip07
frame number: 78
frame name: flip08
frame number: 79
frame name: flip09
frame number: 80
frame name: flip10
frame number: 81
frame name: flip11
frame number: 82
frame name: flip12
frame number: 83
frame name: salute01
frame number: 84
frame name: salute02
frame number: 85
frame name: salute03
frame number: 86
frame name: salute04
frame number: 87
frame name: salute05
frame number: 88
frame name: salute06
frame number: 89
frame name: salute07
frame number: 90
frame name: salute08
frame number: 91
frame name: salute09
frame number: 92
frame name: salute10
frame number: 93
frame name: salute11
frame number: 94
frame name: taunt01
frame number: 95
frame name: taunt02
frame number: 96
frame name: taunt03
frame number: 97
frame name: taunt04
frame number: 98
frame name: taunt05
frame number: 99
frame name: taunt06
frame number: 100
frame name: taunt07
frame number: 101
frame name: taunt08
frame number: 102
frame name: taunt09
frame number: 103
frame name: taunt10
frame number: 104
frame name: taunt11
frame number: 105
frame name: taunt12
frame number: 106
frame name: taunt13
frame number: 107
frame name: taunt14
frame number: 108
frame name: taunt15
frame number: 109
frame name: taunt16
frame number: 110
frame name: taunt17
frame number: 111
frame name: wave01
frame number: 112
frame name: wave02
frame number: 113
frame name: wave03
frame number: 114
frame name: wave04
frame number: 115
frame name: wave05
frame number: 116
frame name: wave06
frame number: 117
frame name: wave07
frame number: 118
frame name: wave08
frame number: 119
frame name: wave09
frame number: 120
frame name: wave10
frame number: 121
frame name: wave11
frame number: 122
frame name: point01
frame number: 123
frame name: point02
frame number: 124
frame name: point03
frame number: 125
frame name: point04
frame number: 126
frame name: point05
frame number: 127
frame name: point06
frame number: 128
frame name: point07
frame number: 129
frame name: point08
frame number: 130
frame name: point09
frame number: 131
frame name: point10
frame number: 132
frame name: point11
frame number: 133
frame name: point12
frame number: 134
frame name: crstand01
frame number: 135
frame name: crstand02
frame number: 136
frame name: crstand03
frame number: 137
frame name: crstand04
frame number: 138
frame name: crstand05
frame number: 139
frame name: crstand06
frame number: 140
frame name: crstand07
frame number: 141
frame name: crstand08
frame number: 142
frame name: crstand09
frame number: 143
frame name: crstand10
frame number: 144
frame name: crstand11
frame number: 145
frame name: crstand12
frame number: 146
frame name: crstand13
frame number: 147
frame name: crstand14
frame number: 148
frame name: crstand15
frame number: 149
frame name: crstand16
frame number: 150
frame name: crstand17
frame number: 151
frame name: crstand18
frame number: 152
frame name: crstand19
frame number: 153
frame name: crwalk1
frame number: 154
frame name: crwalk2
frame number: 155
frame name: crwalk3
frame number: 156
frame name: crwalk4
frame number: 157
frame name: crwalk5
frame number: 158
frame name: crwalk6
frame number: 159
frame name: crattak1
frame number: 160
frame name: crattak2
frame number: 161
frame name: crattak3
frame number: 162
frame name: crattack4
frame number: 163
frame name: crattak5
frame number: 164
frame name: crattak6
frame number: 165
frame name: crattak7
frame number: 166
frame name: crattak8
frame number: 167
frame name: crattak9
frame number: 168
frame name: crpain1
frame number: 169
frame name: crpain2
frame number: 170
frame name: crpain3
frame number: 171
frame name: crpain4
frame number: 172
frame name: crdeath1
frame number: 173
frame name: crdeath2
frame number: 174
frame name: crdeath3
frame number: 175
frame name: crdeath4
frame number: 176
frame name: crdeath5
frame number: 177
frame name: death101
frame number: 178
frame name: death102
frame number: 179
frame name: death103
frame number: 180
frame name: death104
frame number: 181
frame name: death105
frame number: 182
frame name: death106
frame number: 183
frame name: death201
frame number: 184
frame name: death202
frame number: 185
frame name: death203
frame number: 186
frame name: death204
frame number: 187
frame name: death205
frame number: 188
frame name: death206
frame number: 189
frame name: death301
frame number: 190
frame name: death302
frame number: 191
frame name: death303
frame number: 192
frame name: death304
frame number: 193
frame name: death305
frame number: 194
frame name: death306
frame number: 195
frame name: death307
frame number: 196
frame name: death308
frame number: 197
--------------------------------------- 
HEADER MD2 FILE tris.md2
--------------------------------------- 
ident 844121161
version 8
--------------------------------------- 
skinwidth 320
skinheight 200
--------------------------------------- 
framesize 1264
--------------------------------------- 
num_skins 1
num_vertices 306
num_st 362
num_tris 536
num_glcmds 2729
num_frames 198
--------------------------------------- 
offset_skins 68
offset_st 132
offset_tris 1580
offset_frames 8012
offset_glcmds 258284
offset_end 269200
--------------------------------------- 

next up... saving a md2 modeldef and then... making modeldefs for md3 files



source so far


Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/*
 * md2.c -- md2 model loader
 * last modification: aug. 14, 2007
 *
 * Copyright (c) 2005-2007 David HENRY
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * gcc -Wall -ansi -lGL -lGLU -lglut md2.c -o md2
 */



/* Vector */
typedef float vec3_t[3];

/* MD2 header */
struct md2_header_t
{
  int ident;
  int version;

  int skinwidth;
  int skinheight;

  int framesize;

  int num_skins;
  int num_vertices;
  int num_st;
  int num_tris;
  int num_glcmds;
  int num_frames;

  int offset_skins;
  int offset_st;
  int offset_tris;
  int offset_frames;
  int offset_glcmds;
  int offset_end;
};

/* Texture name */
struct md2_skin_t
{
  char name[64];
};

/* Texture coords */
struct md2_texCoord_t
{
  short s;
  short t;
};

/* Triangle info */
struct md2_triangle_t
{
  unsigned short vertex[3];
  unsigned short st[3];
};

/* Compressed vertex */
struct md2_vertex_t
{
  unsigned char v[3];
  unsigned char normalIndex;
};

/* Model frame */
struct md2_frame_t
{
  vec3_t scale;
  vec3_t translate;
  char name[16];
  struct md2_vertex_t *verts;
};

/* GL command packet */
struct md2_glcmd_t
{
  float s;
  float t;
  int index;
};

/* MD2 model structure */
struct md2_model_t
{
  struct md2_header_t header;

  struct md2_skin_t *skins;
  struct md2_texCoord_t *texcoords;
  struct md2_triangle_t *triangles;
  struct md2_frame_t *frames;
  int *glcmds;

  //GLuint tex_id;
};

/* Table of precalculated normals */
vec3_t anorms_table[162] = {
#include "anorms.h"
};

/*** An MD2 model ***/
struct md2_model_t md2file;


/**
 * Load an MD2 model from file.
 *
 * Note: MD2 format stores model's data in little-endian ordering.  On
 * big-endian machines, you'll have to perform proper conversions.
 */
int
ReadMD2Model (const char *filename, struct md2_model_t *mdl)
{
  FILE *fp;
  int i;

  fp = fopen (filename, "rb");
  if (!fp)
    {
      fprintf (stderr, "Error: couldn't open \"%s\"!\n", filename);
      return 0;
    }

  /* Read header */
  fread (&mdl->header, 1, sizeof (struct md2_header_t), fp);

  if ((mdl->header.ident != 844121161) ||
      (mdl->header.version != 8))
    {
      /* Error! */
      fprintf (stderr, "Error: bad version or identifier\n");
      fclose (fp);
      return 0;
    }

  /* Memory allocations */
  mdl->skins = (struct md2_skin_t *)
    malloc (sizeof (struct md2_skin_t) * mdl->header.num_skins);
  mdl->texcoords = (struct md2_texCoord_t *)
    malloc (sizeof (struct md2_texCoord_t) * mdl->header.num_st);
  mdl->triangles = (struct md2_triangle_t *)
    malloc (sizeof (struct md2_triangle_t) * mdl->header.num_tris);
  mdl->frames = (struct md2_frame_t *)
    malloc (sizeof (struct md2_frame_t) * mdl->header.num_frames);
  mdl->glcmds = (int *)malloc (sizeof (int) * mdl->header.num_glcmds);

  /* Read model data */
  fseek (fp, mdl->header.offset_skins, SEEK_SET);
  fread (mdl->skins, sizeof (struct md2_skin_t),
    mdl->header.num_skins, fp);

  fseek (fp, mdl->header.offset_st, SEEK_SET);
  fread (mdl->texcoords, sizeof (struct md2_texCoord_t),
    mdl->header.num_st, fp);

  fseek (fp, mdl->header.offset_tris, SEEK_SET);
  fread (mdl->triangles, sizeof (struct md2_triangle_t),
    mdl->header.num_tris, fp);

  fseek (fp, mdl->header.offset_glcmds, SEEK_SET);
  fread (mdl->glcmds, sizeof (int), mdl->header.num_glcmds, fp);

  /* Read frames */
  fseek (fp, mdl->header.offset_frames, SEEK_SET);
  for (i = 0; i < mdl->header.num_frames; ++i)
    {
      /* Memory allocation for vertices of this frame */
      mdl->frames[i].verts = (struct md2_vertex_t *)
   malloc (sizeof (struct md2_vertex_t) * mdl->header.num_vertices);

      /* Read frame data */
      fread (mdl->frames[i].scale, sizeof (vec3_t), 1, fp);
      fread (mdl->frames[i].translate, sizeof (vec3_t), 1, fp);
      fread (mdl->frames[i].name, sizeof (char), 16, fp);

      /* read the names of the frames and their number, index begins at 0 */
      printf("frame name: %s\n", mdl->frames[i].name);
      printf("frame number: %d\n", i);
      /* next.. take name, remove all trailing numbers, add to list of strings, each time the result change, another animation group is present */

      fread (mdl->frames[i].verts, sizeof (struct md2_vertex_t),
        mdl->header.num_vertices, fp);
    }

  fclose (fp);

  /* Read header */
  fread (&mdl->header, 1, sizeof (struct md2_header_t), fp);

  printf("--------------------------------------- \n");
  printf("HEADER MD2 FILE %s\n", filename);
  printf("--------------------------------------- \n");
  printf("ident %d\n", mdl->header.ident);
  printf("version %d\n", mdl->header.version);
  printf("--------------------------------------- \n");
  printf("skinwidth %d\n", mdl->header.skinwidth);
  printf("skinheight %d\n", mdl->header.skinheight);
  printf("--------------------------------------- \n");
  printf("framesize %d\n", mdl->header.framesize);
  printf("--------------------------------------- \n");
  printf("num_skins %d\n", mdl->header.num_skins);
  printf("num_vertices %d\n", mdl->header.num_vertices);
  printf("num_st %d\n", mdl->header.num_st);
  printf("num_tris %d\n", mdl->header.num_tris);
  printf("num_glcmds %d\n", mdl->header.num_glcmds);
  printf("num_frames %d\n", mdl->header.num_frames);
  printf("--------------------------------------- \n");
  printf("offset_skins %d\n", mdl->header.offset_skins);
  printf("offset_st %d\n", mdl->header.offset_st);
  printf("offset_tris %d\n", mdl->header.offset_tris);
  printf("offset_frames %d\n", mdl->header.offset_frames);
  printf("offset_glcmds %d\n", mdl->header.offset_glcmds);
  printf("offset_end %d\n", mdl->header.offset_end);
  printf("--------------------------------------- \n");

  return 1;
}

/**
 * Free resources allocated for the model.
 */
void
FreeModel (struct md2_model_t *mdl)
{
  int i;

  if (mdl->skins)
    {
      free (mdl->skins);
      mdl->skins = NULL;
    }

  if (mdl->texcoords)
    {
      free (mdl->texcoords);
      mdl->texcoords = NULL;
    }

  if (mdl->triangles)
    {
      free (mdl->triangles);
      mdl->triangles = NULL;
    }

  if (mdl->glcmds)
    {
      free (mdl->glcmds);
      mdl->glcmds = NULL;
    }

  if (mdl->frames)
    {
      for (i = 0; i < mdl->header.num_frames; ++i)
   {
     free (mdl->frames[i].verts);
     mdl->frames[i].verts = NULL;
   }

      free (mdl->frames);
      mdl->frames = NULL;
    }
}


/**
 * Calculate the current frame in animation beginning at frame
 * 'start' and ending at frame 'end', given interpolation percent.
 * interp will be reseted to 0.0 if the next frame is reached.
 */
void
Animate (int start, int end, int *frame, float *interp)
{
  if ((*frame < start) || (*frame > end))
    *frame = start;

  if (*interp >= 1.0f)
    {
      /* Move to next frame */
      *interp = 0.0f;
      (*frame)++;

      if (*frame >= end)
   *frame = start;
    }
}

void
init (const char *filename)
{

  /* Load MD2 model file */
  if (!ReadMD2Model (filename, &md2file))
    exit (EXIT_FAILURE);


  FreeModel (&md2file);

}

int
main (int argc, char *argv[])
{
  if (argc < 2)
    {
      fprintf (stderr, "usage: %s <filename.md2>\n", argv[0]);
      return 0; //-1;
    }
    else
    {
      init (argv[1]);




    }

//  glutInit (&argc, argv);

//  atexit (cleanup);

//  glutReshapeFunc (reshape);
//  glutDisplayFunc (display);
//  glutKeyboardFunc (keyboard);

 // glutMainLoop ();

  return 0;
}


Re: usefull applications

Posted: Fri Nov 08, 2019 12:18 am
by CBM
Tool is now able to read md2 files and write modeldefs

Next .. Adding md3 support

---------------------

texture is read from MD2 file

path is read from MD2 file (path to texture, usually models\players)

spritenames are generated from animation names (yes yes... non animated MD2 models will not work, but this is not a tool for models without animation)

max number of animation sets is 10 in GZDoom apparently... so it skips some animation sets if there are more than 10, usually there are 16

resulting file is named texture name + .modeldef

jumps are handled as a "seperate" animation set regarding spritenames

spritenames are ... first 3 lettes of the animation set name plus a number

(numbered in packs of 10, usually long animations such as stand will be up to 40 frames.. ie... walk0-3 A-J)



If the numbering increases by more than 2 then I interpret that as a jump, so a jump from walk109 to walk201 would be detected



if the input file is named tris.md2 then the tool assumes there is a weapon.md2 with a weapon.pcx texture as well



example output could be

wal0 A 0 "walk01"

for tris.md2 and

wal0 A 1 "walk01"

for weapon.md2



ie. spritename spriteindex modelindex framename


only problem is if 2 or more animations have the same 3 letters in the name of the animation set.. ie... crwalk and crwobble would both begin with crw


I will post more details later today