flowtsohg / mdx-m3-viewer Goto Github PK
View Code? Open in Web Editor NEWA WebGL viewer for MDX and M3 files used by the games Warcraft 3 and Starcraft 2 respectively.
License: MIT License
A WebGL viewer for MDX and M3 files used by the games Warcraft 3 and Starcraft 2 respectively.
License: MIT License
mdx-m3-viewer/src/parsers/mdlx/geoset.ts
Line 149 in eef5dd3
Shouldn't the size of the tangents and skin be written there?
In readMdx
the sizes are being read, so it seems like it can be written too.
As in the title, shouldn't this.getByteLength() be used here instead?
As far as I can tell, this function isn't used anywhere right now.
Rather than storing ImageData objects, like the BLP handler currently does.
Does it change some APIs now?
The War3MapViewer
seemed to have default scene in the 'scenes' prop, should replace viewer.scene
by viewer.scenes[0]
?
mdx-m3-viewer/clients/map/index.js
Lines 80 to 91 in ac7e6c2
And in some other examples, seemed model viewer not imported correctly.
mdx-m3-viewer/clients/example/index.js
Line 14 in ac7e6c2
let viewer = new ModelViewer.default.viewer.ModelViewer(canvas);
let quat = common.glMatrix.quat;
mdx-m3-viewer/clients/sanitytest/index.js
Lines 3 to 5 in ac7e6c2
let glMatrix = ModelViewer.common.glMatrix;
let vec3 = glMatrix.vec3;
let quat = glMatrix.quat;
The class TriggerData
seems to have not been exported
mdx-m3-viewer/clients/weu/main.js
Lines 10 to 11 in ac7e6c2
The assumption was that pivot points are required. Turns out they are not.
See Objects/CinematicCameras/CameraCloseUpLowNoise.mdx
While having seqend is nice for simple scenes, it's actually bothering performance for complex scenes.
Therefore, complex scenes, namely the map viewer, can do their own tracking.
The same goes for clients.
There should probably still be some relatively simple way to react to sequences, need to think about this more.
Incidentally, this removes the need for EventNode, and therefore for the messy class mixing.
Hello,
I'm working on a data viewer/map parser for WC3, and I'm looking to add a model viewer. This seems like a perfect candidate, but I'll need to strip some code I don't need, like loading BLP/TGA textures (I already have all textures available as PNG). Is it ok if I include this repository code (modified) in my project?
My repo is at https://github.com/d07RiV/wc3data and website at https://wc3.rivsoft.net/
Also there's an issue with your code when transpiled with Babel - extending native classes isn't supported in Babel 6, and in Babel 7 it needs to be hinted when they're not extended directly. This causes a problem with this class:
export class SceneNode extends nodeMixin(Object) {}
In transpiled code, instantiating SceneNode
results in a plain object :(
The methods to write MDL models have a few bugs in them. So far I have seen:
it looks like missing some animation on render
using mdx-m3-viewer
the mdx files
HHY.zip
Using a framebuffer will make picking faster and more efficient, and will remove any noticeable delay in the scene.
mdx-m3-viewer/src/parsers/mdlx/layer.ts
Line 107 in b7fb09f
According to your MDX Specs post on Hive 0x30
is no depth test and 0x40
is no depth set, while here it's 0x40
and 0x100
respectively.
According to this MDL dump of a Reforged model it's 0x40
and 0x80
respectively, and 0x100
for a new Unlit flag.
Any idea which is correct?
If I want to render, say a sphere, into an already loaded + rendered wc3 map, what would be the most appropriate way to go about this?
Looking at the code in mdx-m3-viewer\src\viewer\handlers\w3x\viewer.ts
lines 627-656:
for (let unit of unitsDoo.units) {
let row: MappedDataRow | undefined;
let path;
// Hardcoded?
if (unit.id === 'sloc') {
path = 'Objects\\StartLocation\\StartLocation.mdx';
} else {
row = this.unitsData.getRow(unit.id);
path = <string>row.file;
if (path.endsWith('.mdl')) {
path = path.slice(0, -4);
}
path += '.mdx';
}
if (path) {
this.load(path)
.then((model) => {
if (model) {
this.units.push(new Unit(this, <MdxModel>model, row, unit));
}
});
} else {
console.log('Unknown unit ID', unit.id, unit);
}
}
It looks like I can just add units/objects to the map like so -
if (model) {
this.units.push(new Unit(this, <MdxModel>model, row, unit));
}
given that I provide -
unit
that holds info such as scale, location, angle, player, etc.row
setScene
methodMy understanding is that the model should be able to create a model instance and is in charge of determining what webgl program to use to render itself. I would start off by using an existing primitive such as a sphere.
KP2N has the model token Width and KP2W the token Length, shouldn't that be the other way around?
Hi,
I've just cloned your repo on my work station but I'm not able to get started with a trivial example. Commands I ran:
git clone https://github.com/flowtsohg/mdx-m3-viewer/
cd mdx-m3-viewer
ruby compiler.rb
Generating the viewer
compiler.rb:187:in `read': No such file or directory - src/spatial.js (Errno::ENOENT)
from compiler.rb:187:in `block (2 levels) in compile_source'
from compiler.rb:183:in `open'
from compiler.rb:183:in `block in compile_source'
from compiler.rb:179:in `each'
from compiler.rb:179:in `compile_source'
from compiler.rb:278:in `compile'
from compiler.rb:281:in `<main>'
Although compiler.rb didn't manage to generate viewer.js, it generated some files in a build directory, build/spatial.js being one of them. I copied enough js files from build to src so that I was able to run compiler.rb with no error.
I guess build/output/viewer.js is the file to be included in a project. So I copied it in examples directory and opened examples/index.html in a browser. But the javascript console output those lines:
ReferenceError: EventDispatcher is not defined viewer.js:5333:1
ReferenceError: BaseModel is not defined objmodel.js:5:1
ReferenceError: BaseModelInstance is not defined objmodelinstance.js:5:1
Since I was already working on assumptions so far, I'm seeking confirmations about how the build process is supposed to be done.
Maybe I've missed some steps, but it would be very helpful to have a detailed step-by-step procedure to get started with your example :)
Thanks
I am still not sure about this one, but the code might be eventually and over time changed to Typescript.
This is because while writing JS, intellisense barely functions, and usually can't recognize types, function signatures, and so on.
This should be TextureID (capital D). Not sure if this matters at all (case insensitive?).
Models are not required to have sequences.
See UI/Feedback/Resources/resources.mdx
From our previous discussion over email I know you don't check your email often and would prefer to chat over the Hive Discord channel. Could you specify what that channel name is under your readme, because I cannot find it, and it may help other followers here too.
The Mac OpenGL drivers force to write to all varyings.
For now, M3's vsstandard.c fills all the output UVs with dummy data to avoid this issue, but the shader should be redesigned to avoid this issue in the first place.
handlers/mdx/modelinstance is lowercase in compiler.rb, but file name is modelInstance with uppercase I, so it doesn't find the file.
Easy to fix.
Particles are not scaled together with their owning model instances.
Reported by Retera.
Scaling keys of a parent scale also child instances.
Width and Length writing are inverted. In the readMdx function width comes first.
It doesn't make sense to store in-memory loads in the resources map.
If the client can store the in-memory source (e.g. an ArrayBuffer), then it may as well just store the resulting resource directly.
The whole point of the resources map was to avoid fetching things multiple times due to paths having difference letter cases - something which Warcraft 3 is filled with - that's why the final source is used.
In addition, if the client has to store this in-memory source forever, and it is stored in the resources map forever, then it is wasted memory that sits there for no purpose.
In viewer.ts line 282:
async loadTerrainCliffsAndWater(w3e: War3MapW3e) {
let texturesExt = this.solverParams.reforged ? '.dds' : '.blp';
let tileset = w3e.tileset;
let tilesetTextures = [];
let cliffTextures = [];
let waterTextures = [];
for (let groundTileset of w3e.groundTilesets) {
let row = this.terrainData.getRow(groundTileset);
this.tilesets.push(row);
tilesetTextures.push(this.load(`${row.dir}\\${row.file}${texturesExt}`));
}
This function works fine when loading up a map with the classic wc3 settings, but if I specify reforged, then I get an issue where the tileset strings inside of w3e.groundTilesets
do not match whats available inside of this.terrainData
. This happens for any frozenthrone map, or maps from hive. For example none of these values -
0: "Zdrt"
1: "Zdtr"
2: "Zdrg"
3: "Zbks"
4: "Zsan"
5: "Zbkl"
6: "Ztil"
7: "Zgrs"
8: "Zvin"
would be contained in this.terrainData's map object.
I'm not sure if this is a result of me missing using the library or something else.
Hey Chananya,
I am unable to render m3 models. I am adding all these loaders:
viewer.addHandler(handlers.mdx);
viewer.addHandler(handlers.dds);
viewer.addHandler(handlers.blp);
viewer.addHandler(handlers.tga);
viewer.addHandler(handlers.m3);
and my code works fine for WC3 models. Last we talked you said it wasn't updated for SC2 yet. Any progress?
ui/feedback/cooldown/ui-cooldown-indicator.mdx
Since the timeline grows linearly, if the previous keyframe is kept, there is no need for any iteration, you can just get keys[key + 1].
Doing an actual search, then, only becomes necessary when initializing an animation at an arbitrary frame, which is done only in Mdx.Particle2.reset.
This will make almost every keyframe query O(1).
There's some data which isn't represented in the MDL read/write.
For v800 models I'm sure you're aware of these:
EventTrack [COUNT excluding globseqid] {
GlobalSeqId [ID],
[TRACKS...],
}
AnimationFile "[PATH]",
It would be easier to move around the scene if the rotation origin of the scene was where the mouse was when the rotation started.
E.g. in BinaryStream.
This will allow to have Russian, Chinese, or whatever, and not seeing a bunch of empty boxes.
For example:
viewer.on('error', (viewer, error, reason) => {
console.log(`Error: ${error}, Reason: ${reason}`);
});
In addition there is ModelViewer.whenAllLoaded() which will trigger both on the idle event, and if there is currently nothing loading.
For example:
viewer.on('error', ({ viewer, error, reason }) => {
console.log(`Error: ${error}, Reason: ${reason}`);
});
In addition, there is ModelViewer.whenAllLoaded() which will trigger both on the idle event, and if there is currently nothing loading.
Hey cool library, I like it very much ;-).
I have a problem where models might refer to a texture with a .blp extension, but the way Warcraft 3 works, this path is equivalent with the same path with all these extensions ['dds', 'tif', 'tga', 'blp'] and I only know which one actually exists by the time the fetch is complete. So I would very much like to be able to have my pathSolver return a promise, potentially with just an extension and a buffer or a way to tell the viewer to auto detect the extension.
The only work-around I can think of to give me this is to preload a list of all paths before starting to load the model.
You can change background color with scene.color
but is there a way to remove the background color / make it transparent? I thought scene.alpha = true
would do the job but it might be used for something else. I did a Hail Mary and changed the gl.clearColor
alpha argument to 0 in the startFrame()
function of scene.ts
and it didn't also work (still black).
how can use War3Map make extract w3x file to a dir?
The priorityPlane is being read as int32 but written as uint32. It probably doesn't matter, but thought I'd point it out :)
Find some strange behavior on latest model viewer.
There are many mosaics in team color
Maybe a circle renderer bug?
Also with some wings
I find it can injiet some model befor create an instance by add a model on attachments manually.
and can it support multi?
model.whenLoaded().then(model => {
// use this code before add instance
model.attachments[1].internalModel = viewer.load(`${name}.mdx`, pathSolver);
let instance = model.addInstance();
instance.setScene(scene);
instance.setSequence(
model.sequences.findIndex(seq => seq.name.toLowerCase().includes('stand')),
);
});
There is no way to support global translucency sorting with instanced rendering.
Unfortunately this means that all of the effort of implementing instanced rendering in v4 was kind of pointless.
The plan is in general:
Hey Chananya,
The viewer code that used to work isn't working anymore. The screen is just black.
The only thing that sticks out to me is that it always has this error:
error: "Failed to fetch a generic resource"
fetchUrl: "/casc-contents?path=UI%5CSoundInfo%5CAnimLookups.slk"
viewer: Object { _eventsCount: 4, frameTime: 16, visibleCells: 1, … }
But it did so in the past and that file does not exist. Perhaps the promise thing caused it to not work any longer?
The network tab shows that it is loading all these things:
I would show you the code but not in a ticket and your email seems broken.
Hi, I'm trying to get the examples/index.html to display any kind of .mdx model.
It doesnt even show the supplied. obj model.
I added .mdx as supported filetype directly, I added some dummy .pngs for the stuff I mentioned in the title but all it shows is the ground plane. No model.
I did the compilation via ruby, but still.. I assume this is just outdated?
Any clue what's going wrong, because after I added .mdx to the supportedFileTypes array I'm not getting any more errors.
I'm trying this with AzureDragon.mdx
mdx-m3-viewer/src/parsers/mdlx/texture.ts
Line 43 in aa0efe4
I've tested it ingame, this line doesn't need to be written when the path is empty (i.e. Image "",
).
Either the path or the replaceable id need to be written though, or it will fail to load the model.
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.