3D Model Viewer

Level 28
Joined
Jul 29, 2007
Messages
5,115
So since there was never any official thread, here goes.

I am working on a complete different API and user interface that should change the viewer quite a lot (hopefully for good).
The new API should make it easy to load multiple models, move them around in any way you want, change textures on run-time (e.g. to test custom textures) and attach models to other models or nodes (e.g. attachments).
In addition, there will be no distinction between Warcaraft 3 and Starcraft 2 models, you will be able to use both of them interchangeably.

The new user interface would be a fullscreen menu that can be opened or closed via a button or key shortcut.
If you have any suggestions as to how it should look, go for it, I am no designer or artist.
The menu will be context-based. If you have multiple models, you will be able to select one and the menu will change accordingly to reflect that model.

The animation speed is going to be removed, since it's a useless and buggy feature.

Software rendering and one of the hardware rendering modes are going to be removed.
This means the viewer might not work for some people with really terrible computers for which it currently does work, but the numbers should be quite small.
If in the future I see that this affects many people, they can be re-added.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
Here's a small teaser.

Starcraft 2 models seem to be approximately 100 times smaller than Warcraft 3 ones, so they are scaled by that automatically.

The API right now is quite simple, here's the code that made the scene in the first attachment below:
JavaScript:
var zerg_wc3 = loadModel("Units/Critters/zergling/zergling.mdx");
zerg_wc3.move([-100, 100, 0]);

var zerg_sc2 = loadModel("Assets/Units/Zerg/Zergling/Zergling.m3");
zerg_sc2.move([100, 100, 0]);
zerg_sc2.rotate(0, 0, -90);

var hydralisk_wc3 = loadModel("Units/Critters/Hydralisk/Hydralisk.mdx");
hydralisk_wc3.move([-100, -100, 0]);

var hydralisk_sc2 = loadModel("Assets/Units/Zerg/Hydralisk/Hydralisk.m3");
hydralisk_sc2.move([100, -100, 0]);
hydralisk_sc2.rotate(0, 0, -90);

All the asynchronous file loading is hidden from the outside by a nice wrapper.
The new version's model is split into two. The Model structure, which is as before with some added functionality, and a ModelInstance, which is a pointer to a Model, but with additional info - a local transformation (translation, rotation, scaling) and a possible parent.
When you load a model, if that model is already loaded, it will just return a new instance of it, so there is no duplicated data.
While this sounds like magic, trying to run things (e.g. changing animations, changing textures, and so on) before the model is loaded wont do anything.
I am thinking if I should keep it this way with callbacks, or do a call queue which will fill up if you call things before the model is loaded, and then automatically apply them when the model finishes loading, because, let's face it - callbacks suck.

Shader loading is now smarter too, and everything is cached properly.

There will no longer be different url parameters for an absolute path / MPQ path / ID (p/mpq/q right now), the code will recognize each from a single parameter.

Texture overriding is implemented, but until I get direct access to the texture (they are NOT skins!) section, I can't show any meaningful example, so instead have a Warcraft 3 Zergling with the diffuse texture of a Starcraft 2 Zergling.
The code to have that effect, with the current scheme of callbacks, goes like this:
JavaScript:
var zerg_wc3 = loadModel("Units/Critters/zergling/zergling.mdx", function (model) {
  model.overrideTexture("units/Critters/zergling/Zergling.blp", "assets/textures/zergling_diffuse.dds");
});

The third image shows how you can attach a model instance to another model instance, or a model instance's node, with the following code:
JavaScript:
var peasant = loadModel("Units/Human/Peasant/peasant.mdx", function (model) {
  var shield = loadModel("f86573");
  
  // Attach to the model itself (equivalent to attaching to the Origin attachment point)
  // This can be used also before peasant finishes loading
  shield.setParent(model);

  // Attach to the 4th attachment point, which corresponds to the left hand for the peasant model
  // This must be used after peasant finished loading
  shield.setParent(model.getAttachment(3));
});
Note how you have to wait for the first model to actually load before you can get the attachment if you want to attach to nodes (which is the main usage of this feature), which makes loading slower since meanwhile you could have started getting the second model already.
An action queue of sorts could possibly solve this, as I stated above.

There are still many things to rewrite in nicer ways, and finally an API is needed for the outside layer, or in other words, what the user interface interacts with.
 

