mirror of
https://github.com/shawns-valve/halflife.git
synced 2024-11-24 21:21:15 +00:00
650 lines
16 KiB
C
650 lines
16 KiB
C
/***
|
|
*
|
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
|
*
|
|
* This product contains software technology licensed from Id
|
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
****/
|
|
|
|
//
|
|
// write.c: writes a studio .mdl file
|
|
//
|
|
|
|
|
|
|
|
#pragma warning( disable : 4244 )
|
|
#pragma warning( disable : 4237 )
|
|
#pragma warning( disable : 4305 )
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "archtypes.h"
|
|
#include "cmdlib.h"
|
|
#include "lbmlib.h"
|
|
#include "scriplib.h"
|
|
#include "mathlib.h"
|
|
#include "..\..\engine\studio.h"
|
|
#include "studiomdl.h"
|
|
|
|
|
|
int totalframes = 0;
|
|
float totalseconds = 0;
|
|
extern int numcommandnodes;
|
|
|
|
|
|
|
|
/*
|
|
============
|
|
WriteModel
|
|
============
|
|
*/
|
|
byte *pData;
|
|
byte *pStart;
|
|
studiohdr_t *phdr;
|
|
studioseqhdr_t *pseqhdr;
|
|
|
|
#define ALIGN( a ) a = (byte *)((int)((byte *)a + 3) & ~ 3)
|
|
void WriteBoneInfo( )
|
|
{
|
|
int i, j;
|
|
mstudiobone_t *pbone;
|
|
mstudiobonecontroller_t *pbonecontroller;
|
|
mstudioattachment_t *pattachment;
|
|
mstudiobbox_t *pbbox;
|
|
|
|
// save bone info
|
|
pbone = (mstudiobone_t *)pData;
|
|
phdr->numbones = numbones;
|
|
phdr->boneindex = (pData - pStart);
|
|
|
|
for (i = 0; i < numbones; i++)
|
|
{
|
|
strcpy( pbone[i].name, bonetable[i].name );
|
|
pbone[i].parent = bonetable[i].parent;
|
|
pbone[i].flags = bonetable[i].flags;
|
|
pbone[i].value[0] = bonetable[i].pos[0];
|
|
pbone[i].value[1] = bonetable[i].pos[1];
|
|
pbone[i].value[2] = bonetable[i].pos[2];
|
|
pbone[i].value[3] = bonetable[i].rot[0];
|
|
pbone[i].value[4] = bonetable[i].rot[1];
|
|
pbone[i].value[5] = bonetable[i].rot[2];
|
|
pbone[i].scale[0] = bonetable[i].posscale[0];
|
|
pbone[i].scale[1] = bonetable[i].posscale[1];
|
|
pbone[i].scale[2] = bonetable[i].posscale[2];
|
|
pbone[i].scale[3] = bonetable[i].rotscale[0];
|
|
pbone[i].scale[4] = bonetable[i].rotscale[1];
|
|
pbone[i].scale[5] = bonetable[i].rotscale[2];
|
|
}
|
|
pData += numbones * sizeof( mstudiobone_t );
|
|
ALIGN( pData );
|
|
|
|
// map bonecontroller to bones
|
|
for (i = 0; i < numbones; i++) {
|
|
for (j = 0; j < 6; j++) {
|
|
pbone[i].bonecontroller[j] = -1;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < numbonecontrollers; i++) {
|
|
j = bonecontroller[i].bone;
|
|
switch( bonecontroller[i].type & STUDIO_TYPES )
|
|
{
|
|
case STUDIO_X:
|
|
pbone[j].bonecontroller[0] = i;
|
|
break;
|
|
case STUDIO_Y:
|
|
pbone[j].bonecontroller[1] = i;
|
|
break;
|
|
case STUDIO_Z:
|
|
pbone[j].bonecontroller[2] = i;
|
|
break;
|
|
case STUDIO_XR:
|
|
pbone[j].bonecontroller[3] = i;
|
|
break;
|
|
case STUDIO_YR:
|
|
pbone[j].bonecontroller[4] = i;
|
|
break;
|
|
case STUDIO_ZR:
|
|
pbone[j].bonecontroller[5] = i;
|
|
break;
|
|
default:
|
|
printf("unknown bonecontroller type\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
// save bonecontroller info
|
|
pbonecontroller = (mstudiobonecontroller_t *)pData;
|
|
phdr->numbonecontrollers = numbonecontrollers;
|
|
phdr->bonecontrollerindex = (pData - pStart);
|
|
|
|
for (i = 0; i < numbonecontrollers; i++) {
|
|
pbonecontroller[i].bone = bonecontroller[i].bone;
|
|
pbonecontroller[i].index = bonecontroller[i].index;
|
|
pbonecontroller[i].type = bonecontroller[i].type;
|
|
pbonecontroller[i].start = bonecontroller[i].start;
|
|
pbonecontroller[i].end = bonecontroller[i].end;
|
|
}
|
|
pData += numbonecontrollers * sizeof( mstudiobonecontroller_t );
|
|
ALIGN( pData );
|
|
|
|
// save attachment info
|
|
pattachment = (mstudioattachment_t *)pData;
|
|
phdr->numattachments = numattachments;
|
|
phdr->attachmentindex = (pData - pStart);
|
|
|
|
for (i = 0; i < numattachments; i++) {
|
|
pattachment[i].bone = attachment[i].bone;
|
|
VectorCopy( attachment[i].org, pattachment[i].org );
|
|
}
|
|
pData += numattachments * sizeof( mstudioattachment_t );
|
|
ALIGN( pData );
|
|
|
|
|
|
// save bbox info
|
|
pbbox = (mstudiobbox_t *)pData;
|
|
phdr->numhitboxes = numhitboxes;
|
|
phdr->hitboxindex = (pData - pStart);
|
|
|
|
for (i = 0; i < numhitboxes; i++) {
|
|
pbbox[i].bone = hitbox[i].bone;
|
|
pbbox[i].group = hitbox[i].group;
|
|
VectorCopy( hitbox[i].bmin, pbbox[i].bbmin );
|
|
VectorCopy( hitbox[i].bmax, pbbox[i].bbmax );
|
|
}
|
|
pData += numhitboxes * sizeof( mstudiobbox_t );
|
|
ALIGN( pData );
|
|
|
|
}
|
|
|
|
|
|
void WriteSequenceInfo( )
|
|
{
|
|
int i, j;
|
|
|
|
mstudioseqgroup_t *pseqgroup;
|
|
mstudioseqdesc_t *pseqdesc;
|
|
mstudioseqdesc_t *pbaseseqdesc;
|
|
mstudioevent_t *pevent;
|
|
mstudiopivot_t *ppivot;
|
|
byte *ptransition;
|
|
|
|
// save sequence info
|
|
pseqdesc = (mstudioseqdesc_t *)pData;
|
|
pbaseseqdesc = pseqdesc;
|
|
phdr->numseq = numseq;
|
|
phdr->seqindex = (pData - pStart);
|
|
pData += numseq * sizeof( mstudioseqdesc_t );
|
|
|
|
for (i = 0; i < numseq; i++, pseqdesc++)
|
|
{
|
|
strcpy( pseqdesc->label, sequence[i].name );
|
|
pseqdesc->numframes = sequence[i].numframes;
|
|
pseqdesc->fps = sequence[i].fps;
|
|
pseqdesc->flags = sequence[i].flags;
|
|
|
|
pseqdesc->numblends = sequence[i].numblends;
|
|
|
|
pseqdesc->blendtype[0] = sequence[i].blendtype[0];
|
|
pseqdesc->blendtype[1] = sequence[i].blendtype[1];
|
|
pseqdesc->blendstart[0] = sequence[i].blendstart[0];
|
|
pseqdesc->blendend[0] = sequence[i].blendend[0];
|
|
pseqdesc->blendstart[1] = sequence[i].blendstart[1];
|
|
pseqdesc->blendend[1] = sequence[i].blendend[1];
|
|
|
|
pseqdesc->motiontype = sequence[i].motiontype;
|
|
pseqdesc->motionbone = 0; // sequence[i].motionbone;
|
|
VectorCopy( sequence[i].linearmovement, pseqdesc->linearmovement );
|
|
|
|
pseqdesc->seqgroup = sequence[i].seqgroup;
|
|
|
|
pseqdesc->animindex = sequence[i].animindex;
|
|
|
|
pseqdesc->activity = sequence[i].activity;
|
|
pseqdesc->actweight = sequence[i].actweight;
|
|
|
|
VectorCopy( sequence[i].bmin, pseqdesc->bbmin );
|
|
VectorCopy( sequence[i].bmax, pseqdesc->bbmax );
|
|
|
|
pseqdesc->entrynode = sequence[i].entrynode;
|
|
pseqdesc->exitnode = sequence[i].exitnode;
|
|
pseqdesc->nodeflags = sequence[i].nodeflags;
|
|
|
|
totalframes += sequence[i].numframes;
|
|
totalseconds += sequence[i].numframes / sequence[i].fps;
|
|
|
|
// save events
|
|
pevent = (mstudioevent_t *)pData;
|
|
pseqdesc->numevents = sequence[i].numevents;
|
|
pseqdesc->eventindex = (pData - pStart);
|
|
pData += pseqdesc->numevents * sizeof( mstudioevent_t );
|
|
for (j = 0; j < sequence[i].numevents; j++)
|
|
{
|
|
pevent[j].frame = sequence[i].event[j].frame - sequence[i].frameoffset;
|
|
pevent[j].event = sequence[i].event[j].event;
|
|
memcpy( pevent[j].options, sequence[i].event[j].options, sizeof( pevent[j].options ) );
|
|
}
|
|
ALIGN( pData );
|
|
|
|
// save pivots
|
|
ppivot = (mstudiopivot_t *)pData;
|
|
pseqdesc->numpivots = sequence[i].numpivots;
|
|
pseqdesc->pivotindex = (pData - pStart);
|
|
pData += pseqdesc->numpivots * sizeof( mstudiopivot_t );
|
|
for (j = 0; j < sequence[i].numpivots; j++)
|
|
{
|
|
VectorCopy( sequence[i].pivot[j].org, ppivot[j].org );
|
|
ppivot[j].start = sequence[i].pivot[j].start - sequence[i].frameoffset;
|
|
ppivot[j].end = sequence[i].pivot[j].end - sequence[i].frameoffset;
|
|
}
|
|
ALIGN( pData );
|
|
}
|
|
|
|
// save sequence group info
|
|
pseqgroup = (mstudioseqgroup_t *)pData;
|
|
phdr->numseqgroups = numseqgroups;
|
|
phdr->seqgroupindex = (pData - pStart);
|
|
pData += phdr->numseqgroups * sizeof( mstudioseqgroup_t );
|
|
ALIGN( pData );
|
|
|
|
for (i = 0; i < numseqgroups; i++)
|
|
{
|
|
strcpy( pseqgroup[i].label, sequencegroup[i].label );
|
|
strcpy( pseqgroup[i].name, sequencegroup[i].name );
|
|
}
|
|
|
|
// save transition graph
|
|
ptransition = (byte *)pData;
|
|
phdr->numtransitions = numxnodes;
|
|
phdr->transitionindex = (pData - pStart);
|
|
pData += numxnodes * numxnodes * sizeof( byte );
|
|
ALIGN( pData );
|
|
for (i = 0; i < numxnodes; i++)
|
|
{
|
|
for (j = 0; j < numxnodes; j++)
|
|
{
|
|
*ptransition++ = xnode[i][j];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
byte *WriteAnimations( byte *pData, byte *pStart, int group )
|
|
{
|
|
int i, j, k;
|
|
int q, n;
|
|
|
|
mstudioanim_t *panim;
|
|
mstudioanimvalue_t *panimvalue;
|
|
|
|
// hack for seqgroup 0
|
|
// pseqgroup->data = (pData - pStart);
|
|
|
|
for (i = 0; i < numseq; i++)
|
|
{
|
|
if (sequence[i].seqgroup == group)
|
|
{
|
|
// save animations
|
|
panim = (mstudioanim_t *)pData;
|
|
sequence[i].animindex = (pData - pStart);
|
|
pData += sequence[i].numblends * numbones * sizeof( mstudioanim_t );
|
|
ALIGN( pData );
|
|
|
|
panimvalue = (mstudioanimvalue_t *)pData;
|
|
for (q = 0; q < sequence[i].numblends; q++)
|
|
{
|
|
// save animation value info
|
|
for (j = 0; j < numbones; j++)
|
|
{
|
|
for (k = 0; k < 6; k++)
|
|
{
|
|
if (sequence[i].panim[q]->numanim[j][k] == 0)
|
|
{
|
|
panim->offset[k] = 0;
|
|
}
|
|
else
|
|
{
|
|
panim->offset[k] = ((byte *)panimvalue - (byte *)panim);
|
|
for (n = 0; n < sequence[i].panim[q]->numanim[j][k]; n++)
|
|
{
|
|
panimvalue->value = sequence[i].panim[q]->anim[j][k][n].value;
|
|
panimvalue++;
|
|
}
|
|
}
|
|
}
|
|
if (((byte *)panimvalue - (byte *)panim) > 65535)
|
|
Error("sequence \"%s\" is greate than 64K\n", sequence[i].name );
|
|
panim++;
|
|
}
|
|
}
|
|
|
|
// printf("raw bone data %d : %s\n", (byte *)panimvalue - pData, sequence[i].name);
|
|
pData = (byte *)panimvalue;
|
|
ALIGN( pData );
|
|
}
|
|
}
|
|
return pData;
|
|
}
|
|
|
|
void WriteTextures( )
|
|
{
|
|
int i, j;
|
|
mstudiotexture_t *ptexture;
|
|
short *pref;
|
|
|
|
// save bone info
|
|
ptexture = (mstudiotexture_t *)pData;
|
|
phdr->numtextures = numtextures;
|
|
phdr->textureindex = (pData - pStart);
|
|
pData += numtextures * sizeof( mstudiotexture_t );
|
|
ALIGN( pData );
|
|
|
|
phdr->skinindex = (pData - pStart);
|
|
phdr->numskinref = numskinref;
|
|
phdr->numskinfamilies = numskinfamilies;
|
|
pref = (short *)pData;
|
|
|
|
for (i = 0; i < phdr->numskinfamilies; i++)
|
|
{
|
|
for (j = 0; j < phdr->numskinref; j++)
|
|
{
|
|
*pref = skinref[i][j];
|
|
pref++;
|
|
}
|
|
}
|
|
pData = (byte *)pref;
|
|
ALIGN( pData );
|
|
|
|
phdr->texturedataindex = (pData - pStart); // must be the end of the file!
|
|
|
|
for (i = 0; i < numtextures; i++) {
|
|
strcpy( ptexture[i].name, texture[i].name );
|
|
ptexture[i].flags = texture[i].flags;
|
|
ptexture[i].width = texture[i].skinwidth;
|
|
ptexture[i].height = texture[i].skinheight;
|
|
ptexture[i].index = (pData - pStart);
|
|
memcpy( pData, texture[i].pdata, texture[i].size );
|
|
pData += texture[i].size;
|
|
}
|
|
ALIGN( pData );
|
|
}
|
|
|
|
|
|
void WriteModel( )
|
|
{
|
|
int i, j, k;
|
|
|
|
mstudiobodyparts_t *pbodypart;
|
|
mstudiomodel_t *pmodel;
|
|
// vec3_t *bbox;
|
|
byte *pbone;
|
|
vec3_t *pvert;
|
|
vec3_t *pnorm;
|
|
mstudiomesh_t *pmesh;
|
|
s_trianglevert_t *psrctri;
|
|
int cur;
|
|
int total_tris = 0;
|
|
int total_strips = 0;
|
|
|
|
pbodypart = (mstudiobodyparts_t *)pData;
|
|
phdr->numbodyparts = numbodyparts;
|
|
phdr->bodypartindex = (pData - pStart);
|
|
pData += numbodyparts * sizeof( mstudiobodyparts_t );
|
|
|
|
pmodel = (mstudiomodel_t *)pData;
|
|
pData += nummodels * sizeof( mstudiomodel_t );
|
|
|
|
for (i = 0, j = 0; i < numbodyparts; i++)
|
|
{
|
|
strcpy( pbodypart[i].name, bodypart[i].name );
|
|
pbodypart[i].nummodels = bodypart[i].nummodels;
|
|
pbodypart[i].base = bodypart[i].base;
|
|
pbodypart[i].modelindex = ((byte *)&pmodel[j]) - pStart;
|
|
j += bodypart[i].nummodels;
|
|
}
|
|
ALIGN( pData );
|
|
|
|
cur = (int)pData;
|
|
for (i = 0; i < nummodels; i++)
|
|
{
|
|
int normmap[MAXSTUDIOVERTS];
|
|
int normimap[MAXSTUDIOVERTS];
|
|
int n = 0;
|
|
|
|
strcpy( pmodel[i].name, model[i]->name );
|
|
|
|
// save bbox info
|
|
|
|
// remap normals to be sorted by skin reference
|
|
for (j = 0; j < model[i]->nummesh; j++)
|
|
{
|
|
for (k = 0; k < model[i]->numnorms; k++)
|
|
{
|
|
if (model[i]->normal[k].skinref == model[i]->pmesh[j]->skinref)
|
|
{
|
|
normmap[k] = n;
|
|
normimap[n] = k;
|
|
n++;
|
|
model[i]->pmesh[j]->numnorms++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// save vertice bones
|
|
pbone = pData;
|
|
pmodel[i].numverts = model[i]->numverts;
|
|
pmodel[i].vertinfoindex = (pData - pStart);
|
|
for (j = 0; j < pmodel[i].numverts; j++)
|
|
{
|
|
*pbone++ = model[i]->vert[j].bone;
|
|
}
|
|
ALIGN( pbone );
|
|
|
|
// save normal bones
|
|
pmodel[i].numnorms = model[i]->numnorms;
|
|
pmodel[i].norminfoindex = ((byte *)pbone - pStart);
|
|
for (j = 0; j < pmodel[i].numnorms; j++)
|
|
{
|
|
*pbone++ = model[i]->normal[normimap[j]].bone;
|
|
}
|
|
ALIGN( pbone );
|
|
|
|
pData = pbone;
|
|
|
|
// save group info
|
|
pvert = (vec3_t *)pData;
|
|
pData += model[i]->numverts * sizeof( vec3_t );
|
|
pmodel[i].vertindex = ((byte *)pvert - pStart);
|
|
ALIGN( pData );
|
|
|
|
pnorm = (vec3_t *)pData;
|
|
pData += model[i]->numnorms * sizeof( vec3_t );
|
|
pmodel[i].normindex = ((byte *)pnorm - pStart);
|
|
ALIGN( pData );
|
|
|
|
for (j = 0; j < model[i]->numverts; j++)
|
|
{
|
|
VectorCopy( model[i]->vert[j].org, pvert[j] );
|
|
}
|
|
|
|
for (j = 0; j < model[i]->numnorms; j++)
|
|
{
|
|
VectorCopy( model[i]->normal[normimap[j]].org, pnorm[j] );
|
|
}
|
|
printf("vertices %6d bytes (%d vertices, %d normals)\n", pData - cur, model[i]->numverts, model[i]->numnorms);
|
|
cur = (int)pData;
|
|
|
|
// save mesh info
|
|
pmesh = (mstudiomesh_t *)pData;
|
|
pmodel[i].nummesh = model[i]->nummesh;
|
|
pmodel[i].meshindex = (pData - pStart);
|
|
pData += pmodel[i].nummesh * sizeof( mstudiomesh_t );
|
|
ALIGN( pData );
|
|
|
|
total_tris = 0;
|
|
total_strips = 0;
|
|
for (j = 0; j < model[i]->nummesh; j++)
|
|
{
|
|
int numCmdBytes;
|
|
byte *pCmdSrc;
|
|
|
|
pmesh[j].numtris = model[i]->pmesh[j]->numtris;
|
|
pmesh[j].skinref = model[i]->pmesh[j]->skinref;
|
|
pmesh[j].numnorms = model[i]->pmesh[j]->numnorms;
|
|
|
|
psrctri = (s_trianglevert_t *)(model[i]->pmesh[j]->triangle);
|
|
for (k = 0; k < pmesh[j].numtris * 3; k++)
|
|
{
|
|
psrctri->normindex = normmap[psrctri->normindex];
|
|
psrctri++;
|
|
}
|
|
|
|
numCmdBytes = BuildTris( model[i]->pmesh[j]->triangle, model[i]->pmesh[j], &pCmdSrc );
|
|
|
|
pmesh[j].triindex = (pData - pStart);
|
|
memcpy( pData, pCmdSrc, numCmdBytes );
|
|
pData += numCmdBytes;
|
|
ALIGN( pData );
|
|
total_tris += pmesh[j].numtris;
|
|
total_strips += numcommandnodes;
|
|
}
|
|
printf("mesh %6d bytes (%d tris, %d strips)\n", pData - cur, total_tris, total_strips);
|
|
cur = (int)pData;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#define FILEBUFFER ( 16 * 1024 * 1024)
|
|
|
|
|
|
void WriteFile (void)
|
|
{
|
|
FILE *modelouthandle;
|
|
int total = 0;
|
|
int i;
|
|
|
|
pStart = kalloc( 1, FILEBUFFER );
|
|
|
|
StripExtension (outname);
|
|
|
|
for (i = 1; i < numseqgroups; i++)
|
|
{
|
|
// write the non-default sequence group data to separate files
|
|
char groupname[128], localname[128];
|
|
|
|
sprintf( groupname, "%s%02d.mdl", outname, i );
|
|
|
|
printf ("writing %s:\n", groupname);
|
|
modelouthandle = SafeOpenWrite (groupname);
|
|
|
|
pseqhdr = (studioseqhdr_t *)pStart;
|
|
pseqhdr->id = IDSTUDIOSEQHEADER;
|
|
pseqhdr->version = STUDIO_VERSION;
|
|
|
|
pData = pStart + sizeof( studioseqhdr_t );
|
|
|
|
pData = WriteAnimations( pData, pStart, i );
|
|
|
|
ExtractFileBase( groupname, localname );
|
|
sprintf( sequencegroup[i].name, "models\\%s.mdl", localname );
|
|
strcpy( pseqhdr->name, sequencegroup[i].name );
|
|
pseqhdr->length = pData - pStart;
|
|
|
|
printf("total %6d\n", pseqhdr->length );
|
|
|
|
SafeWrite( modelouthandle, pStart, pseqhdr->length );
|
|
|
|
fclose (modelouthandle);
|
|
memset( pStart, 0, pseqhdr->length );
|
|
}
|
|
|
|
if (split_textures)
|
|
{
|
|
// write textures out to a separate file
|
|
char texname[128];
|
|
|
|
sprintf( texname, "%sT.mdl", outname );
|
|
|
|
printf ("writing %s:\n", texname);
|
|
modelouthandle = SafeOpenWrite (texname);
|
|
|
|
phdr = (studiohdr_t *)pStart;
|
|
phdr->id = IDSTUDIOHEADER;
|
|
phdr->version = STUDIO_VERSION;
|
|
|
|
pData = (byte *)phdr + sizeof( studiohdr_t );
|
|
|
|
WriteTextures( );
|
|
|
|
phdr->length = pData - pStart;
|
|
printf("textures %6d bytes\n", phdr->length );
|
|
|
|
SafeWrite( modelouthandle, pStart, phdr->length );
|
|
|
|
fclose (modelouthandle);
|
|
memset( pStart, 0, phdr->length );
|
|
pData = pStart;
|
|
}
|
|
|
|
//
|
|
// write the model output file
|
|
//
|
|
strcat (outname, ".mdl");
|
|
|
|
printf ("---------------------\n");
|
|
printf ("writing %s:\n", outname);
|
|
modelouthandle = SafeOpenWrite (outname);
|
|
|
|
phdr = (studiohdr_t *)pStart;
|
|
|
|
phdr->id = IDSTUDIOHEADER;
|
|
phdr->version = STUDIO_VERSION;
|
|
strcpy( phdr->name, outname );
|
|
VectorCopy( eyeposition, phdr->eyeposition );
|
|
VectorCopy( bbox[0], phdr->min );
|
|
VectorCopy( bbox[1], phdr->max );
|
|
VectorCopy( cbox[0], phdr->bbmin );
|
|
VectorCopy( cbox[1], phdr->bbmax );
|
|
|
|
phdr->flags = gflags;
|
|
|
|
pData = (byte *)phdr + sizeof( studiohdr_t );
|
|
|
|
WriteBoneInfo( );
|
|
printf("bones %6d bytes (%d)\n", pData - pStart - total, numbones );
|
|
total = pData - pStart;
|
|
|
|
pData = WriteAnimations( pData, pStart, 0 );
|
|
|
|
WriteSequenceInfo( );
|
|
printf("sequences %6d bytes (%d frames) [%d:%02d]\n", pData - pStart - total, totalframes, (int)totalseconds / 60, (int)totalseconds % 60 );
|
|
total = pData - pStart;
|
|
|
|
WriteModel( );
|
|
printf("models %6d bytes\n", pData - pStart - total );
|
|
total = pData - pStart;
|
|
|
|
if (!split_textures)
|
|
{
|
|
WriteTextures( );
|
|
printf("textures %6d bytes\n", pData - pStart - total );
|
|
}
|
|
|
|
phdr->length = pData - pStart;
|
|
|
|
printf("total %6d\n", phdr->length );
|
|
|
|
SafeWrite( modelouthandle, pStart, phdr->length );
|
|
|
|
fclose (modelouthandle);
|
|
}
|
|
|
|
|
|
|