There are only a handful of commands you need to understand before you can start playing with 3D. Blizzard’s default objects have a lot of built-in functionality and this can really simplify the process. At the same time, most of that functionality is hidden, so you can’t modify it. If it does something you don’t want it to, you have to deal with it. Fortunately, I haven’t come across any game-breakers that can’t be overcome with a little creative thinking.
Let’s start with the 3D objects you’ll be using. These are “widgets” used in your XML document. They’re used to define an object on your screen. Normal widgets are frames, buttons, textures, etc. There are also (at least) three 3D widgets.
Model:
Model is the standard 3D model object. It inherits all the functionality from the Frame and LayoutFrame widgets (go, go object oriented programming!)
You’d think that model is the ideal widget for just about everything in World of Warcraft, and indeed it is for most, but I couldn’t get anything to look right just using Model. If I loaded a model it would be completely lacking textures and, well, look like crap. If you need a hideous stark white drake or something, then go with Model. It’ll get the job done. As far as I can tell, there are no known public ways to apply a texture to a 3D model using this widget.
What Model lacks in texture application, it more than makes up for in other areas like lighting, position, and rotation. Fortunately, all that functionality is lent to the more useful widgets below.
PlayerModel:
PlayerModel inherits everything Model can do and has some hidden functions that help with displaying player models (I presume anyway.) Blizzard uses the PlayerModel object to create, you guessed it, your player model when viewing your character screen.
The cool thing about PlayerModel is that it automatically loads the correct textures and animation for the model you’re loading. PlayerModel was my holy grail. All of sudden my drakes weren’t stark white and stupid. They were evil, dark, and brooding. They flapped their wings in a threatening manner. Perfect!
Just because the object is called PlayerModel doesn’t mean you have to use it for player models. You can load any model in World of Warcraft using this object. Best thing since sliced bread? Almost.
DressUpModel:
DressUpModel inherits everything that PlayerModel can do but also adds a few really cool new features. DressUpModel is used in Blizzard’s dress up frame and can be used to add any kind of armor, weapon, or tool to the model you have loaded. This is one of the most exciting objects because there are enormous possibilities in its use.
Functions:
Now that you know the three main 3D widgets, it’s time to get an overview of their use. Remember, anything that Model can do, PlayerModel and DressUpModel can do too.
Model:AdvanceTime()
Honestly, I don’t know exactly what this command does. I believe it resets the time for the GetTime() function. GetTime() (again, just speculating here) is used to measure the amount of time since the last AdvanceTime() call.
Initially, I thought Model:AdvanceTime() had something to do with sequences (animation), but now I don’t believe that to be the case. I’m sure it won’t take long for someone to chime in with the correct usage.
Model: ClearFog
No idea what this does, but you can probably guess it’s used to clear the scene of fog. Fog is generally used to speed up calculations (and framerates.) Anything past the fog won’t be rendered and the program will run smoother.
Model:ClearModel
I never used this, but it can be assumed that when you want to clear your widget, you’d use this routine.
Model:GetFacing()
Probably used to get the direction that the model is facing. This can be handy if your trying to animate a character in a certain direction. I don’t know if the function returns the result in degrees or radians.
Model:GetPosition()
This returns your model’s Z position. More on Z below. I wonder if you can get all the position variables if you ask for them?
Model:GetScale()
This returns your model’s scale. Scale is used to set the size of your model. A scale size of 1.0 is the normal size. You can turn your chicken into Chickzilla by setting the scale to some crazy number. Note that the size of the model is limited by the size of the frame you have it in. If your chicken is in a tiny 32x32 frame, when you expand him to legendary size, all you’ll likely see tiny portion of a enormous feather attached to an enormous wing, attached... you get the idea. If you want a giant chicken, you need to have a giant frame to house him.
Model:ReplaceIconTexture(“texture”)
No clue.
Model:SetAlpha()
Alpha is how transparent or opaque your model is. You can easily turn your healthy chicken into a chicken ghost by lowering his alpha level. It’s the trick Blizzard (and every other game company in the world) uses to make ghosts. Valid ranges are from 0.0 (completely invisible) to 1.0 (completely opaque).
Model:SetCamera(index)
This changes the camera viewing your model. The default camera is slightly at an angle and you can change this by changing the camera index. Generally, you’d set the camera to a neutral position (straight ahead) and rotate your model how you want it to look if the default doesn’t suit you.
Model:SetFacing(facing)
I guess this sets your model’s direction. But I don’t know if accepts facing as a degree of rotation or a radian.
Model:SetFogColor()
If you’re using fog, you can set the color using this command. Color is probably set by 3 different values (maybe 4 if they’re using alpha), so experiment with this. I’d guess that Model:SetFogColor(1.0, 1.0, 1.0) would make your fog completely white. You might try Model:SetFogColor(1.0, 1.0, 1.0, 0.5) to see if you can make the fog thicker or thinner by setting an alpha value.
Model:SetFogFar(value)
This is most likely used to set the furthest distance that fog is shown.
Model:SetFogNear(value)
This will set how close the fog is to your view. The further you move this back, the further fog will appear to start on your view. Move it closer to get that Silent Hill feeling.
Model:SetLight
(enabled[,omni,dirX,dirY,dirZ,ambIntensity[,ambR,ambG,ambB
[,dirIntensity[,dirR,dirG,dirB]]]])
Okay, this one is going to be tough to explain. I’ve only experimented with this a little, but I think I can give you enough information to get you up and running with lighting.
First of all, whenever a model is shown in the UI, it has balanced lighting. This is called ambient light. You can light the entire model evenly by only using ambient light which is the default.
Ambient light is good and all, but it’s not very realistic. Everything looks kind of flat.
You can set a more dramatic lighting mode using the above command.
Directional light appears to come from one direction. By moving the direction the light appears to come from, you can get some pretty satisfying results. Let me step through the various values in this command to give you a better idea how to use them. Remember, I had no documentation when I messed around with this, so my observations might be less than perfect.
enabled: This specifies if lighting is to be used on this model or not. Generally, you can’t turn it off because the model then appears black (apparently, the default ambient light won’t reset after using the command) so this has to be “1” if you’re going to use custom lighting.
omni: I have no idea what this does. It should be a true or false value like enabled which would mean, “Use ambient light on this object?” Matter of fact, that must be what it does, but I never got it to work right. Being able to manually change the ambient light would be a welcome skill.
dirX, dirY, dirZ: These set the direction for where your light is coming from. X is the horizontal plane, Y is the vertical plane, and Z is the depth plane. If you wanted a low light in front of the model (like a flashlight pointing up at someone’s chin) then you’d set a negative Y value, and a negative Z value. That would move the light below and towards you. Keep in mind when setting the lighting direction, that it might not move logically if your view is skewed. What I’m saying is that if your camera is looking at the model at an angle, your X, Y, and Z positions might not be how you imagine them. Either experiment until you get it right (like I do) or do the smart thing and figure out how it relates to your model’s facing direction.
ambIntensity: This should set how bright your model appears uniformly. If you max it out, your model should turn pure white, but I never got it to work right.
ambR, ambG, ambB: This sets your ambient light’s color. If you want your model to have a green tint, make sure that ambG is 1.0. If you want it to look white, set ambR, ambG, and ambB all to 1.0. More on colors below.
dirIntensity: This sets how bright your directional light is. This is not a uniform setting. Meaning, your light will appear brighter if it’s closer to your model and dimmer if it’s further away. Light that is further from your model needs higher intensity. Think of intensity on how far the light travels. If your light source is far away, and your intensity is low, your model will be dim.
Model:SetModel(“file”)
This is a great command. This allows you to load any model you want into the UI. You can either set the location to a file in your Addon’s directory, or you can even set it to load one of Blizzard’s models from within the MPQ archive.
For example:
Model:SetModel
("World/Generic/PassiveDoodads/TreasurePiles/GoldPileLarge01.m2");
That will load a treasure pile model from within Blizzard’s MPQ. No additional configuration needed.
Model:SetPosition(z, x, y)
Okay, I’m not positive on the ordering of SetPosition. It shouldn’t be Z, X, Y. It should be X, Y, Z. It might be. You know, I’m the kind of person who just randomly changes numbers until it looks right, so try them both and see which one is right. Then get back to me. It won’t take you long to figure it out.
Right, now SetPosition sets your model’s position in the frame. X will move it side to side, Y will move it up and down, and Z will move it back and forward. This is an important command and one you’ll probably end up using a lot.
Model:SetScale(value)
This allows you to set your model’s scale. Scale is used to set the size of your model. A scale size of 1.0 is the normal size. You can turn your chicken into Chickzilla by setting the scale to some crazy number. Note that the size of the model is limited by the size of the frame you have it in. If your chicken is in a tiny 32x32 frame, when you expand him to legendary size, all you’ll likely see tiny portion of a enormous feather attached to an enormous wing, attached... you get the idea. If you want a giant chicken, you need to have a giant frame to house him.
Model:SetSequence(sequence)
Oh boy. This was one of the most difficult commands for me to wrap my head around. In a nutshell, you can set a sequence (animation) for your model. Nearly every model in World of Warcraft has some kind of animation: chests open, players dance, murlocs die, etc. Most player models will have hundreds of sequences. Some of these repeat. Some don’t look right when playing them back, but most do.
Finally, SetSequence doesn’t do jack for PlayerModel or DressUpModel. I can only imagine that their default sequence is the ambient animation that they load with. When you change the sequence using SetSequence, it immediately changes back to the ambient sequence. So how do you get around it?
Model:SetSequenceTime(sequence, time)
You’d think that all this would do would set what frame the animation was up to on a particular sequence (Right? You thought that right? Good. I knew you understood me), but it actually sets the sequence too. What does all that mean?
You can animate your model in dozens of different animations using this command! You can have your murloc repeat his death animation over and over, have your sheep attack, have your gnome fly through the air, and have your ogre dance!
Wait a minute? Ogre dance? But ogres don’t dance. AH HA! That’s right. Why would the Blizzard animators spend hours and hours creating a hilarious ogre dance that you would never see? They didn’t! I’m all-in with ogres as a playable race in the expansion.
By the way, goblins dance too…
Back to topic at hand. SetSequenceTime is what you use when you want to animate your models. Don’t bother using SetSequence when your model was created as a PlayerModel or a DressUpModel because their default animation will override it on the next update.
More on how to animate in the examples.
PlayerModel:SetUnit(“unit”)
This allows you to set your model by using the unit tag. Basically, the unit tag can be yourself, your pet, party members, or your target. There is more information about units at the WOW Wiki.
Note: Since DressUpModel is derived from PlayerModel, SetUnit also works with that widget.
DressUpModel:Dress()
I believe this removes any equipped items and armor from the DressUpModel.
DressUpModel:DressUpItemLink(item)
This tells your DressUpModel to equip whatever item link you pass to the function. This has really cool possibilities when used with models that can wear items (all the player models can of course.)
General Concepts (really short):
3D Positioning:
Every 3D model has 3 points that determine it’s location in the world (or your frame.) They are X, Y, and Z. X moves your model side to side; Y moves your model up and down; Z moves your model forward and backwards.
If you move your model too close to the frame, it will become invisible. Imagine your frame as yourself looking at an object. If you move the model behind you, you can’t see it.
Colors:
Every color is made up of red, green, and blue. These are represented numerically as a number between 0 and 1. If you set red to 1, you’re setting it to the maximum amount of red possible. There are millions of combinations you can make by combining red, green, and blue. Generally, the higher the total of the three values, the brighter your color will be. If you want a bright blue for example, you’d set: 0.8 (red), 0.8 (green), 1 (blue). If you wanted a dark blue, you could try: 0.0 (no red), 0.0 (no green), 1 (lots of blue).
A final component in color setting comes from alpha. Alpha is just a transparency. It’s usually the fourth value set in a color and it’s set in the same way. From 0 (completely invisible) to 1 (completely opaque).
Examples:
In this final section, I’ll show you how to load a 3D object from my code. Keep in mind that my code is ugly and my observations are limited. However, I think it’s much better for you to have some idea than absolutely nothing to go on.
Please forgive my non-formatted code. I only have a limited content pane to work with here, and tabbing them out would cause a real mess.
How to Load a 3D Model into a Frame:
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
C:\Projects\WoW\Bin\Interface\FrameXML\UI.xsd">
<Script file="Demo.lua"/>
<Frame name="DemoFrame" enableMouse="false" parent="UIParent" hidden="true">
<Frames>
<PlayerModel name="ModelFrame">
<Size>
<AbsDimension x="64" y="64"/>
</Size>
<Anchors>
<Anchor point="BOTTOM" relativeTo="PlayerPortrait" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="2" y="2"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
ModelFrame:SetUnit("player");
</OnLoad>
<OnShow>
PlayerPortrait:Hide();
ModelFrame:SetUnit("player");
ModelFrame:SetScale(3.0);
ModelFrame:SetPosition(0, 0, -2.0);
</OnShow>
</Scripts>
</PlayerModel>
</Frames>
</Frame>
</Ui>
Okay, there we go. It’s that easy. Basically, what this code does is hide the default player portrait and replace it with a 3D one. This won’t look exactly right for you unless you’re a gnome. So you’ll likely have to play with SetScale and SetPosition to get it to look right.

