The glow effects are done through particles, the PAR_ chunks in models. I'm not sure what those unknown bytes are for in the vertices but I'll check into them when I have the time. As far as I know blanking them has no effect on the model in-game. I do believe alot of the values in the model are not for the engine but for 3ds max itself, however I maintain the viewpoint that if the engine can render it without those values then max should be able to aswell. Good to see you contributing therockman, it's great to have some fresh people on the scene helping to figure things out :).
As for an application for conversion, it's possible. HeliosDoubleSix and I were talking about creating a metaformat to use for easy importing into different modelling applications. I'm going to stick to 3ds max because I know Blizzard are using it, so everything Blizzard includes in their M3's must be possible through max. Previously I'd designed a World of Warcraft .M2 importer/exporter so I'm able to reuse alot of that code and am reusing it for the future exporter. A metaformat is a little too much overhead for me, I don't get alot of spare time as it is, and it would mean coding in something like C plus which is not my fortay. I do feel like restricting people to 3ds max is not the way to go but at the moment, it'll have to be up to other people to sort it out.
It's done through ribbons. The hair is bound to the Star2Ribbon01 bone in the model. We don't have ribbons properly documented yet, but you can see the first int32 points to its parent bone. You can turn ribbons off by blanking the reference and you'll see the hair disappear.
I haven't tried using the rotation matrix that comes right after the IREF reference, but the one in the zealot contains no rotation data, just translation.
It says the person that submitted it at nibbits was you? Is that really you or someone pretending to be you? I'll make an account at some stage and sort it out. It looks bad how my name has been pulled from anywhere in the description :(
I've looked into the smoothing, it's because your importing the model through the OBJ importer in 3ds max. It uses an algorithm to automatically smooth faces based on their angles to one another when no smoothing groups are provided, I'm assuming the SC2 engine does something similar. I'm not sure how to do this through my script, but I've checked my normals against the ones present in your OBJ generated files and they're the same. I'll try and hunt down some maxscript code that does similar smoothing to the OBJ importer.
@witchsong:
I'm also interested in figuring out the basic information an M3 requires for rendering. It'll be easy to export static mesh geometry at this point, the only problems I foresee are the materials with their layer information. However I believe alot of the values are mostly pointless (such as the many animation ref's) so it won't be long before we can start putting custom models into SC2. My concern is that we're at a road block with animations. Until we figure out what's going wrong, we're going to be stuck with just geometry exporting capabilities, and that's not much fun.
Hrm? Which seams? The normals seem fine to me, can put up a shot of the max normals or you can look for yourself in max. You don't have to do the player colours by hand Sixen, I'm just rendering them with no colour. Witchsong is correct. Really have to figure out these animations and why they're going so wrong. It's confusing because some bones seem to go where they should be while others are completely messed up.
Initial Reference (fancy wording for bindpose?) would be my guess. Yes, so far as I can tell the matrix has no impact on the bone itself. The bone bindpose is setup through the scale/rotations/translation values found in the bone chunks. The IREF values seem like they're only used for putting vertices in the bindpose position. I'm thinking you could move the vertices to their IREF positions then have the bones carry them to the bindpose position, but I'm not getting good results trying that method through maxscript.
I've found a guide on how to calculate final vertex positions with vertices weighted to multiple bones in this MD5 guide which I've added to my new M3 import script. The M3 format is extremely close to how the MD5 format is read, at least when it comes to bones/vertices/bindposes and animations. Even moving the vertices with multiple bone weights, there's geometry ending up where it shouldn't be. The immortal is very tricky, its left cannon is completely reversed. The zealot's bones do not animate as they should (check out the Fidget_Full animation to see what I mean) and its blade vertices seem bound to the wrong bones and consequently positioned incorrectly. I'm definitely missing something major when it comes to animations. My bindposes are almost identical to how they look in-game for most models, but some such as the immortal and the zealot have vertices seemingly weighted to bogus bones and ending up in weird orientations/positions. I'll keep investigating, there's something we're missing.
This is mostly for witchsong and myself, but feel free to eavesdrop :)
I'm going to explain how I setup the bones/mesh in my maxscript plugin. I'm not very good with matrices, so maybe you can shed some light on what I may be missing. To begin with, I have noticed alot of parallels between the MD5 (doom3) model format and M3. I believe they use similar methods to animate their models. You can find out more about the MD5 file format at Doom3world.
Bone Arrangement
The IREF chunks in M3's seem to contain the transformation matrix for each of the bone nodes. However this is not the bindpose, the nodes are additionally positioned, orientated and scaled through the bone chunks all relative to the parent. In my script I don't even use the matrices to arrange the bindpose bone setup.
First, I create all the bones, then I set up the chain by linking all the bones with parents to their parent bone. After that I iterate through the bones based on depth so that I begin with bones furthest from the root bone of the chain. Then I apply the scale, rotation and position (in that order) to the bone in the coordinate system of the parent bone (in maxscript you have to indicate the coordinate system) for all the bones so that the root bone is done last. I'm not sure if this is the correct way to go about arranging the bones but it gives me what I believe is the bindpose of the model when no animation data is present. That's the bindpose of the bones covered.
Code is here:
mb=mread.bones--M3bonechunksfori=1tomb.countdo--iteratethroughbonechunks(b=mb[i]--assignbcurrentboneiniteration--createbonenode,placementseemsirrelevantaschangedlatercb=BoneSys.createBone[0,0,0][0,0,0][0,0,0.1]--3dsMaxsettings,nothingimportantjustvisualelementscb.name=b.namecb.width=bonesizecb.height=bonesizecb.showLinks=truecb.boneScaleType=#none--appendthecbnodeontocbonesarray(maxscriptdynamicallyenlargesarray)appendcbonescb)maxviewsredraw--redrawsallviewports--Afterbonenodesarecreated,linkthemtogetherecho"Setting up bone hierarchy"fori=1tomb.countdo--iteratethroughbonechunks/nodes(b=mb[i]--currentbonechunk--Maxscriptuses1basedarraysinsteadof0based---1fornobonebecomes0,0becomes1,andsoforthifb.parent!=0then--ifbonehasaparent...(cbones[i].parent=cbones[b.parent]--assignthenodesparent))echo"Set up bone depth"--sortbonesbydepthfunction,returnsanarrayofdepthassortedboneswith--xandymembers.xindicatesdepthofbone,yindicatesthebonelocalbd=M3_Get_Bone_Depthmread.bonesecho"Set up bone transform"fori=1tocbones.countdo--iteratethroughbonenodes(--Dodeepestbonesfirstlocalh=bd[i].y--h=bonetotransformb=mread.bones[h]--M3bonechunkcb=cbones[h]--3dsMaxbonenodeincoordsysparent--intheparentcoordinatesystem(--applythescale,rotationandtranslationinthebonechunk--tothebonenodecb.scale=b.scalecb.rotation=b.rotcb.position=b.pos))
Vertex Setup
Now the bindpose is not arranged so that it deforms the standard mesh, so you need to adjust the vertices so that the mesh fits the bone placement. The way I do this, I really don't understand the math completely to be honest, but it seems to work at least partially.
Iterating through each vertex:
Multiply the original vertex position by the IREF matrix of the first bone it's weighted to (I assume there's a way to do all the bones a vertex is weighted to but I don't know how yet)
Multiply the new vertex position by the scale, inverse rotation and position of the bone. The rotation is the inverse due to the way 3ds max stores transform matrix rotations.
Hopefully that makes a bit of sense. I know maxscript can be confusing to read coming from C. Now I know the bones/mesh seems a bit off. I'm not sure why, I think this is as far as I can get. Figuring out the rest will be up to someone who has a better understanding of matrices and such.
I've got a few models to compare to show that my bindposes are at least mostly accurate. The in-game shots are done by blanking all the animid's in the bone chunks so that they don't reference any sequence data. All you're left with is the bindpose of the model. I notice that some meshes aren't in the right place, I believe this has something to do with vertices that are weighted to multiple bones which I'm not taking into consideration, and also attachments using their own transformation matrix.
Comparison shots:
Immortal has bad geometry, something I need to look into
@therockman: Go
The glow effects are done through particles, the PAR_ chunks in models. I'm not sure what those unknown bytes are for in the vertices but I'll check into them when I have the time. As far as I know blanking them has no effect on the model in-game. I do believe alot of the values in the model are not for the engine but for 3ds max itself, however I maintain the viewpoint that if the engine can render it without those values then max should be able to aswell. Good to see you contributing therockman, it's great to have some fresh people on the scene helping to figure things out :).
As for an application for conversion, it's possible. HeliosDoubleSix and I were talking about creating a metaformat to use for easy importing into different modelling applications. I'm going to stick to 3ds max because I know Blizzard are using it, so everything Blizzard includes in their M3's must be possible through max. Previously I'd designed a World of Warcraft .M2 importer/exporter so I'm able to reuse alot of that code and am reusing it for the future exporter. A metaformat is a little too much overhead for me, I don't get alot of spare time as it is, and it would mean coding in something like C plus which is not my fortay. I do feel like restricting people to 3ds max is not the way to go but at the moment, it'll have to be up to other people to sort it out.
@witchsong: Go
It's done through ribbons. The hair is bound to the Star2Ribbon01 bone in the model. We don't have ribbons properly documented yet, but you can see the first int32 points to its parent bone. You can turn ribbons off by blanking the reference and you'll see the hair disappear.
I haven't tried using the rotation matrix that comes right after the IREF reference, but the one in the zealot contains no rotation data, just translation.
@witchsong: Go
It says the person that submitted it at nibbits was you? Is that really you or someone pretending to be you? I'll make an account at some stage and sort it out. It looks bad how my name has been pulled from anywhere in the description :(
I've looked into the smoothing, it's because your importing the model through the OBJ importer in 3ds max. It uses an algorithm to automatically smooth faces based on their angles to one another when no smoothing groups are provided, I'm assuming the SC2 engine does something similar. I'm not sure how to do this through my script, but I've checked my normals against the ones present in your OBJ generated files and they're the same. I'll try and hunt down some maxscript code that does similar smoothing to the OBJ importer.
@witchsong:
I'm also interested in figuring out the basic information an M3 requires for rendering. It'll be easy to export static mesh geometry at this point, the only problems I foresee are the materials with their layer information. However I believe alot of the values are mostly pointless (such as the many animation ref's) so it won't be long before we can start putting custom models into SC2. My concern is that we're at a road block with animations. Until we figure out what's going wrong, we're going to be stuck with just geometry exporting capabilities, and that's not much fun.
Hrm? Which seams? The normals seem fine to me, can put up a shot of the max normals or you can look for yourself in max. You don't have to do the player colours by hand Sixen, I'm just rendering them with no colour. Witchsong is correct. Really have to figure out these animations and why they're going so wrong. It's confusing because some bones seem to go where they should be while others are completely messed up.
I got the zealot and marine vertices all good now:
The immortal is still messed up, I'll work on it later. I'll explain how I got the zealot and other bindposes looking proper later too :).
Initial Reference (fancy wording for bindpose?) would be my guess. Yes, so far as I can tell the matrix has no impact on the bone itself. The bone bindpose is setup through the scale/rotations/translation values found in the bone chunks. The IREF values seem like they're only used for putting vertices in the bindpose position. I'm thinking you could move the vertices to their IREF positions then have the bones carry them to the bindpose position, but I'm not getting good results trying that method through maxscript.
I've found a guide on how to calculate final vertex positions with vertices weighted to multiple bones in this MD5 guide which I've added to my new M3 import script. The M3 format is extremely close to how the MD5 format is read, at least when it comes to bones/vertices/bindposes and animations. Even moving the vertices with multiple bone weights, there's geometry ending up where it shouldn't be. The immortal is very tricky, its left cannon is completely reversed. The zealot's bones do not animate as they should (check out the Fidget_Full animation to see what I mean) and its blade vertices seem bound to the wrong bones and consequently positioned incorrectly. I'm definitely missing something major when it comes to animations. My bindposes are almost identical to how they look in-game for most models, but some such as the immortal and the zealot have vertices seemingly weighted to bogus bones and ending up in weird orientations/positions. I'll keep investigating, there's something we're missing.
This is mostly for witchsong and myself, but feel free to eavesdrop :)
I'm going to explain how I setup the bones/mesh in my maxscript plugin. I'm not very good with matrices, so maybe you can shed some light on what I may be missing. To begin with, I have noticed alot of parallels between the MD5 (doom3) model format and M3. I believe they use similar methods to animate their models. You can find out more about the MD5 file format at Doom3world.
Bone Arrangement
The IREF chunks in M3's seem to contain the transformation matrix for each of the bone nodes. However this is not the bindpose, the nodes are additionally positioned, orientated and scaled through the bone chunks all relative to the parent. In my script I don't even use the matrices to arrange the bindpose bone setup.
First, I create all the bones, then I set up the chain by linking all the bones with parents to their parent bone. After that I iterate through the bones based on depth so that I begin with bones furthest from the root bone of the chain. Then I apply the scale, rotation and position (in that order) to the bone in the coordinate system of the parent bone (in maxscript you have to indicate the coordinate system) for all the bones so that the root bone is done last. I'm not sure if this is the correct way to go about arranging the bones but it gives me what I believe is the bindpose of the model when no animation data is present. That's the bindpose of the bones covered. Code is here:
Vertex Setup
Now the bindpose is not arranged so that it deforms the standard mesh, so you need to adjust the vertices so that the mesh fits the bone placement. The way I do this, I really don't understand the math completely to be honest, but it seems to work at least partially. Iterating through each vertex:
Hopefully that makes a bit of sense. I know maxscript can be confusing to read coming from C. Now I know the bones/mesh seems a bit off. I'm not sure why, I think this is as far as I can get. Figuring out the rest will be up to someone who has a better understanding of matrices and such.
I've got a few models to compare to show that my bindposes are at least mostly accurate. The in-game shots are done by blanking all the animid's in the bone chunks so that they don't reference any sequence data. All you're left with is the bindpose of the model. I notice that some meshes aren't in the right place, I believe this has something to do with vertices that are weighted to multiple bones which I'm not taking into consideration, and also attachments using their own transformation matrix.
Comparison shots:
Immortal has bad geometry, something I need to look into