Pages: [1] 2
  Print  
Author Topic: New model format  (Read 33787 times)
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« on: August 19, 2015, 10:30:30 AM »

I've been working on a model format based on MDR/MD4 labeled MDL ( so creative ) and its nearly completed. I'm just having trouble the the exporter for blender. The exporter is pretty much done, there is just things here and there that aren't working. The model loads but does not show up at all. At this point I really can't figure much else out. If anyone is able to help out I would appreciate it. OA could use a model format that has a working exporter / more direct export pipeline. The exporter is also based upon my modified MD3 exporter btw.

FINAL EDIT FOR NOW: removed attachments for now.
« Last Edit: August 19, 2015, 07:26:41 PM by revanic » Logged
Suicizer
Member
Member
*

Cakes 2
Posts: 402


WWW
« Reply #1 on: August 19, 2015, 04:07:46 PM »

Sounds seriously awesome and perhaps even worth the effort to start making something for OA in modeling.
Logged

I'm good at everything but can't do anything...
fromhell
Administrator
GET A LIFE!
**********

Cakes 35
Posts: 14520



WWW
« Reply #2 on: August 19, 2015, 05:49:53 PM »

I strongly advise against the MDL extension name.  That's used by Quake, Half-Life/HL2, and Serious Sam.

Maybe MDK? Smiley
Logged

asking when OA3 will be done won't get OA3 done.
Progress of OA3 currently occurs behind closed doors alone

I do not provide technical support either.

new code development on github
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #3 on: August 19, 2015, 07:25:57 PM »

I was aware of the MDL extension conflicts, but usually have a hard time figuring out what sounds good. MDK seems okay, but what would the K stand for? I thought of SMF(Skeletal model format) and SSM(Simple Skeletal Model/Mesh(fitting for these kinds of models))

In other news, I have figured out a had a couple tiny loading mistakes and some writing mistakes and have fixed them. Right now tags seem to have incorrect offsets written, but I shall figure this out.
Logged
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #4 on: August 20, 2015, 04:26:29 PM »

Big milestone today. The format is ~80 percent functional. The model will load, the model will draw (sideways ...), and just about everything but animation works. I also need to change the bone matrices on export so they match up with Quake 3's XYZ.

A cool thing: Instead of bone tags, each bone has an extra info assigned to it that gives it a name. With this format you can just name a bone as the tag you want and it'll work. On the flip side, you can use any bone that exists in a model as a tag in code.

 I'll probably also include an Auto Rotate option so that we don't have to rotate the entire model ourselves before exporting if that sounds good.

Update: This is severely annoying me. Everything is done but the bone matrices and animation are the last things left that I just cant seem to get to work., Namely converting the bone matrices to quake's matrix... Lods are also not done yet. If I can't figure it out in a few weeks I may just dump whatever works as is here and let someone else finish it. Probably doesn't help that I'm not much of a coder or python user...
« Last Edit: August 21, 2015, 07:39:21 PM by revanic » Logged
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #5 on: August 23, 2015, 08:31:39 PM »

Woo, Triple posting!

Okay, since I finally got this 99% working, I'm going to give out the file format and base loading code now. The format extension is now MSK ( in-between what I wanted and what Lei suggested )

