mugen87 / three-m2loader Goto Github PK
View Code? Open in Web Editor NEWthree.js loader for importing M2 assets from World of Warcraft.
License: MIT License
three.js loader for importing M2 assets from World of Warcraft.
License: MIT License
M2Loader
does not yet support skeletal animation which is however the most important animation technique for character models.
I've tried to implement the feature and tested it with druidcat2.m2
however the geometry gets distorted and not properly animated. Unfortunately, https://wowdev.wiki/ does not provide enough information about how the skeleton should be built and integrated in the scene graph.
Starting with Legion, M2 assets might be chunked. M2Loader
only support a small subset of chunks for far. To improve the compatibility with newer files, chunk parsing support has to be improved. Possible chunks are:
Checked entries are at least partially supported or not implemented for a specific reasons. The idea is to use the parsed chunk data as an alternative data source for building three.js
entities.
It would be good to know if there is an intended way to detect whether an object is animated or not. Right now, M2Loader
counts the number of bones although this approach is not robust.
Lines 394 to 397 in e71c776
The model in the middle is done with the three-m2loader. The one on the left is done with x3dom (up until 2014 https://wowmodelviewer.net/ had a x3d export), which supports skeletal-animations but no texture-animations. The one on the right is done with https://github.com/Deamon87/WebWowViewerCpp which supports both.
M2Loader applies texture-animations to parts of the model that souldn't have texture-animation. In this case, it can be seen on the hands/bracelets of the elemental. They should be static, but M2Loader still "scrolls them around".
Hello, in your example in the test folder I saw that bearmount.m2 is used, I exported all the files with wow.export but threem2loader searches for textures and skins by fileDataID and not by file name. After I looked at bearmount.manifest.json and renamed all the .blp and .skin file names to {fileDataID}.blp everything worked. Is there any way to fix this?
M2 allows to animate the color and transparency of vertices. The loader already parses M2Color
but it does not yet map the data to three.js
entities. AFAICS, M2Color.color
would animate Material.color
and M2Color.alpha
would animate Material.opacity
(next to texture weights).
It would be good to know the filename of such an asset for testing (https://wow.tools/) so _readColors()
can verified and the animation implemented:
Line 145 in 2a4c561
Since Wrath of the Lich King, skin profiles are stored in separate .skin
files. However, earlier M2 assets stored the data in the M2 itself. It would be good to know the filename of such an asset for testing (https://wow.tools/) so the below code path can be implemented and verified:
Lines 160 to 164 in e71c776
Most M2 asset rely on S3TC texture compression which the loader already supports. However, certain assets use uncompressed textures. It would be good to know the filename of such an asset for testing (https://wow.tools/) so the below code path can be implemented and verified:
Lines 1735 to 1739 in e71c776
Hey I basically used the code in your ./test dir to test how it loads vanilla .m2 files.
I get this
RangeError: Offset is outside the bounds of the DataView at DataView.getUint32 (<anonymous>) at BinaryParser.readUInt32 (M2Loader.js:1875:25) at M2Loader._readTrack (M2Loader.js:1176:25) at M2Loader._readBoneDefinition (M2Loader.js:802:27) at M2Loader._readBoneDefinitions (M2Loader.js:828:22) at M2Loader.parse (M2Loader.js:150:32) at Object.onLoad (M2Loader.js:66:10) at three.module.js:39951:38
Any ideas?
Low priority sequences (like emotes) are not embedded in M2 files but located in separate files with .anim
extensions. There is such a file for each low priority sequence and it can be identified via the sequence and subsequence id.
Each sequence that does not hold the 0x20
value in its flag is a called external sequence and must be processed in a separate code path.
I think it's best to introduce an option (loadExternalSequences
) that can be passed to the load()
method. It's default value would be false
. When set to true
, the loader automatically loads all external .anim
files. Their content is stored as array buffers internally and used when parsing tracks.
I've noticed an issue with the WotLK-Version of the airelemental:
When playing the death-sequence, the "main body" of the elemental should disappear, but that doesn't work. This is because the sequence consists of animations with different duration. Some are 3 seconds long, but some (those that fade out the body) are only ~0.9 seconds long. They set the opacity to 0 right at the end of those 0.9 seconds, but then the animation already loops and opacity is back at 1. Instead the animation should wait until all animations of that sequence are finished.
This is almost the opposite of #13.
I tried synchronizing the animations in this commit:
fcbeb7b
And it works for that case:
That looks like it does in game, except the hands and eyes should disappear as well, not sure what's the issue with that.
But I'm not too happy with the code as it really takes active control over the animation-orchestration. I'd rather let tree.js handle it, but I don't think that's possible, since the animations might have different root-objects and thus different mixers, which is why I couldn't get it done with https://threejs.org/docs/index.html#api/en/animation/AnimationAction.syncWith (according to ChatGPT, I have no idea if that's true).
Also I have no idea if doing it this way is always correct or if for some sequences this is wrong. Especially since the death-sequence doesn't really loop ingame anyway, so having the animations loop doesn't make sense. But for sequences like Stand/Walk/Run, maybe it is correct that animations loop individually instead of waiting.
When testing the new version with the air-elemental, I noticed one problem: the "shells" pause after each rotation, while they should rotate continuously. The issue seems to be that the skeletal-animation has tracks of different duration and THREE.js sets the duration for the whole clip to the maximum of the tracks, so the shorter tracks have to wait for the longer ones to finish.
For this instance I could fix it by simply adding a separate clip for each track, like this:
Lines 425 to 426 in 7fe01af
for ( let t = 0; t < globalTracks[ j ].length; t++) {
const clip = new AnimationClip( 'GlobalSkeletonAnimation_' + j + '_' + t, - 1, [ globalTracks[ j ][ t ] ] );
sequenceManager.addAnimationToGlobalSequence( clip, group, j );
}
However I have no idea if that has implications. Probably that should be done for other global animations as well. The airelemental also uses multiple GlobalTextureTransform-Animations, but they all only have a single track, so no issue there. And for non-global animations, all tracks (excluding ones with length 0) have the same length for the airelemental, but I have no idea if that is always the case, and whether tracks should loop individually if tracks do have different lengths.
M2 files lower than Wrath of the Lich King
(264) use a legacy data structure for tracks. It would be good for compatibility to support this format if the required code paths for parsing and key frame creation are manageable.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.