3D Model Viewer

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
Cool as it looks, I am not entirely sure it is meant to look like this...
attachment.php

The geometry looks stretched from the centre, as if an explosion had occurred.

Seems to be a problem with Microsoft Edge. In IE11 it looks more like one would expect.

This is strange as it looked fine in Microsoft Edge yesterday when you linked it in the chat.
 

Attachments

  • GhostWolf's Bomb.jpg
    GhostWolf's Bomb.jpg
    167.8 KB · Views: 208
Cool as it looks, I am not entirely sure it is meant to look like this...
attachment.php

The geometry looks stretched from the centre, as if an explosion had occurred.

Seems to be a problem with Microsoft Edge. In IE11 it looks more like one would expect.

This is strange as it looked fine in Microsoft Edge yesterday when you linked it in the chat.

Works just fine in Chrome. It looks as if the world is imploding in your picture.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Seems to be a problem with Microsoft Edge. In IE11 it looks more like one would expect.

This is strange as it looked fine in Microsoft Edge yesterday when you linked it in the chat.

Pretty much all of the rendering code is different than what you saw.
Can't test it on Edge, since I don't have Windows 10.
Maybe it has issues with instanced rendering?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
Following errors...

HTTP404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier).
(XHR): GET - http://viewer.hiveworkshop.com/MPQ/sheet.css
HTML1300: Navigation occurred.
MPQ
HTTP404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier).
(XHR): GET - http://viewer.hiveworkshop.com/MPQ/sheet.css
HTTP404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier).
(XHR): GET - http://viewer.hiveworkshop.com/MPQ/images/ground.png
HTTP404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier).
(XHR): GET - http://viewer.hiveworkshop.com/MPQ/images/water.png
HTTP404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier).
(XHR): GET - http://viewer.hiveworkshop.com/MPQ/images/sky.png
war3map.w3e
,war3map.w3i
,war3map.wtg
,war3map.wct
,war3map.wts
,war3map.j
,war3map.shd
,war3mapMap.blp
,war3map.mmp
,war3map.wpm
,war3map.doo
,war3mapUnits.doo
,war3map.w3r
,war3map.w3c
,war3map.w3u
,war3map.w3s
,
mpq.js (421,5)
[
0: "war3map.w3e
",
1: "war3map.w3i
",
2: "war3map.wtg
",
3: "war3map.wct
",
4: "war3map.wts
",
5: "war3map.j
",
6: "war3map.shd
",
7: "war3mapMap.blp
",
8: "war3map.mmp
",
9: "war3map.wpm
",
10: "war3map.doo
",
11: "war3mapUnits.doo
",
12: "war3map.w3r
",
13: "war3map.w3c
",
14: "war3map.w3u
",
15: "war3map.w3s
",
16: "",
length: 17
]