Attachments

  • models.jpg
    models.jpg
    300.9 KB · Views: 1,075
  • override.jpg
    override.jpg
    331.5 KB · Views: 449
  • attachments.jpg
    attachments.jpg
    285.4 KB · Views: 466
Last edited:
Good luck on updating the viewer.

As for the current one, there is a slight issue loading textures (not technically a 'bug'). There are some models who use a path such as "Textures\<Texture Name>.blp", which means that wc3 will look under the "Textures" directory. But when it is uploaded to the hive, the textures are actually found in the same directory as the model.

Perhaps you could add a measure where, if the texture cannot be loaded from its actual path, the viewer will look within the model's directory itself. Here are two examples of models in our db that show up as black because their textures have paths for the "Textures" directory:
http://www.hiveworkshop.com/forums/models-530/krasus-249755/
http://www.hiveworkshop.com/forums/models-530/mounted-paladin-47461/
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
There was indeed a small error with the texture loading function (not related to paths), fixed it.
As usual, do a hard refresh (Ctrl + F5) if it still fails to work properly.

----

Now that Ralle gave me access to the texture section (I will NOT call it skin!), here's a more meaningful example of texture overriding.
Texture overriding is now per-instance, and it requires no callbacks.
JavaScript:
var mountainKing = loadModel("units/human/HeroMountainKing/HeroMountainKing.mdx");

// hiveworkshop.com/forums/skins-552/heromountainking-61742/
mountainKing.overrideTexture("replaceabletextures/heromountainking/heromountainking.blp", "opmmml");
mountainKing.move([0, -50, 0]);

// This only creates an instance, since the model is already loaded/loading
var mountainKing2 = loadModel("units/human/HeroMountainKing/HeroMountainKing.mdx");

mountainKing2.move([0, 50, 0]);

// Oops, this sets the animation for the model, so it affects both instances
mountainKing.setAnimation(0);

I am working on the action queue to remove the need for callbacks also for other things (already done for setAnimation as can be seen above), but it's proving tricky for setParent. I don't know if I should make a setParentNode method that will take care of the tricky part, or make even weirder behind-the-scenes things.

In addition, I suddenly realized my code is all wrong. Model instances are really shallow wrappers right now, but in reality, they need to incorporate the model's skeleton, animation timers, and really any data that changes. Otherwise, how would you run different animations on different instances?
This will require quite a lot of code redesigning.
 

Attachments

  • override.jpg
    override.jpg
    289.4 KB · Views: 289
Last edited:
Level 28
Joined
Jul 29, 2007
Messages
5,115
So after a lot of hair tearing and frustrations, I finally managed to make everything work for MDX files. I ended up restructuring almost all of the old viewer's code.
I still didn't work on M3, but knowing the format, it should probably be a lot easier and faster.

Here's a new teaser - dwarven wings. :)


JavaScript:
var modelPath = "units/human/HeroMountainKing/HeroMountainKing.mdx";
var oldTexture = "replaceabletextures/heromountainking/heromountainking.blp";
var newTexture = "opmmml";

var mountainKing = loadModel(modelPath);
mountainKing.setAnimation(0);

var mountainKing2 = loadModel(modelPath);
mountainKing2.setAnimation(0);
mountainKing2.setParent(mountainKing, 4);

var mountainKing3 = loadModel(modelPath);
mountainKing3.setAnimation(0);
mountainKing3.setParent(mountainKing2, 4);

var mountainKing4 = loadModel(modelPath);
mountainKing4.setAnimation(0);
mountainKing4.setParent(mountainKing, 2);

var mountainKing5 = loadModel(modelPath);
mountainKing5.setAnimation(0);
mountainKing5.setParent(mountainKing4, 2);

// Overrides the texture for the model itself, this affects all instances
modelCache[modelPath].overrideTexture(oldTexture, newTexture);

// Overrides the texture just for the first instance
mountainKing.overrideTexture(newTexture, oldTexture);

var blade = loadModel("4fkwk3");
blade.setParent(mountainKing, 2);

var blade2 = loadModel("4fkwk3");
blade2.setParent(mountainKing, 4);
 

Attachments

  • teaser.jpg
    teaser.jpg
    397.4 KB · Views: 336
Level 28
Joined
Jul 29, 2007
Messages
5,115
Working on M3 was indeed a breeze compared to MDX, though there is an issue.
Since M3 models are scaled by 100, it means that if you attach something to them, that something is scaled by 100 too, and chaos ensues.
I am not sure how to solve this yet.

Time to work on the actual API.
What would you guys want in terms of configuration and information?
E.g. set animations, override textures, load models, parent models to other ones...
Should I do more complicated things like list all the currently loaded models, instances and textures, or if not loaded, their loading status? show model node hierarchies? anything else?

If you want something, this is the time to suggest it!
 

Attachments

  • teaser.jpg
    teaser.jpg
    364.4 KB · Views: 326
Level 28
Joined
Jul 29, 2007
Messages
5,115
While it was made for the Hive, it's a library you can use wherever you want, assuming you can supply required links to get the files.

It is hosted on github. The version there is the same as what's on the Hive right now (except for a tiny fix I didn't bother pushing).

url.js is used to get the paths of MPQ files and such, and this depends on the server.
For example, if the viewer calls url.mpqFile("path/to/some/model.mdx"), then you must return an url that will lead to that model.
For images, PNG images are expected when requesting BLP files (or really any format the browser understands and has alpha channels, PNG is the safest), and DDS files should be given as-is.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
Yes, all of that exists, though I am waiting with the scene-sharing until I know what you people want to share.

Any information about the models etc. that anyone would like to see?
Should bounding shapes be per-instance, or global?
And so on...come on people, use your imagination, because I have none.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
There's an option to draw the bounding shapes of models, as in cubes/spheres/whatever shapes that bound the model's geometry.
They are used in the games for selecting units, collision detection, etc.

On a side note, I did a small change in the M3 loading that makes it load noticeably faster, and probably render a little faster too.
 
Level 24
Joined
Jan 25, 2011
Messages
2,294
Alright I have a small suggestion.

Right now when you choose an animation to be played you cannot play the same animation again before another has been chosen.
It would be nice if you could fix that.

Also perhaps add a loop effect so the same animation can be played over and over again without having to click?

Anyway.
Just small annoyances.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
Alright I have a small suggestion.

Right now when you choose an animation to be played you cannot play the same animation again before another has been chosen.
It would be nice if you could fix that.

Also perhaps add a loop effect so the same animation can be played over and over again without having to click?

Anyway.
Just small annoyances.

Uhm, both of those features exist.
To restart an animation, press on the skeleton hand icon next to the animation list. To force animation looping for animations that don't loop (e.g. attack), set the looping mode to "Always".
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
Ok, the new version of the API is as follows.


  • loadModel(source) - Load a model.
    Source can be an absolute path to a MDX/M3 file, a path to a MDX/M3 file in any of the Warcraft 3 and Starcraft 2 MPQs, or a model ID used by the Hiveworkshop.
    Returns the ID of the loaded model.
    Note: if a model was already loaded from the given source, its ID will be returned.
  • loadInstance(source) - Create a new instance from an existing model or instance, or a path that will be used to load also the model if needed.
    If source is a string, it can be an absolute path to a MDX/M3 file, a path to a MDX/M3 file in any of the Warcraft 3 and Starcraft 2 MPQs, or a model ID used by the Hiveworkshop.
    If source is a number, it can be an ID of a model or an instance.
    Returns null if given an invalid ID, otherwise returns the ID of the created instance.
    Note: if the source is a string, and a model was already loaded from that string, only a new instance will be created.
  • setPosition(objectId, v) - Set the position of an instance.
  • move(objectId, v) - Move an instance.
  • setRotation(objectId, v) - Set the rotation of an instance.
  • rotate(objectId, v) - Rotate an instance.
  • setScale(objectId, n) - Set the scale of an instance.
  • scale(objectId, n) - Scale an instance.
  • setParent(objectId, parentId, attachmentId) - Set the parent of an instance to another instance, with an optional attachment point ID owned by that parent.
  • setTeamColor(objectId, teamId) - Set the team color used by an instance.
  • overrideTexture(objectId, oldPath, newPath) - Override a texture of an instance or a model with another texture.
    If objectId is an instance, overrides the texture locally just for that instance.
    If objectId is a model, it overrides the texture for the model, which affects all instances that don't explicitly override this texture.
  • playAnimation(objectId, animationId) - Set the animation of an instance.
  • stopAnimation(objectId) - Stop the animation of an instance.
    Equivalent to playAnimation with animation ID -1.
  • setAnimationLoop(objectId, mode) - Sets the animation loop mode of an instance.
    Possible values are 0 for default, 1 for never, and 2 for always.
  • getSequences(objectId) - Get a list of the sequences owned by a model.
    Returns null if the object ID is invalid or not a model, or if the model didn't finish loading.
  • getCameras(objectId) - Get a list of the cameras owned by a model.
    Returns null if the object ID is invalid or not a model, or if the model didn't finish loading.
  • applyCamera(objectId, cameraId) - Apply a camera of an instance.
    When an instance camera is applied, the main camera is disabled.
    If the given object ID is -1, the instance camera is disabled and the main camera becomes active.
  • setScene(mode) - Set the drawn scene.
    Possible values are 0 for nothing, 1 for sky, 2 for sky and ground, and 3 for sky and water.
  • showBoundingShapes(b) - Shows or hides the bounding shapes on all the instances.
  • panCamera(x, y) - Pan the camera on the x and y axes.
  • rotateCamera(x, y) - Rotate the camera on the x and y axes.
  • zoomCamera(n) - Zoom the camera by a factor.
  • resetCamera() - Reset the camera back to the initial state.


Notes:
  • A model is a heavy object that holds all the big data structures, such as the vertices and animation data.
  • An instance is a light-weight object that holds a skeleton, the selected team color, the selected animation, and so on.
  • If a model is loaded from an ID, it will automatically override its textures with custom ones if those exist.


Anything missing? Anything else anyone would like?

I will probably add some more information getting functions like getTextures, getLoadedModels, getLoadedInstances, etc., if anyone would want to see that information.
 
Last edited:
Level 28
Joined
Jul 29, 2007
Messages
5,115
getSequences is there for the animations (both MDX and M3 call them sequences).

I decided to make a better callback messaging system than what is used now to show the status of loading the model/textures, so this removes the need for things like getting a list of textures or models.
The client will give the viewer one callback, and it will be repeatedly called whenever a model/texture begins loading, finishes loading (whether with an error, or successfully), and for progress messages when possible.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
A small performance test. At the end whether the viewer would run smooth obviously depends on one's graphics card, but the viewer's code seems to be pretty efficient too.

On a side note, maybe I'll implement antialiasing at some point, the specular highlights look horrible from a distance.
 

Attachments

  • teaser.jpg
    teaser.jpg
    420.6 KB · Views: 145
Last edited:
Level 28
Joined
Jul 29, 2007
Messages
5,115
I updated the public github repo with the new code.

I removed applyCamera and getCameras because they seem like a useless feature to me.
Would anyone miss the feature to set the view to a model's built-in camera?

Other then that, the viewer library is mostly done, with some minor things to add or change.

I am still not exactly sure how to design the new user interface, but I'll try some things out.
 

Ralle

Owner
Level 67
Joined
Oct 6, 2004
Messages
9,486
Meh, cameras. I suppose one place where they would be useful is if looking at a unit portrait, but that is all.

I would like if you have two scripts.

script 1: the core of this viewer: functions to add models, textures, play animations, pan, zoom.
script 2: your javascript in the /model_viewer/ page.

My goal is to have something easily embeddable in any context as long as a canvas is present. I mean, it would not necessarily come with any visible UI.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
I would like if you have two scripts.

script 1: the core of this viewer: functions to add models, textures, play animations, pan, zoom.
script 2: your javascript in the /model_viewer/ page.

My goal is to have something easily embeddable in any context as long as a canvas is present. I mean, it would not necessarily come with any visible UI.

That's already how it is.
The only Hive-specific part is as usual url.js, and I might just make it another argument of model viewer to take that out too. Yeah come to think about it, I'll just do that.

/Edit
Updated the repo with the above change, the viewer is truly independent now (also actually implemented team colors, forgot all about them).

New API functions:
  • getModelFromInstance(objectId)] - Return the model ID that an instance points to.
    Returns null if the given ID is invalid or is not an instance.
  • getModelFromPath(path)] - Return the model ID that was loaded with the given path
    Returns null if no model was loaded from the given path.

Planned features for the (hopefully) close future:
  • A ray casting function to easily pick instances.
  • Ease the requirements of SC2 models by falling back to PNG images instead of DDS images if the client can't support them (this means the textures will take x4 GPU memory, but at least it would work).
  • Re-add a function to set the shader that will be used for SC2 model rendering (not sure if this actually interests anyone).
  • Add touch events for mobile devices.
  • Got something to suggest? go for it.
 