Blender Export Features( when it is released, which I am guessing sometime next week or sooner):
- Fix front axis option, on by default ( automatically rotates the model so you don't have too )
- no more auto scaling, but manual scaling left in
- retains the xyz offset options
- hopefully improved bounding boxes + radius code
Note: I will repeat this later, but the very first frame of the model when exporting MUST be a root/base frame, since each frame represents a transformation between the base frame and the real frame that is being exported
- Lods are handled PER-SCENE(I hope this is okay, it was easier to iterate through scenes than to check each obj's layers all the time. Plus, it technically means you get unlimited lods). No re-naming is necessary if you do a copy of the scene ( even if there is a .001 .002 etc for your objects, it is ignored )

MSK Features:
-IQM and RTCW inspired bone matrix, simplified into angles, scale, and translation( since using that to export from blender made the code simpler and let me understand what I was actually doing.) Angles are converted from radians to degrees on export, and the bone data is converted into a 3x4 matrix at runtime.
- Bone info, currently just contains a name for each bone index so we can go through the bones and find which one matches the name of a needed tag
- Working Bone References, AKA: Stop! Don't re-interpolate 56 bones for a surface that only uses 1 of them!
- True XYZ vertex origins, both MDR and MDS(... and mdm...) formats used vertex offsets found in the weights struct for deformation(basically vert position relative to the bone, FOR EACH WEIGHT.). MSK instead stores the absolute positions of vertices(which also makes the format slightly smaller)
- LODs
- Up to 8 bone weights!

File Format( either add it to its own file, or append qfiles.h after MDR ):
Code:
/*
==============================================================================

.MSK Skeletal Model Format - by Revanic

==============================================================================
*/

#define MSK_IDENT (('2'<<24)+('K'<<16)+('S'<<8)+'M')
#define MSK_VERSION 2
#define MSK_MAX_BONES 256
#define MSK_MAX_BONEWEIGHTS 8

typedef struct {
int boneIndex;
float          boneWeight;
} mskWeight_t;

typedef struct {
vec3_t xyz; // true XYZ pos of vertex, instead of weight offsets
vec3_t normal;
int numWeights;
mskWeight_t weights[MSK_MAX_BONEWEIGHTS];
} mskVertex_t;

typedef struct {
vec2_t texCoords;
} mskTexCoord_t;

typedef struct {
int indexes[3];
} mskTriangle_t;

typedef struct {
int ident;

char name[MAX_QPATH]; // polyset name
char shader[MAX_QPATH];
int shaderIndex; // for in-game use

int ofsHeader; // subtract this to get header

int numVerts;
int numTriangles;
int numBoneRefs;
int ofsVerts;
int ofsUV;
int ofsTriangles;
int ofsBoneRefs;

int ofsEnd; // next surface follows
} mskSurface_t;

typedef struct {
float angles[3];
vec3_t scale;
vec3_t translation;
} mskBoneMat_t; // iqm + rtcw mds inspired

typedef struct {
char name[32];
} mskBoneInfo_t;

typedef struct {
vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame
vec3_t localOrigin; // midpoint of bounds, used for sphere cull
float radius; // dist from localOrigin to corner
char name[16];
mskBoneMat_t bones[1]; // [numBones], bone mats
} mskFrame_t;

typedef struct {
int numSurfaces;
int ofsSurfaces; // first surface, others follow
int ofsEnd; // next lod follows
} mskLOD_t;

typedef struct {
int ident;
int version;

char name[MAX_QPATH]; // model name

// frames and bones are shared by all levels of detail
int numFrames;
int numBones;
int numLODs;

int ofsFrames;
int ofsBones;
int ofsLODs;

int ofsEnd;
} mskHeader_t;

Loading Code:
Code:
/*
=================
R_LoadMSK - Skeletal MSK format
=================
*/
static qboolean R_LoadMSK( model_t *mod, void *buffer, int filesize, const char *mod_name ) {
int i, j, k, lodindex;
mskHeader_t *pinmodel, *mdl;
    mskFrame_t *frame;
mskLOD_t *lod;
mskSurface_t *surf;
mskTriangle_t *tri;
mskVertex_t *v;
mskTexCoord_t *uv;
mskBoneInfo_t *bone;
int *boneRef;
int version;
int size;
shader_t *sh;
int frameSize;

pinmodel = (mskHeader_t *)buffer;

version = LittleLong (pinmodel->version);
if (version != MSK_VERSION) {
ri.Printf( PRINT_WARNING, "R_LoadMSK: %s has wrong version (%i should be %i)\n",
mod_name, version, MSK_VERSION);
return qfalse;
}

mod->type = MOD_MSK;

size = LittleLong(pinmodel->ofsEnd);
if(size > filesize)
{
ri.Printf(PRINT_WARNING, "R_LoadMSK: Header of %s is broken. Wrong filesize declared!\n", mod_name);
return qfalse;
}

mod->dataSize += size;
mod->modelData = mdl = ri.Hunk_Alloc( size, h_low );

Com_Memcpy( mdl, buffer, LittleLong(pinmodel->ofsEnd) );

    LL(mdl->ident);
    LL(mdl->version);
    LL(mdl->numFrames);
    LL(mdl->numBones);
    LL(mdl->numLODs);
    LL(mdl->ofsFrames);
    LL(mdl->ofsLODs);
    LL(mdl->ofsEnd);

if ( mdl->numFrames < 1 ) {
ri.Printf( PRINT_WARNING, "R_LoadMSK: %s has no frames\n", mod_name );
return qfalse;
}

if( mdl->numLODs < 1){
ri.Printf( PRINT_WARNING, "R_LoadMSK: %s has no LODs\n", mod_name );
return qfalse;
}
    
// swap all the frames
frameSize = (int)( &((mskFrame_t *)0)->bones[ mdl->numBones ] );
    for ( i = 0 ; i < mdl->numFrames ; i++, frame++) {
   frame = (mskFrame_t *) ( (byte *)mdl + mdl->ofsFrames + i * frameSize );
     frame->radius = LittleFloat( frame->radius );
        for ( j = 0 ; j < 3 ; j++ ) {
            frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
            frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
    frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
        }
for ( j = 0 ; j < mdl->numBones * sizeof(mskBoneMat_t) / sizeof(float) ; j++ ) {
( (float *)frame->bones )[j] = LittleFloat( ( (float *)frame->bones )[j] );
}
}

// swap all the bone infos
bone = (mskBoneInfo_t *) ( (byte *)mdl + mdl->ofsBones );
for ( i = 0; i < mdl->numBones; i++, bone++ ){
// lowercase the bone name so tag compares are faster
Q_strlwr( bone->name );
}

// swap all the LOD's
lod = (mskLOD_t *) ( (byte *)mdl + mdl->ofsLODs );
if( !lod ){
ri.Printf( PRINT_WARNING, "R_LoadMSK: %s has broken LODs\n", mod_name );
return qfalse;
}
for ( lodindex = 0 ; lodindex < mdl->numLODs ; lodindex++ ) {
// swap all the surfaces
surf = (mskSurface_t *) ( (byte *)lod + lod->ofsSurfaces );
for ( i = 0 ; i < lod->numSurfaces ; i++) {
LL(surf->ident);
LL(surf->ofsHeader); // don't swap header offset
LL(surf->numTriangles);
LL(surf->ofsTriangles);
LL(surf->numVerts);
LL(surf->ofsVerts);
LL(surf->ofsUV);
LL(surf->numBoneRefs);
LL(surf->ofsBoneRefs);
LL(surf->ofsEnd);


if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
ri.Error (ERR_DROP, "R_LoadMSK: %s has more than %i verts on a surface (%i)",
mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
}
if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
ri.Error (ERR_DROP, "R_LoadMSK: %s has more than %i triangles on a surface (%i)",
mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
}

// change to surface identifier
surf->ident = SF_MSK;

// lowercase the surface name so skin compares are faster
Q_strlwr( surf->name );

// register the shaders
sh = R_FindShader(surf->shader, LIGHTMAP_NONE, qtrue);
if ( sh->defaultShader ) {
surf->shaderIndex = 0;
} else {
surf->shaderIndex = sh->index;
}

// swap all the vertexes
v = (mskVertex_t *) ( (byte *)surf + surf->ofsVerts);
for ( j = 0 ; j < surf->numVerts ; j++ ) {
v->xyz[0] = LittleFloat( v->xyz[0] );
v->xyz[1] = LittleFloat( v->xyz[1] );
v->xyz[2] = LittleFloat( v->xyz[2] );

v->normal[0] = LittleFloat( v->normal[0] );
v->normal[1] = LittleFloat( v->normal[1] );
v->normal[2] = LittleFloat( v->normal[2] );

v->numWeights = LittleLong( v->numWeights );
if(v->numWeights > MSK_MAX_BONEWEIGHTS){
ri.Printf( PRINT_WARNING, "R_LoadMSK: Vertex %i has more than %i bone weights! Num Weights: %i\n", j, MSK_MAX_BONEWEIGHTS, v->numWeights);
return qfalse;
}

for ( k = 0 ; k < v->numWeights ; k++ ) {
v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex );
v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight );
}

v = (mskVertex_t *)( ( byte * )&v->weights[v->numWeights]);
}

// swap all the texcoords
uv = (mskTexCoord_t *) ( (byte *)surf + surf->ofsUV );
for ( j = 0 ; j < surf->numVerts ; j++, uv++ ) {
uv->texCoords[0] = LittleFloat( uv->texCoords[0] );
uv->texCoords[1] = LittleFloat( uv->texCoords[1] );
}

// swap all the triangles
tri = (mskTriangle_t *) ( (byte *)surf + surf->ofsTriangles );
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
LL(tri->indexes[0]);
LL(tri->indexes[1]);
LL(tri->indexes[2]);
}

// swap all the bone references
boneRef = ( int * )( ( byte *)surf + surf->ofsBoneRefs );
for ( j = 0; j < surf->numBoneRefs; j++, boneRef++ ){
*boneRef = LittleLong( *boneRef );
}

// find the next surface
surf = (mskSurface_t *)( (byte *)surf + surf->ofsEnd );
}

// find the next LOD
lod = (mskLOD_t *)( (byte *)lod + lod->ofsEnd );
}