LOh1
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOlp
mpq.js (400,9)
YPbs
mpq.js (400,9)
LTw2
mpq.js (400,9)
VOfl
mpq.js (400,9)
AObd
mpq.js (400,9)
LOsh
mpq.js (400,9)
LTlt
mpq.js (400,9)
LOsh
mpq.js (400,9)
AWfs
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOsh
mpq.js (400,9)
VOfs
mpq.js (400,9)
LSba
mpq.js (400,9)
VOfs
mpq.js (400,9)
VOfl
mpq.js (400,9)
LTw2
mpq.js (400,9)
VOfs
mpq.js (400,9)
VOfl
mpq.js (400,9)
LTw2
mpq.js (400,9)
LOsh
mpq.js (400,9)
LOsh
mpq.js (400,9)
AObd
mpq.js (400,9)
LSwl
mpq.js (400,9)
LOsh
mpq.js (400,9)
LOsh
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOh1
mpq.js (400,9)
LOsp
mpq.js (400,9)
LOwb
mpq.js (400,9)
LOwb
mpq.js (400,9)
LOch
mpq.js (400,9)
LOh1
mpq.js (400,9)
ARrk
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw0
mpq.js (400,9)
ARrk
mpq.js (400,9)
LPrs
mpq.js (400,9)
LPrs
mpq.js (400,9)
LOtr
mpq.js (400,9)
LSwl
mpq.js (400,9)
LOrh
mpq.js (400,9)
YPbs
mpq.js (400,9)
LTlt
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTlt
mpq.js (400,9)
LOwb
mpq.js (400,9)
LOsh
mpq.js (400,9)
LOsh
mpq.js (400,9)
LTlt
mpq.js (400,9)
YOwa
mpq.js (400,9)
LTw0
mpq.js (400,9)
YPbs
mpq.js (400,9)
LTw2
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTlt
mpq.js (400,9)
YOfn
mpq.js (400,9)
LOlp
mpq.js (400,9)
AWfs
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTlt
mpq.js (400,9)
AWfs
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTlt
mpq.js (400,9)
LSin
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTlt
mpq.js (400,9)
LSwl
mpq.js (400,9)
LTcr
mpq.js (400,9)
LTcr
mpq.js (400,9)
VOal
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw2
mpq.js (400,9)
LOss
mpq.js (400,9)
LOrh
mpq.js (400,9)
LOrh
mpq.js (400,9)
LTlt
mpq.js (400,9)
LSgr
mpq.js (400,9)
APct
mpq.js (400,9)
ARrk
mpq.js (400,9)
VOfs
mpq.js (400,9)
LOrh
mpq.js (400,9)
LTw0
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTw2
mpq.js (400,9)
AWfs
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOlp
mpq.js (400,9)
YOec
mpq.js (400,9)
YOec
mpq.js (400,9)
LOrc
mpq.js (400,9)
YOec
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw2
mpq.js (400,9)
AObd
mpq.js (400,9)
LOss
mpq.js (400,9)
YPbs
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOlp
mpq.js (400,9)
AWfs
mpq.js (400,9)
LTw2
mpq.js (400,9)
YPbs
mpq.js (400,9)
LObz
mpq.js (400,9)
YPbs
mpq.js (400,9)
LSwm
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTlt
mpq.js (400,9)
YPbs
mpq.js (400,9)
YPbs
mpq.js (400,9)
LOhp
mpq.js (400,9)
LOlp
mpq.js (400,9)
YPbs
mpq.js (400,9)
APct
mpq.js (400,9)
LTlt
mpq.js (400,9)
LOh1
mpq.js (400,9)
LOh1
mpq.js (400,9)
YPbs
mpq.js (400,9)
LTw2
mpq.js (400,9)
AWfs
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTw2
mpq.js (400,9)
VOfs
mpq.js (400,9)
VOfl
mpq.js (400,9)
VOfl
mpq.js (400,9)
LOtr
mpq.js (400,9)
LTw0
mpq.js (400,9)
LSgr
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTlt
mpq.js (400,9)
VOal
mpq.js (400,9)
LTlt
mpq.js (400,9)
YPbs
mpq.js (400,9)
LOlp
mpq.js (400,9)
VOal
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTlt
mpq.js (400,9)
VOal
mpq.js (400,9)
VOal
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw0
mpq.js (400,9)
YObw
mpq.js (400,9)
LOss
mpq.js (400,9)
YPbs
mpq.js (400,9)
LObr
mpq.js (400,9)
LTw2
mpq.js (400,9)
YPbs
mpq.js (400,9)
LTlt
mpq.js (400,9)
LOrc
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw0
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTw2
mpq.js (400,9)
APct
mpq.js (400,9)
LTw2
mpq.js (400,9)
LOlp
mpq.js (400,9)
LPwb
mpq.js (400,9)
LPwb
mpq.js (400,9)
LTlt
mpq.js (400,9)
VOfs
mpq.js (400,9)
VOfl
mpq.js (400,9)
LOlp
mpq.js (400,9)
VOal
mpq.js (400,9)
VOal
mpq.js (400,9)
LOhp
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTlt
mpq.js (400,9)
LOhb
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw0
mpq.js (400,9)
LPwb
mpq.js (400,9)
LOhp
mpq.js (400,9)
YPbs
mpq.js (400,9)
VOal
mpq.js (400,9)
LPrs
mpq.js (400,9)
AWfs
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTlt
mpq.js (400,9)
APct
mpq.js (400,9)
YPbs
mpq.js (400,9)
APct
mpq.js (400,9)
LTw2
mpq.js (400,9)
YOec
mpq.js (400,9)
LPwb
mpq.js (400,9)
VOal
mpq.js (400,9)
LTw2
mpq.js (400,9)
LSin
mpq.js (400,9)
LTlt
mpq.js (400,9)
VOfs
mpq.js (400,9)
AWfs
mpq.js (400,9)
LTlt
mpq.js (400,9)
YPbs
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTlt
mpq.js (400,9)
VOal
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw0
mpq.js (400,9)
LObr
mpq.js (400,9)
YPbs
mpq.js (400,9)
LOss
mpq.js (400,9)
YOec
mpq.js (400,9)
YOec
mpq.js (400,9)
LSwm
mpq.js (400,9)
LSin
mpq.js (400,9)
LTw2
mpq.js (400,9)
LOwb
mpq.js (400,9)
LSin
mpq.js (400,9)
LSwl
mpq.js (400,9)
LSba
mpq.js (400,9)
LSwm
mpq.js (400,9)
VOal
mpq.js (400,9)
LOce
mpq.js (400,9)
LTlt
mpq.js (400,9)
APct
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTlt
mpq.js (400,9)
LTlt
mpq.js (400,9)
VOal
mpq.js (400,9)
LTlt
mpq.js (400,9)
LOlp
mpq.js (400,9)
YPbs
mpq.js (400,9)
LTw0
mpq.js (400,9)
YPbs
mpq.js (400,9)
APct
mpq.js (400,9)
VOal
mpq.js (400,9)
YOwa
mpq.js (400,9)
LTlt
mpq.js (400,9)
YOec
mpq.js (400,9)
YOec
mpq.js (400,9)
YPbs
mpq.js (400,9)
LTw2
mpq.js (400,9)
YPbs
mpq.js (400,9)
LPwb
mpq.js (400,9)
LOlp
mpq.js (400,9)
LPwb
mpq.js (400,9)
LOar
mpq.js (400,9)
LObz
mpq.js (400,9)
LOhb
mpq.js (400,9)
LOhb
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOhb
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTlt
mpq.js (400,9)
LObz
mpq.js (400,9)
LOlp
mpq.js (400,9)
LOwb
mpq.js (400,9)
LOam
mpq.js (400,9)
AWfs
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTw0
mpq.js (400,9)
AWfs
mpq.js (400,9)
YOfn
mpq.js (400,9)
VOfl
mpq.js (400,9)
LOlp
mpq.js (400,9)
VOal
mpq.js (400,9)
LOlp
mpq.js (400,9)
APct
mpq.js (400,9)
APct
mpq.js (400,9)
APct
mpq.js (400,9)
ARrk
mpq.js (400,9)
APct
mpq.js (400,9)
APct
mpq.js (400,9)
APct
mpq.js (400,9)
ARrk
mpq.js (400,9)
YOwa
mpq.js (400,9)
ARrk
mpq.js (400,9)
YOlp
mpq.js (400,9)
YPbs
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTlt
mpq.js (400,9)
VOal
mpq.js (400,9)
LTlt
mpq.js (400,9)
LPrs
mpq.js (400,9)
LPrs
mpq.js (400,9)
LTw0
mpq.js (400,9)
LSin
mpq.js (400,9)
AWfs
mpq.js (400,9)
AWfs
mpq.js (400,9)
LTw0
mpq.js (400,9)
AWfs
mpq.js (400,9)
LSba
mpq.js (400,9)
VOfl
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw0
mpq.js (400,9)
LOlp
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw0
mpq.js (400,9)
LOlp
mpq.js (400,9)
VOfl
mpq.js (400,9)
VOfl
mpq.js (400,9)
LOrh
mpq.js (400,9)
APct
mpq.js (400,9)
LTw0
mpq.js (400,9)
LTw0
mpq.js (400,9)
APct
mpq.js (400,9)
LOtz
mpq.js (400,9)
LOtz
mpq.js (400,9)
APct
mpq.js (400,9)
APct
mpq.js (400,9)
VOal
mpq.js (400,9)
VOal
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTw2
mpq.js (400,9)
LTcr
mpq.js (400,9)
LTcr
mpq.js (400,9)
LObz
mpq.js (400,9)
LSgr
mpq.js (400,9)
[object Object]
model.js (278,13)
{
[functions]: ,
__proto__: { },
attribs: 6,
fragmentUnit: { },
id: { },
name: "wstandard",
ready: true,
type: "shader",
variables: { },
vertexUnit: { }
}

wwhite Shader compilation errors
(23, 18): Invalid arguments passed to function 'boneAtIndex'

shader.js (28,9)
wcolor Shader compilation errors
(21, 15): Invalid arguments passed to function 'boneAtIndex'
shader.js (28,9)

The invalid arguments to boneAtIndex sounds like a possible cause for the visual anomaly.

IE11 throws a million "OUT OF MEMORY" errors. However it does not look corrupt.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Those errors shouldn't matter, I just didn't update the rest of the shaders which aren't normally used.

The doodads file gives every object with a variation number that allows to load different models (e.g. LanternPost0, LanternPost1), however when a model has no variations, it doesn't have 0 at the end, so loading fails.
Is there a way to know if an object is actually supposed to use the variation or not?


Wrote a very simple SLK parser, it was actually really easy.

/Edit
The variations are properly used now.
I updated the demo to use the SLK files, and I added a button that allows you to select whatever map you want, although most custom maps will probably not load properly (no parsing of custom data yet).
Loading all of the models can take a while, and I didn't bother adding any kind of progress bar, so be patient.
I also re-enabled the camera controls, so you can move and zoom (but it's still the same terrible camera that is pretty useless outside of the scope of a model viewer).

Team glows (and colors) for the MDX handler used texture overriding, and per-instance overriding is no longer possible, so they will need to be computed by the shaders.
While I don't know the equation that generated the original ones, I made a simple approximation that I am happy with for now.
You can see it here in action.
The left image is the original, the right is generated by the code.
The generated images are more shiny and have more contrast (much like a sphere), which makes me believe they used a curvature rather than linear interpolation, but like I said, it's good enough for me, unless someone has a better approximation.

/Edit
All built-in doodads should load now (but custom ones aren't parsed yet).
I added .w3m as an accepted format.
This client was moved to http://viewer.hiveworkshop.com/map/

/Edit
Object data is now used.
This means that user-defined modifications to existing doodads, and newly created ones, are now loaded properly.
Also added a simple message that shows the loading status.
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
Apparently items, doodads and destructables hold their file paths, but units don't.
Is there some file that I don't know of that holds unit ID->file mapping? if not, is there a list somewhere?
I mean, there must be something, since otherwise custom models wouldn't be possible...?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
What about terrain. Is it possible to work that in?

I have no idea how it works currently.

Animations!
I optimized the node computations by simply ignoring skeleton updates for sequences that won't actually change anything (most doodads).
Therefore it should be fast enough...for now.
Eventually I'll do the same for emitters.

Anyone knows anything about the unit paths?

/Edit
Re-implemented team colors.
Re-implemented team glows with the estimation I mentioned previously.

I suddenly realized that since per-instance textures are not possible, it means that texture animations that use images instead of texture coordinates are also not possible (e.g. most elemental models).
Therefore, they are not going to be supported for now.
Eventually I will add an unoptimized rendering path for them.

/Edit
Re-implemented geoset visiblity (from geoset animations or layer visiblity).
 
Last edited by a moderator:
Level 29
Joined
Jul 29, 2007
Messages
5,174
Essentially nothing major needs to change in the M3 handler, it just needs to match the new render call.
Of course, if nothing more is changed, M3 will be as unoptimized as it always was, but I don't really care about it right now.
Obviously the same kind of optimizations can be made for it too (like I've shown in the past).
 
Apparently items, doodads and destructables hold their file paths, but units don't.
Is there some file that I don't know of that holds unit ID->file mapping? if not, is there a list somewhere?
I mean, there must be something, since otherwise custom models wouldn't be possible...?

Units/UnitUI.slk?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Units/UnitUI.slk?

Thanks.

/Edit
Re-implemented geoset colors.
Re-implemented texture coordinate animations.
Units are now loaded (and performance went down drastically, yey!)

/Edit
Made a very nifty (if I may boldly say so) optimization to keyframe fetching which made it a whole lot more efficient. Maps should run quite better now.

/Edit
Split the render calls to opaque and translucent, so translucent layers should be less buggy (rendering behind objects that are behind them, or before objects that are in front of them).
Also changed the near plane of the camera, which removed most of the annoying z-fighting that made intersecting polygons to keep swapping when moving the camera.

/Edit
Made the MPQ parser more efficient.
The texture animation (multiple images) issue is fixed! All of the textures in the animation are put into a single texture atlas, and from there the code just does texture coordinate manipulations to get the correct texture from the atlas, exactly the same way as particle emitters. The current implementation is pretty bad, but I'll improve it.
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
I am trying once again to figure the rules of sequence data, this time actually with checking in the world editor.

What I can gather is that:
1) Frame 0 is ignored (when it's not in an actual sequence, for some reason Magos always seems to define it).
2) If a sequence has only one key, it is constant using that key.
3) If a sequence has no keys, it uses the default value of the sequence data (e.g. [1,1,1] for scale).
4) If a sequence has a keyframe at the beginning, but no keyframe at the end, the beginning keyframe is copied to the end.
5) If a sequence has both start and end keyframes, they are used as is with no overriding (obviously).

This all makes sense...but then a weird thing happened.
I used scaling keyframes in a sequence interval [1833, 4333], with the keyframes being:
2500: { 2, 2, 2 }
3500: { 10, 10, 10 }

The result was the model starting at scale 10, getting somewhat smaller (but nowhere near 2), then immediately changing to 2 when it reached that frame, scaling back to 10 as expected, then starting to scale down to something weird again, and repeat.

I can't explain this...

Does anyone have better observations?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Sure, it's just the in-game Footman with said changes to the root bone.

Attached the test map (it has also other tests in it).

This specific test is the unit already placed in the map, and it's in the Stand - 2 sequence.

This one is actually using 0.1 scale to 10, to make the change more obvious (though the sequence is too short to really see...probably should have used a building instead of the footman).
 

Attachments

  • Map.w3m
    323.5 KB · Views: 65
Level 29
Joined
Jul 29, 2007
Messages
5,174
In fact, just in the test map there are multiple in-game models that don't have starting keyframes (GoldMine, ForestTroll, ForestTrollTrapper, Ogre, OgreMagi, MarketPlace, OgreLord, GnollWarden).
The conditions for the check are that there isn't a global sequence, and that there are multiple keyframes in the sequence.
So it's kind of important to know what to do when there isn't a starting keyframe...
 

Ralle

Owner
Level 79
Joined
Oct 6, 2004
Messages
10,212
I am thinking out loud here, been a while since I attempted at making my own model viewer. MDX can pretty easily be converted to MDL right? If that is the case, shouldn't this problem persist in the MDL? Then can we see how all of the MDL viewers in the world handle this issue? Many of them are probably open source.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
There are Blizzard MDL viewers other than Magos?

For now the rules will be as following, until the results of the game are clearer (if they'll ever be...):

If a sequence data has 0 or 1 keyframes, for a specific sequence, it's constant for that sequence (which makes the code a lot more optimized!).

If a sequence data has 2+ keyframes, then:
1) If the sequence data has no keyframe at the start of the sequence, the default value (e.g. [0, 0, 0] for translation, [1, 1, 1] for scale, etc.) is injected.
2) If the sequence data has no keyframe at the end of the sequence, the keyframe from the start of the sequence is injected but with the in/out tangents swapped.

If a sequence data uses a global sequence, then it is considered as a sequence between [0, global sequence value], and the above rules are applied in the same way.

We'll see how this fares...
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
The mdl and mdx formats are very confusing. WC3 can apparently pass mdl files judging by the constants it contains in its machine code. However if one tries to get WC3 to load a mdl file it breaks (cube model). Further more when you reference models in the object editor it appends ".mdl" onto the path even if the actual path is suffixed with ".mdx" and it then successfully loads the model.

I have a feeling that WC3 used the text based mdl format in one of its alpha/beta phases which is where the structure and concept of "mdl" files came from. They then migrated to binary mdx probably for file size and possibly load times. A lot of the legacy mdl stuff remains in the games machine code, such as all strings for different chunks and a lot of parse error messages. However as far as I know one cannot get the game to load mdl files.

It is possible that the mdl tools we have do not produce correct mdl output which is why WC3 cannot load them. It is also possible that the mdl code is not reachable, fully replaced with the mdx code and is only present in the game due to the dll based structure of WC3 (compiler had to put it in because it was exposed in DLL, even though not used anymore).
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
From what I have learned they are rendered in an order (forget if lowest to highest or highest to lowest), they come in 2 sizes (standard, and extended variant), and the standard variant has a well defined structure shared with all tilesets.

There is probably a lot of hard-coded tests used to determine how each of the 4*4 tiles map into actual texture coordinates used by the shaders. These tests probably only needed to be run once as the resulting coordinates can then be cached for future rendering.

This describes tile texture layout. Not sure if it is correct but is what I am basing my answer on and you probably already know of it.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I wasn't aware of that page, thanks.

What do you mean by order? there is some order in which they are blended (e.g. snow above dirt), but I don't see what determines this order (placement in the tileset?)

I wonder what the requirements for this blending will be, it seems like a headache.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
but I don't see what determines this order (placement in the tileset?)
From what I have heard placement in the tileset list is exactly what determines the blend order. Blight is a special case given a hard-coded position (I think it is always on top of all other tiles).

Water is very simple and appears nothing more than wrapping a sequenced texture per tile area. The waves water generates on shore lines is not so simple, I am not sure what calculation is used for that.

Judging by how WC3 handles lighting and the recorded metrics when you load maps there is a good chance the terrain meshes are broken into smaller meshes. Enough of these are then rendered to fill the screen with the remainder not being loaded. Judging by how the editor performs when panning very large maps there is additional information computed the first time each mesh is viewed which is cached for subsequent views.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Terrain textures are now applied properly.
I added also the random tiles, although it's just based on arbitrary numbers I chose (20%). Are there known numbers that the game uses? Different chances for different types? (e.g. different grass, grass + rocks, grass + bones)

Does anyone know how cliffs and ramps work?

On a side note, WebGL is really bad at rendering. The main offender to FPS seems to be the amount of draw calls, which is quite small (generally <600, a huge percentage of that taken by only a few silly models like the human town center).
I can't think of any way to reduce the draw calls more though.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
It's not actually related to JS, but rather to the WebGL implementation.
The JS side pretty much always takes close to 100% of browser time when animations are running, but after some previous optimizations this doesn't seem to affect the FPS much anymore (profiling JS is pretty weird in projects like these that involve many aspects of it plus the GPU).
Right now the FPS is really noisy. If I disable just the actual render calls, it's stable 60FPS, so there you have it.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I am pretty sure they know! Maybe it will get better with WebGL 2.
Many maps do run at stable 60FPS, it's mostly the ones with silly models like TownHall that don't.
Just for some general statistics based on nothing (we all love those!), the terrain has as many calls as the tileset size (so like 6-10 usually?), doodads are usually 1-2 calls, and units tend to be anywhere between 6 (normal units) and 40+ (silly models like TownHall and HumanTower).

On a side note, cleaned lots of the viewer code, and removed some old stuff that wasn't usable in ages (color selection, and saving/loading scenes).
If selection will ever be needed, it should use the game data (aka bounding shapes).
As to scenes, I am not sure if it's worthwhile anymore (or ever was).

The map can now actually be changed again, since I removed errors that happened when a map unloaded.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
If you mean changing team colors/glows, those are now handled by the shader and don't require textures.

By scenes I mean that thing where you could have saved the current setup as an url and later on load it. You know, that thing that was used by literally no one but me when testing it.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Yeah, that's generally the gist of every change I did to the viewer itself for quite some time now.
I am just removing more and more old weird unrelated stuff that shouldn't be a part of it.
It's becoming a much more minimal resource management library and an event propagator.
All of these things had to be a part of it in the past, because the client had far less access, but now that the client has access to almost everything, there's not much of a point to have these things as a part of the viewer.
 
Level 49
Joined
Apr 18, 2008
Messages
8,451
Terrain textures are now applied properly.
I added also the random tiles, although it's just based on arbitrary numbers I chose (20%). Are there known numbers that the game uses? Different chances for different types? (e.g. different grass, grass + rocks, grass + bones)

They're hand-placed in the editor. The user can actually use specific variations iirc. Or maybe not, that might only work for doodads, but either way it doesn't randomize each time, it's set in the map.
 
Top