Last edited:
Level 28
Joined
Jul 29, 2007
Messages
5,115
Here's a small demo. The main menu is hidden currently because I still need to work on it some more, and I also disabled the textures panel (which allows to override textures) for now, because the long names caused the menu to be way too big.

Code:
http://www.hiveworkshop.com/model_viewer/dev/?s=[[41,-41,377],[315,212],2,0,1,0,[[0,%22178202%22],[1,0,0,0,[0,0,0],[0,0,0,1],0.4,3,1,0],[0,%22Assets/Units/Zerg/Zergling/Zergling.m3%22],[1,2,12,2,[0,0,0],[0,0,0,1],1,-1,-1,0]]]

(can't link directly, because vB ruins the url)
 
Last edited:
Level 28
Joined
Jul 29, 2007
Messages
5,115
Updated the above demo, almost everything is enabled now.

I am not sure if toggling the menus makes sense, please comment on it (graphical design isn't exactly my strong side, if I didn't make it obvious so far).

The textures panel takes way too much room in both directions, not sure what to do with it.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
Changed the user interface significantly - the instances tab is now default, and pressing on an instance name will open all its options.
Still not a very good design, but I think it's getting better.

Code:
http://www.hiveworkshop.com/model_viewer/dev/?s=[[41,-41,377],[315,212],2,0,1,0,[[0,%22178202%22],[1,0,0,0,[0,0,0],[0,0,0,1],0.4,3,1,0],[0,%22Assets/Units/Zerg/Zergling/Zergling.m3%22],[1,2,12,2,[0,0,0],[0,0,0,1],1,-1,-1,1]]]
 
Level 43
Joined
Apr 18, 2008
Messages
8,117
Being able to view from a model's camera, as well as being able to switch to the "_Portrait" version of a model, would be very useful features.
Also, the SC2 rendering seems a little... Off, to me. I'm not sure if it's just the lack of anti-aliasing, but the models look nothing like they do in the game, or in the editor. They look too dark and smooth and shiny.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
Being able to view from a model's camera, as well as being able to switch to the "_Portrait" version of a model, would be very useful features.
Also, the SC2 rendering seems a little... Off, to me. I'm not sure if it's just the lack of anti-aliasing, but the models look nothing like they do in the game, or in the editor. They look too dark and smooth and shiny.

For SC2 models, the rendering is largely a guess and trying to emulate old shaders from the game MPQs, so don't expect the same results (especially since nobody (I am looking at you BlinkBoy) is continuing to crack the format). There are also no model lights implemented, just one static light in the sky.
Also check if all the textures actually loaded - for some reason I could never figure out, sometimes DDS textures just stop loading in the middle, and this messes up rendering.

About portraits - we changed the way that model metadata is given, so instead of a model ID the thread ID is now used, and all the resources in the thread are inputs, including the portrait if one exists.
However, I am not sure how to incorporate this into the current scheme of instances.
Would the portrait belong to the same instance? that makes sense. However what if you open a SC2 resource that has in it multiple unrelated models?

You think the camera option was useful? it mostly confused people as to why they suddenly can't move around.
 
Level 43
Joined
Apr 18, 2008
Messages
8,117
For SC2 models, the rendering is largely a guess and trying to emulate old shaders from the game MPQs, so don't expect the same results (especially since nobody (I am looking at you BlinkBoy) is continuing to crack the format). There are also no model lights implemented, just one static light in the sky.
Also check if all the textures actually loaded - for some reason I could never figure out, sometimes DDS textures just stop loading in the middle, and this messes up rendering.

About portraits - we changed the way that model metadata is given, so instead of a model ID the thread ID is now used, and all the resources in the thread are inputs, including the portrait if one exists.
However, I am not sure how to incorporate this into the current scheme of instances.
Would the portrait belong to the same instance? that makes sense. However what if you open a SC2 resource that has in it multiple unrelated models?

You think the camera option was useful? it mostly confused people as to why they suddenly can't move around.

Camera + Portrait is pretty much necessary, I think.
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
Ok, so what I ended up doing was add a loadResource function that blindly loads all the models and textures from a resource (a resource in this case is a relative path, MPQ path, or thread ID of any of the models/textures/SC2 resource sections).
loadResource can't return any instance IDs immediately for obvious reasons, so now also instance loads send an event.
This means the code is no longer nice and synchronous, but what can I do...at the end it isn't real time no matter what I do to hide the fact.

When you save the scene, the resource information is discarded, and you just get the actual loaded models and instances.
Since this discards the metadata, it also means the saved scene now must include all the custom textures (but this was supposed to be this way either way to support saving overrided textures), which sadly makes the scene text huge.
You can save a scene via Options -> Scene -> Save, it will generate a copy-n-paste url.

I also added a visibility modifier so you can hide things you don't want to see.

I changed quite a few things that were probably cached by your browsers, so you should hard refresh (Ctrl + F5).

(also note that the previous links I posted are no longer valid)

http://www.hiveworkshop.com/model_v...1,4,1,12,2,[0,0,0],[0,0,0,-1],1,-1,-1,0,{}]]]

/Edit

Finally added error reporting via the messaging system, though the user interface only shows errors for model/texture loading. I still need to add more error reporting (e.g. if shaders fail to compile), and mostly to add a way to see these other errors via the user interface.
Updated the github readme with how the API and messaging system looks like right now, hopefully it will be readable.
 
Last edited:
i have some suggestions.. dont know if any of those were already suggested since i didnt read everything here, if that's the case you can ignore them:

- event objects: create a library with the MPQ footprints, spawned effects and ubersplats so they do appear in the model preview.. sounds aren't so important, but would be quite nice to have them too. the previewer could load only the effects used by the current model so it isnt bulky

- moving model space: make the model move in space along with the camera when the model is walking (with the preset walking speed or with a default speed in case it isnt there). that would make particles, ribbons and some spawned effects show correctly along the model's path

- day/night lighting: i dont care much about this one, but it would be a fancy addition :p

- head facing/turret facing: that body-part facing thing... a way to show how a model performs when it's a building facing a target or cinematic body-part animation. kinda irrelevant too, just in case you're bored and feel like implementing it :v
 
Level 28
Joined
Jul 29, 2007
Messages
5,115
i have some suggestions.. dont know if any of those were already suggested since i didnt read everything here, if that's the case you can ignore them:

- event objects: create a library with the MPQ footprints, spawned effects and ubersplats so they do appear in the model preview.. sounds aren't so important, but would be quite nice to have them too. the previewer could load only the effects used by the current model so it isnt bulky

- moving model space: make the model move in space along with the camera when the model is walking (with the preset walking speed or with a default speed in case it isnt there). that would make particles, ribbons and some spawned effects show correctly along the model's path

- day/night lighting: i dont care much about this one, but it would be a fancy addition :p

- head facing/turret facing: that body-part facing thing... a way to show how a model performs when it's a building facing a target or cinematic body-part animation. kinda irrelevant too, just in case you're bored and feel like implementing it :v

I don't know how event objects work, care to elaborate? I don't see any sound references in the format.

I thought about adding movement along the ground, but that's for later on, if I'll ever add it (at the very least after I implement ray casting for selections with the mouse).

I am not sure how convincing a night could be, since all the lighting is fake and not really related to either WC3 or SC2.

How does facing work in-game? You make an attachment point face another one (possibly on a different model)? Or any node?
 
I don't know how event objects work, care to elaborate? I don't see any sound references in the format.
event objects are helpers (points/nodes) that spawn external models that are in the MPQ. they work with a notetrack that has an empty keyframe whenever the object is supposed to be spawned. which object is to be spawned is a consequence of the node's name. you can read the Art Tools Documentation at event objects, there you have a database of all the existing event objects in the mpq. (external custom models can't be spawned with it)
sounds work just like the event objects. an empty keyframe in a notetrack. but i suppose it is harder to implement than everything else.

I am not sure how convincing a night could be, since all the lighting is fake and not really related to either WC3 or SC2.
its probably done in a cheap way, but in WC3 whether its midnight/noon alters how the model is seen.

How does facing work in-game? You make an attachment point face another one (possibly on a different model)? Or any node?
there's the 'bone_head' and 'bone_turret'. both are able to be manipulated in-game. bone_head can be used in cinematics. the bone will be rotated towards a specific point. (depending on the rig and the angle that looks bad)... dont know how exactly that is done, i assume the base rotation is looking frontwards in a 100% horizontal angle, then the second point will give the displacement necessary. the bone_turret works only with buildings and makes the bone_turret face the unit it is attacking while the rest of the model keeps still.
 
Top