How to Animate a 3D Model:
Using the above example, let’s add some animation. First of all, not all animations run smoothly using SetSequenceTime, but many of them do. To animate we need to set up a few extra things. First, we need a global variable that keeps track of the animation frame, second, we need a function in Lua that updates the sequence time with the frame.
Create a function called Demo_OnUpdate(elapsed).
function Demo_OnUpdate(elapsed)
seqtime = seqtime + (elapsed * 1000);
ModelFrame:SetSequenceTime(1, seqtime);
end
Make sure that seqtime is a global variable so it remembers what its value is between function calls.
The first line takes our global variable seqtime and adds to the elapsed time multiplied by 1000. Why 1000? Well, the OnUpdate method when applied to models sends the function the amount of time (in milliseconds) that has elapsed since the last frame update. Game designers use that time to create smooth animations and timings in games. 1000 milliseconds = 1 second. Anyway, we then take the resulting variable and move our animation sequence along.
So what is the 1 for in SetSequenceTime? 1 (if you look above at the command explanations) is the actual sequence. It identifies what animation we’re running. Generally, sequence 1 is a death animation, so you should see your character fall over dead when this is all set up and running.
Now all you have to do is put the function in the OnUpdate section, like so:
<Scripts>
<OnLoad>
ModelFrame:SetUnit("player");
</OnLoad>
<OnShow>
PlayerPortrait:Hide();
ModelFrame:SetUnit("player");
ModelFrame:SetScale(3.0);
ModelFrame:SetPosition(0, 0, -2.0);
</OnShow>
<OnUpdate>
Demo_OnUpdate(arg1)
</OnUpdate>
</Scripts>
When your model appears now, he’ll immediately die. If you want it to repeat the animation over and over, you’ll need to have it reset seqtime when it reaches a certain value.
That’s it for my article on using 3D models in World of Warcraft Addons. I hope you have learned enough to start implementing them in your own creations. Please let me know about any addons that have been started as a result of this article. It would make me all warm and fuzzy inside knowing that I was able to help you out.
If you like this guide, be sure to check out my latest World of Warcraft guide: Mastering the Warlock. I write for a living, and my warlock guide isn’t free, but it’s over 70 pages of information. If I didn’t get paid for it would have surely starved around page 43.

Home
Contact Us
Affiliates
Authors
Partners
Site Map |