return qtrue;
}

I'll edit this tomorrow and add drawing code too... I'm going to bed for now.
Edit: Added drawing code as an attachment since its kinda big( only as big as mdr's, but still has multiple functions )
Also, Tags:
Code:
md3Tag_t *R_GetMSKTag( mskHeader_t *mod, int framenum, const char *tagName, md3Tag_t * dest)
{
int i, j, k;
int frameSize;
mskFrame_t *frame;
mskBoneInfo_t *bone;

if ( framenum >= mod->numFrames )
{
// it is possible to have a bad frame while changing models, so don't error
framenum = mod->numFrames - 1;
}

bone = (mskBoneInfo_t *)((byte *)mod + mod->ofsBones);
for ( i = 0; i < mod->numBones; i++, bone++ )
{
if ( !strcmp( bone->name, tagName ) )
{
Q_strncpyz(dest->name, bone->name, sizeof(dest->name));

frameSize = (size_t)( &((mskFrame_t *)0)->bones[ mod->numBones ] );
frame = (mskFrame_t *)((byte *)mod + mod->ofsFrames + framenum * frameSize );

AnglesToAxis(frame->bones[i].angles, dest->axis);
// scale may or may not be needed, ignoring for now.

dest->origin[0] = frame->bones[i].translation[0];
dest->origin[1] = frame->bones[i].translation[1];
dest->origin[2] = frame->bones[i].translation[2];

return dest;
}
}

return NULL;
}
« Last Edit: August 24, 2015, 08:27:47 AM by revanic » Logged
fromhell
Administrator
GET A LIFE!
**********

Cakes 35
Posts: 14520



WWW
« Reply #6 on: August 24, 2015, 05:32:57 PM »

Cool!

I am fine with more scenes as LODs.  I ttypically sort my LODs into different layers to select and export though

However does this mean I have to have a different file dedicated to a part (i..e upper.blend)? I don't want that Sad


Also another thing I wonder about is low-end performance compared to MDR...  8 weights per vertex seems like 5 weights too many.
« Last Edit: August 24, 2015, 06:24:52 PM by fromhell » Logged

asking when OA3 will be done won't get OA3 done.
Progress of OA3 currently occurs behind closed doors alone

I do not provide technical support either.

new code development on github
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #7 on: August 24, 2015, 07:18:34 PM »

No, you will not have to have your head, upper, and lower models in separate blend files. It should export just like an md3 usually does. I may also include a list select option for auto-transforming your mesh + bones to either the origin or so that its lowest point touches quake's floor.
If you think 8 bone weights is too much I can limit it to 4, maybe 3 if you think that's all you'll need.
Logged
fromhell
Administrator
GET A LIFE!
**********

Cakes 35
Posts: 14520



WWW
« Reply #8 on: August 24, 2015, 11:43:19 PM »

I think i'd just need 3 to deal with pelvises and collarbones... or even hair.

which makes me think if this format could get some form of jigglebone support in some fashion
Logged

asking when OA3 will be done won't get OA3 done.
Progress of OA3 currently occurs behind closed doors alone

I do not provide technical support either.

new code development on github
grey matter
Member


Cakes 8
Posts: 381

>9k


« Reply #9 on: August 25, 2015, 05:57:37 AM »

File Format( either add it to its own file, or append qfiles.h after MDR ):
[..]

Loading Code
[..]

I'll edit this tomorrow and add drawing code too... I'm going to bed for now.
Edit: Added drawing code as an attachment since its kinda big( only as big as mdr's, but still has multiple functions )
Also, Tags:
[..]

What's the license of that code? GPLv2+?

IQM and RTCW inspired [..]

Does this use code or technology that might have a different license or patents?
Logged

This space is for rent.
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #10 on: August 25, 2015, 07:05:13 AM »

It is GPL v2, should be compatible with OA's code liscense. It does not use code that is under different licenses, the way the initial bone data is written is inspired of those two formats but not copy-pasted. Their codes are GPL as well anyway. Everything here I am slaving away at whenever I have time to, so that 1: OpenArena gets an easy to use model format that doesn't have a complicated pipeline, and anyone could use it. 2: I get a basis of a completed model format that I wrote myself, to expand it into another format I have planned for a project(one with separate skeleton animation and model data *gasp*).
Logged
Suicizer
Member
Member
*

Cakes 2
Posts: 402


WWW
« Reply #11 on: August 26, 2015, 01:55:47 AM »

It is GPL v2, should be compatible with OA's code liscense. It does not use code that is under different licenses, the way the initial bone data is written is inspired of those two formats but not copy-pasted. Their codes are GPL as well anyway. Everything here I am slaving away at whenever I have time to, so that 1: OpenArena gets an easy to use model format that doesn't have a complicated pipeline, and anyone could use it. 2: I get a basis of a completed model format that I wrote myself, to expand it into another format I have planned for a project(one with separate skeleton animation and model data *gasp*).


And what if you publish your very own work under several licences?
Logged

I'm good at everything but can't do anything...
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #12 on: August 26, 2015, 06:38:04 AM »

What do you mean? I intend to leave MSK as GPL, the exporter is GPL due to being based off the MD3 exporter which is also GPL. I don't have much room, nor do I care for for putting things under different licenses for this model format.

Also, I hope someone can help with this math since I've been constantly getting it wrong:
Code:
## get identity matrix
            scene.frame_set(scene.frame_start) # base frame
            identityMatrix = mathutils.Matrix.Identity(4)
            if correct_frontaxis:
              my_rotation = mathutils.Matrix.Rotation(radians(90), 4, 'Z')
              identityMatrix = identityMatrix * my_rotation
              identityMatrix.normalize()

            ## get base pos matrix
            baseMatrix = pbone.matrix * identityMatrix
            if pbone.parent:
              parentMatrix = pbone.parent.matrix.inverted() * identityMatrix
              baseMatrix = baseMatrix * parentMatrix
            
            ## get matrix for current frame
            scene.frame_set(frame) # current frame
            poseMatrix = pbone.matrix * identityMatrix
            if pbone.parent:
              parentMatrix = pbone.parent.matrix.inverted() * identityMatrix
              poseMatrix = poseMatrix * parentMatrix
              
            bonemat = baseMatrix.inverted() * poseMatrix  # get transformation
This is VERY close, but the animations go the wrong way. Without the inverse base, the animations tweak out.

Edit: Also, FromHell, if you are concerned about low-end support, you could allow a fast-skinning option where you use only the most influential bone to transform the mesh. Single weight based bones animations can still work pretty well if the model is created with that in mind. The original half-life had only one bone per vertex assigned and so did the original Max Payne game.
« Last Edit: August 26, 2015, 07:29:31 PM by revanic » Logged
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #13 on: August 29, 2015, 08:17:14 PM »

Exporter is definitely not out this week, I can't seem to get the math right for the bones, ugh. Eventually this will be done and I'll release it. I did find out they aren't supposed to be relative to their parent for this kind of format though. So there's that much. Characters do the t-pose just fine in game, but when you ask them to animate any other frame they become spaghetti.
Logged
Gig
In the year 3000
***

Cakes 45
Posts: 4394


WWW
« Reply #14 on: August 31, 2015, 12:41:48 AM »

Hi!
Consider I'm not a real dev... my question is (but it is more for Fromhell or Sago)... will a new model format be compatible with old mods? I mean, what would happen when an old mod would try to load a player model of the new kind? Would it work? Would it fall back to a default model instead?

PS: other possible names for the model format may have been "MDO" or "OMD", where "O" stands for "Open".  Smiley I have not checked existing uses of those extensions.
Logged

I never want to be aggressive, offensive or ironic with my posts. If you find something offending in my posts, read them again searching for a different mood there. If you still see something bad with them, please ask me infos. I can be wrong at times, but I never want to upset anyone.
andrewj
Member


Cakes 24
Posts: 584



« Reply #15 on: August 31, 2015, 06:50:43 AM »

There won't be any compatibility issue with supporting another model format. When ioquake3 added IQM support (such as it is), nothing in OpenArena or any mods broke.
Logged
Suicizer
Member
Member
*

Cakes 2
Posts: 402


WWW
« Reply #16 on: August 31, 2015, 09:00:31 AM »

There won't be any compatibility issue with supporting another model format. When ioquake3 added IQM support (such as it is), nothing in OpenArena or any mods broke.

Nice to think about, but isn't that the problem of the mod to stay compatible with the original game platform?
« Last Edit: August 31, 2015, 09:08:56 AM by Suicizer » Logged

I'm good at everything but can't do anything...
grey matter
Member


Cakes 8
Posts: 381

>9k


« Reply #17 on: August 31, 2015, 10:48:11 AM »

Nice to think about, but isn't that the problem of the mod to stay compatible with the original game platform?

OGG and PNG ain't in id Tech 3 either.
Logged

This space is for rent.
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #18 on: September 05, 2015, 09:14:01 PM »

Alright, Here is an update for this month: I have begun to completely re-write the exporter rather than continue to mess with the butchered MD3exporter-based one. The code should be cleaner and character setups will be different. I make no promises of anything at this time and shall now go into hiding until I have something to show. Enjoy the wait Smiley *poof*
Logged
fromhell
Administrator
GET A LIFE!
**********

Cakes 35
Posts: 14520



WWW
« Reply #19 on: September 09, 2015, 05:20:47 AM »

If you want a typical 'rigify'd model to test the exporter and reading on that's actually OA3 related you could try to use this bowdlerized Sorceress
Logged

asking when OA3 will be done won't get OA3 done.
Progress of OA3 currently occurs behind closed doors alone

I do not provide technical support either.

new code development on github
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #20 on: September 09, 2015, 06:16:16 PM »

Uhhh... over half her body is missing in blender. When I put her in edit mode she displays correctly, but other than that I can only see her head( + hat), hands, and feet.
Logged
fromhell
Administrator
GET A LIFE!
**********

Cakes 35
Posts: 14520



WWW
« Reply #21 on: September 09, 2015, 07:06:29 PM »

Strange. She looks okay here (blender 2.66a) and it's pretty much a modifier baked version.  Her materials all use the same texture even
Logged

asking when OA3 will be done won't get OA3 done.
Progress of OA3 currently occurs behind closed doors alone

I do not provide technical support either.

new code development on github
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #22 on: September 15, 2015, 08:34:40 AM »

Okay, I am REALLY excited because this format is nearly done. I just need to fix bone tags rotation and add in a few convenience options for exporting. Animation works 100 percent. I have renamed the format to MDO and there are some changes in file structure. MDO also supports non-skeletal static models with LODs. I know I have renamed this before already, but please bear with me Tongue.

LODs are not done per scene because that idea was stupid. For each lod, you need to create an empty and name it lod_*number*, then you parent all surfaces of that LOD to it. You MUST have at least a lod_0, and only selected surfaces of that lod are exported( the empty itself doesn't need to be selected, and also you will not need to do any seperate upper and lower lod). Do not rename surfaces or remove the . when making LODs as it is needed to skip the end part of the name( body.001 is saved as body in lod_1 on export, for example)

Tags are bone tags, not much different other than needing to set a custom bone property of mdoBoneFlag with a value of 1, bone tags need to use the absolute matrix rather than the relative transformation, which is why the bone flag is needed since it affects animation output for that bone.

Static meshes only support 1 frame, but can be posed by their armature before export ( you can turn off the skeleton on export btw, which will achieve this effect )
Per-frame bounds are supported and appear to work really well.

This is all I have to say right now.
Logged
Suicizer
Member
Member
*

Cakes 2
Posts: 402


WWW
« Reply #23 on: September 15, 2015, 09:03:26 AM »

Okay, I am REALLY excited because this format is nearly done. I just need to fix bone tags rotation and add in a few convenience options for exporting. Animation works 100 percent. I have renamed the format to MDO and there are some changes in file structure. MDO also supports non-skeletal static models with LODs. I know I have renamed this before already, but please bear with me Tongue.

LODs are not done per scene because that idea was stupid. For each lod, you need to create an empty and name it lod_*number*, then you parent all surfaces of that LOD to it. You MUST have at least a lod_0, and only selected surfaces of that lod are exported( the empty itself doesn't need to be selected, and also you will not need to do any seperate upper and lower lod). Do not rename surfaces or remove the . when making LODs as it is needed to skip the end part of the name( body.001 is saved as body in lod_1 on export, for example)

Tags are bone tags, not much different other than needing to set a custom bone property of mdoBoneFlag with a value of 1, bone tags need to use the absolute matrix rather than the relative transformation, which is why the bone flag is needed since it affects animation output for that bone.

Static meshes only support 1 frame, but can be posed by their armature before export ( you can turn off the skeleton on export btw, which will achieve this effect )
Per-frame bounds are supported and appear to work really well.

This is all I have to say right now.



So this currently is a working exporter and importer for the newest Blender version?
Logged

I'm good at everything but can't do anything...
revanic
VIP
Half-Nub


Cakes 4
Posts: 67


« Reply #24 on: September 15, 2015, 11:29:38 AM »

There is no import option. However the exporter works right now. There's just a few touch ups to do before everything will be released.

Edit: Another thing, with this kind of format, true skeletal animation is not possible as the bone matrices represent fully pre-calculated transformations for each bone. An import option would not be possible because of this, as each bones origin for the base frame would be (0, 0, 0) and all bones would have an identity orientation. The only exception would be tag bones, as they need their true placement and orientation for attachments.

Also, FromHell, how important is bone scaling? they aren't included at this time. I have currently compressed the bones to be a Quaternion and translation represented by 16 bit shorts. This makes the file size much smaller without much loss. There is still a tiny amount of bone swimming ( mostly from the quats themselves due to them being so sensitive, even with a scale of 768 punched. Should've seen it when it was at 128 or 255, it was worse than quake 2 )
« Last Edit: September 15, 2015, 11:53:19 AM by revanic » Logged
Pages: [1] 2
  Print  
 
Jump to: