Thread Tools Display Modes
10-22-13, 06:22 AM   #1
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Model tilting

I managed to tilt ingame models in the x axis like this:



However my code only works with ~45 degree tilt yet.

Lua Code:
  1. local frame = CreateFrame("Frame", nil, UIParent)
  2. frame:SetPoint("Center", 128, 0)
  3. frame:SetWidth(512 / (2 * math.sqrt(2)))
  4. frame:SetHeight(512 / (2 * math.sqrt(2)))
  5. frame:SetAlpha(1)
  6.  
  7. local model = CreateFrame("PlayerModel", nil, frame)
  8. model:SetAllPoints(frame)
  9.  
  10. local zz = 2
  11.  
  12. function ModelBasics_UpdateModel()
  13.     model:SetModel("Creature/LasherSunflower/lasher_sunflower.m2")
  14.     model:SetRotation(math.rad(0))
  15.     model:SetAlpha(1)
  16.     model:SetCustomCamera(1)
  17.     model:SetCameraDistance(1)
  18.     local x, y, z = model:GetCameraPosition()
  19.     model:SetCameraPosition(x, y, zz)
  20.     model:SetPosition(0, 0, - (zz * zz))
  21. end
  22.  
  23. ModelBasics_UpdateModel()
  24.  
  25. local frame2 = CreateFrame("Frame", nil, UIParent)
  26. frame2:SetPoint("Center", - 128, 0)
  27. frame2:SetWidth(512)
  28. frame2:SetHeight(512)
  29. frame2:SetAlpha(1)
  30.  
  31. local model2 = CreateFrame("PlayerModel", nil, frame)
  32. model2:SetAllPoints(frame2)
  33.  
  34. function ModelBasics_UpdateModel2()
  35.     model2:SetModel("Creature/LasherSunflower/lasher_sunflower.m2")
  36.     model2:SetRotation(math.rad(0))
  37.     model2:SetAlpha(1)
  38. end
  39.  
  40. ModelBasics_UpdateModel2()

Also i'm unable to create a slider for this zz (aka the tilt value) to work properly with every value from 0-90 (0-180 would be the best) degrees. Maybe someone with more experience can help me with this?

I think this would be an awsome feature for addons.

Last edited by Resike : 10-22-13 at 06:27 AM.
  Reply With Quote
10-22-13, 11:34 AM   #2
Malsomnus
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Apr 2013
Posts: 203
If I understand correctly, the problem you're describing is that you cannot actually rotate the model by 90 degrees by only controlling the Z axis, and the solution is to have the slider control the Y axis (or is it X?) as well to make sure that the camera goes in a circle around the model, with sin(Y) = sqrt (1-cos(Z)*cos(Z)) or some such equation.
I hope that that's indeed the problem you meant
__________________
SanityCheck - If you've ever said the words "Sorry, I forgot" then you need this add-on.

Remember, every time you post a comment on an add-on, a kitten gets its wings!
  Reply With Quote
10-22-13, 12:15 PM   #3
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Yeah i got it, i just have no clue how to code that now.
  Reply With Quote
10-22-13, 12:33 PM   #4
Malsomnus
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Apr 2013
Posts: 203
Say the slider moves between -180 and 180, and we call its value [i]s/I], and you have some value for camera distance because, you know, different model sizes, then you want something like:

Lua Code:
  1. local deg = s * math.pi / 180
  2. local y = math.pow (math.sin(deg), 2) * camDistance
  3. local z = math.pow (math.cos(deg), 2) * camDistance
(I think. It's been a long day.)
__________________
SanityCheck - If you've ever said the words "Sorry, I forgot" then you need this add-on.

Remember, every time you post a comment on an add-on, a kitten gets its wings!
  Reply With Quote
10-22-13, 04:41 PM   #5
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Okay, thanks for you help i managed to do it, however the tilting seems kinda weird, also the model sometimes radnomly flips 180 degrees when its tilted 0 or 90 degrees. Not sure whats causing this.

Here is my code:

Lua Code:
  1. local frame2 = CreateFrame("Frame", nil, UIParent)
  2. frame2:SetPoint("Center", - 128, 0)
  3. frame2:SetWidth(512)
  4. frame2:SetHeight(512)
  5. frame2:SetAlpha(1)
  6.  
  7. local model2 = CreateFrame("PlayerModel", nil, frame)
  8. model2:SetModel("Creature/LasherSunflower/lasher_sunflower.m2")
  9. model2:SetAlpha(1)
  10. model2:SetAllPoints(frame2)
  11. model2:SetCustomCamera(1)
  12. local x, y, z = model2:GetCameraPosition()
  13. local r = math.sqrt((x * x) + (z * z))
  14. print(x, y, z, r)
  15.  
  16. local degree = 90
  17.  
  18. local slider = CreateFrame("Slider", nil, UIParent, "OptionsSliderTemplate")
  19. slider:ClearAllPoints()
  20. slider:SetPoint("Center", UIParent, "Center", 0, 300)
  21. slider:SetMinMaxValues(90, 180)
  22. slider:SetValue(90)
  23. slider:SetValueStep(1)
  24. slider:SetScript("OnValueChanged", function(slider, value)
  25.     degree = value
  26.     ModelBasics_UpdateModel2()
  27. end)
  28.  
  29. function ModelBasics_UpdateModel2()
  30.     --model2:SetModel("Creature/LasherSunflower/lasher_sunflower.m2")
  31.     --model2:SetRotation(math.rad(0))
  32.     model2:SetCustomCamera(1)
  33.     local xx = math.pow(math.sin(math.rad(degree)), 2) * r
  34.     local zz = math.pow(math.cos(math.rad(degree)), 2) * r
  35.     model2:SetCameraPosition(xx, y, zz)
  36.     --model2:SetAllPoints(frame2)
  37. end
  38.  
  39. ModelBasics_UpdateModel2()

Last edited by Resike : 10-22-13 at 04:47 PM.
  Reply With Quote
10-22-13, 04:49 PM   #6
Malsomnus
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Apr 2013
Posts: 203
I'm a bit high on a sleeping pill at the moment, but I promise to give this a look in the morning
__________________
SanityCheck - If you've ever said the words "Sorry, I forgot" then you need this add-on.

Remember, every time you post a comment on an add-on, a kitten gets its wings!
  Reply With Quote
10-22-13, 10:06 PM   #7
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by Malsomnus View Post
I'm a bit high on a sleeping pill at the moment, but I promise to give this a look in the morning
It's okay. I think this is working nice so i'll definately use it in my addons. I might only let the slider handle 90-170 values only and then the flippings seems to be solved.
  Reply With Quote
10-22-13, 11:35 PM   #8
Malsomnus
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Apr 2013
Posts: 203
Hmmm, it looks fine... I'll have to run it myself and see what's happening, at some point after work. I hate it when real life keeps me away from coding fun stuff
__________________
SanityCheck - If you've ever said the words "Sorry, I forgot" then you need this add-on.

Remember, every time you post a comment on an add-on, a kitten gets its wings!
  Reply With Quote
10-23-13, 06:03 AM   #9
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Interesting thread. I have some model functions in my model viewer aswell.

Finding a function that allows tossing around with the cameraposition would be awesome. It would be enough if the cameraposition z-axis has a max of 180° (-90° till 90°). Thus you can look at a model from bottom to top.

model:SetRotation() will do the rest since it allows a 360° rotation of the model around its axis.

Important: Models only work when cached. The only way to display uncached models is by using SetDisplayInfo() on a playermodel type model. That's how NPCSCAN works. It checks for the model cache to determine if a rare mob model is found.

Model methods

OTHER
Model:ClearModel() - Removes the 3D model currently displayed
Model:HasCustomCamera() - This function is not yet documented

GET
Model:GetCameraDistance() - This function is not yet documented
Model:GetCameraFacing() - This function is not yet documented
Model:GetCameraPosition() - This function is not yet documented
Model:GetCameraTarget() - This function is not yet documented
Model:GetFacing() - Returns the model's current rotation setting
Model:GetModel() - Returns the model file currently displayed
Model:GetModelScale() - Returns the scale factor determining the size at which the 3D model appears
Model:GetPosition() - Returns the position of the 3D model within the frame
Model:GetWorldScale() - This function is not yet documented

SET
Model:SetCamera(index) - Sets the view angle on the model to a pre-defined camera location
Model:SetCameraDistance() - This function is not yet documented
Model:SetCameraFacing() - This function is not yet documented
Model:SetCameraPosition() - This function is not yet documented
Model:SetCameraTarget() - This function is not yet documented
Model:SetCustomCamera() - This function is not yet documented
Model:SetFacing(facing) - Sets the model's current rotation
Model:SetModel("filename") - Sets the model file to be displayed
Model:SetModelScale(scale) - Sets the scale factor determining the size at which the 3D model appears
Model:SetPosition(x, y, z) - Sets the position of the 3D model within the frame
Source: http://wowprogramming.com/docs/widgets/Model

PlayerModel model sub-methods

PlayerModel:GetDoBlend() - This function is not yet documented
PlayerModel:RefreshCamera() - This function is not yet documented
PlayerModel:RefreshUnit() - Updates the model's appearance to match that of its unit
PlayerModel:SetAnimation() - This function is not yet documented
PlayerModel:SetBarberShopAlternateForm() - This function is not yet documented
PlayerModel:SetCamDistanceScale() - This function is not yet documented
PlayerModel:SetCreature(creature) - Sets the model to display the 3D model of a specific creature
PlayerModel:SetCustomRace() - This function is not yet documented
PlayerModel:SetDisplayInfo() - This function is not yet documented
PlayerModel:SetDoBlend() - This function is not yet documented
PlayerModel:SetPortraitZoom() - This function is not yet documented
PlayerModel:SetRotation(facing) - Sets the model's current rotation by animating the model
PlayerModel:SetUnit("unit") - Sets the model to display the 3D model of a specific unit
Source: http://wowprogramming.com/docs/widgets/PlayerModel

For my purposes I could work with playermodel type models only since I could not rely on a model being cached. But I could not get a custom camera to work on it. But maybe I was missing sth who knows. Accoring to the docs a playermodel type model is a child of the model object and inherits all model functions, so custom camera should work.
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 10-23-13 at 06:43 AM.
  Reply With Quote
10-23-13, 11:09 AM   #10
Malsomnus
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Apr 2013
Posts: 203
Great point about model:SetRotation(), assuming it rotates the model itself, it solves what is normally a pretty significant problem
__________________
SanityCheck - If you've ever said the words "Sorry, I forgot" then you need this add-on.

Remember, every time you post a comment on an add-on, a kitten gets its wings!
  Reply With Quote
10-23-13, 11:56 AM   #11
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Yep i was aware pretty much any api that models have, the bad part most of them is undocumented, i would like to add some descripion for some of the function i recently tried:

Model:ClearModel() -- Works fine unless your model is set by unit ids like: Model:SetModel("player"), you can clear that with Model:SetModel("none").

Model:SetCustomCamera() -- You can enabled this with 1 parameter, not sure how to disable it, my guess would be 0.

Model:GetCameraPosition() -- Gives you the current camera's X, Y, Z axis coordinates based on 0, 0, 0 point in this order: Y, X, Z.

Model:GetCameraDistance() -- Disabled, addons cant call it (Always returns 0.). Workaround to get the same value:

Lua Code:
  1. -- Set the model first.
  2. Model:SetModel(randommodel)
  3. -- Note here x is actually the y coordinate and y is x.
  4. local x, y, z = Model:GetCameraPosition()
  5. local r = math.sqrt((x * x) + (y * y) + (z * z))

Model:SetCameraDistance() -- Works fine.

Model:SetCameraPosition(x, y, z) -- Only works with "Model:SetCustomCamera(1)", the order is Y, X, Z.

I'm actually not sure whats the difference between Model and PlayerModel, i was always using PlayerModel.

Also you're right about the "SetRotation will fix it" but when you want to handle the tilting value with an onupdate script which automatically tilts the models in like 3-4 sec in 0-90 degrees then the random flipping could be annoying.

Last edited by Resike : 11-07-13 at 11:22 PM.
  Reply With Quote
10-24-13, 05:44 AM   #12
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
I would like the tilting to be like on WoW Model Viewer or like pretty much any 3D modeller program has:

https://wowmodelviewer.atlassian.net...2898511&api=v2
  Reply With Quote
10-24-13, 06:07 AM   #13
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Regarding models. You can play different animation types. This is from the petbattle ui.
Lua Code:
  1. --petbattleui.lua
  2.         if ( C_PetBattles.GetHealth(petOwner, petIndex) == 0 ) then
  3.             self.PetModel:SetAnimation(6, 0); --Display the dead animation
  4.             --self.PetModel:SetAnimation(0, 0);
  5.         else
  6.             self.PetModel:SetAnimation(742, 0); -- Display the PetBattleStand animation
  7.             --self.PetModel:SetAnimation(742, 0);
  8.         end

Other functions from the tabardframe.lua
Lua Code:
  1. --tabardframe.lua
  2. function TabardCharacterModelRotateLeftButton_OnClick()
  3.     TabardModel.rotation = TabardModel.rotation - .03;
  4.     TabardModel:SetRotation(TabardModel.rotation);
  5.     PlaySound("igInventoryRotateCharacter");
  6. end
  7.  
  8. function TabardCharacterModelRotateRightButton_OnClick()
  9.     TabardModel.rotation = TabardModel.rotation + .03;
  10.     TabardModel:SetRotation(TabardModel.rotation);
  11.     PlaySound("igInventoryRotateCharacter");
  12. end
  13.  
  14. function TabardCharacterModelFrame_OnUpdate(self, elapsedTime)
  15.     if ( TabardCharacterModelRotateRightButton:GetButtonState() == "PUSHED" ) then
  16.         self.rotation = self.rotation + (elapsedTime * 2 * PI * ROTATIONS_PER_SECOND);
  17.         if ( self.rotation < 0 ) then
  18.             self.rotation = self.rotation + (2 * PI);
  19.         end
  20.         self:SetRotation(self.rotation);
  21.     end
  22.     if ( TabardCharacterModelRotateLeftButton:GetButtonState() == "PUSHED" ) then
  23.         self.rotation = self.rotation - (elapsedTime * 2 * PI * ROTATIONS_PER_SECOND);
  24.         if ( self.rotation > (2 * PI) ) then
  25.             self.rotation = self.rotation - (2 * PI);
  26.         end
  27.         self:SetRotation(self.rotation);
  28.     end
  29. end
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 10-24-13 at 06:10 AM.
  Reply With Quote
10-24-13, 06:58 AM   #14
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
I didn't meant that but if you compare the tilting from WoW model viewer and my my code then you can see my method still have some zooming/scaling issues.

Edit: I fixed that now:

Lua Code:
  1. local frame2 = CreateFrame("Frame", nil, UIParent)
  2. frame2:SetPoint("Center", - 128, 0)
  3. frame2:SetWidth(512)
  4. frame2:SetHeight(512)
  5. frame2:SetAlpha(1)
  6.  
  7. local model2 = CreateFrame("PlayerModel", nil, frame2)
  8. model2:SetModel("Creature/LasherSunflower/lasher_sunflower.m2")
  9. model2:SetAlpha(1)
  10. model2:SetAllPoints(frame2)
  11. model2:SetCustomCamera(1)
  12. local x, y, z = model2:GetCameraPosition()
  13. local r = math.sqrt((x * x) + (z * z))
  14. print(x, y, z, r)
  15.  
  16. local degree = 90
  17.  
  18. local slider = CreateFrame("Slider", nil, UIParent, "OptionsSliderTemplate")
  19. slider:ClearAllPoints()
  20. slider:SetPoint("Center", UIParent, "Center", 0, 300)
  21. slider:SetMinMaxValues(0, 90)
  22. slider:SetValue(0)
  23. slider:SetValueStep(1)
  24. slider:SetScript("OnValueChanged", function(slider, value)
  25.     degree = value
  26.     ModelBasics_UpdateModel2()
  27. end)
  28.  
  29. function ModelBasics_UpdateModel2()
  30.     --model2:SetModel("Creature/LasherSunflower/lasher_sunflower.m2")
  31.     model2:SetRotation(math.rad(0))
  32.     model2:SetCustomCamera(1)
  33.     local xx = math.sin(math.rad(degree)) * r
  34.     local zz = math.cos(math.rad(degree)) * r
  35.     model2:SetCameraPosition(xx, y, zz)
  36.     --model2:SetAllPoints(frame2)
  37. end
  38.  
  39. ModelBasics_UpdateModel2()

This one should be much smoother.

I blame Malsomnus ofc. There is no need for math.pow here: :P

Lua Code:
  1. local y = math.pow(math.sin(deg), 2) * camDistance
  2. local z = math.pow(math.cos(deg), 2) * camDistance

Last edited by Resike : 11-07-13 at 11:23 PM.
  Reply With Quote
10-24-13, 07:59 AM   #15
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Bad news, seems like you can only set custom camera for the model if Model:HasCustomCamera() returns true.

Also managed to fix the flipping issue like this:

Lua Code:
  1. local frame2 = CreateFrame("Frame", nil, UIParent)
  2. frame2:SetPoint("Center", - 128, 0)
  3. frame2:SetWidth(512)
  4. frame2:SetHeight(512)
  5. frame2:SetAlpha(1)
  6.  
  7. local model2 = CreateFrame("PlayerModel", nil, frame2)
  8. model2:SetModel("Creature/LasherSunflower/lasher_sunflower.m2")
  9. model2:SetAlpha(1)
  10. model2:SetAllPoints(frame2)
  11. model2:SetCustomCamera(1)
  12. local x, y, z = model2:GetCameraPosition()
  13. local r = math.sqrt((x * x) + (z * z))
  14. print(x, y, z, r)
  15. print(model2:HasCustomCamera())
  16.  
  17. --model2:SetLight(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
  18.  
  19. local degree = 90
  20.  
  21. local slider = CreateFrame("Slider", nil, UIParent, "OptionsSliderTemplate")
  22. slider:ClearAllPoints()
  23. slider:SetPoint("Center", UIParent, "Center", 0, 300)
  24. slider:SetMinMaxValues(0, 90)
  25. slider:SetValue(0)
  26. slider:SetValueStep(1)
  27. slider:SetScript("OnValueChanged", function(slider, value)
  28.     degree = value
  29.     ModelBasics_UpdateModel2()
  30. end)
  31.  
  32. function ModelBasics_UpdateModel2()
  33.     --model2:SetModel("Creature/LasherSunflower/lasher_sunflower.m2")
  34.     --model2:SetRotation(math.rad(0))
  35.     model2:SetCustomCamera(1)
  36.     local xx = math.sin(math.rad(degree)) * r
  37.     local zz = math.cos(math.rad(degree)) * r
  38.     if xx > 0.1 then
  39.         model2:SetCameraPosition(xx, y, zz)
  40.     else
  41.         model2:SetCameraPosition(0.1, y, zz)
  42.     end
  43.     --model2:SetCameraTarget(0, y, 0)
  44.     --model2:SetAllPoints(frame2)
  45. end
  46.  
  47. --model2:SetCamera(2)
  48. ModelBasics_UpdateModel2()

Last edited by Resike : 10-24-13 at 08:30 AM.
  Reply With Quote
10-24-13, 03:59 PM   #16
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
The custom camera seems to be limited to keeping the model upright, that's what's causing the sudden flipping. You may just need to cap the pitch to +/- 90 degrees (+/- pi / 2 radians). Here is what I came up with from playing around with the camera stuff today (along with many client crashes):
Code:
local MODEL = "Creature/LasherSunflower/lasher_sunflower.m2"
local MODEL_SIZE = 256
local INCREMENT_ZOOM, MAX_ZOOM, MIN_ZOOM = 0.5, 20, 1

local atan, cos, sin, sqrt, PI = math.atan, math.cos, math.sin, math.sqrt, math.pi
local INCREMENT_RADIAL, PITCH_LIMIT = PI / 180, PI / 2 - 0.023

local frame = CreateFrame('Frame', nil, UIParent)
frame:SetPoint('CENTER', UIParent:GetWidth() / 4, UIParent:GetHeight() / 4)
frame:SetSize(MODEL_SIZE + 8, MODEL_SIZE + 8)
frame:SetBackdrop({
    bgFile = [[Interface\BUTTONS\WHITE8X8]],
    edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
    tileSize = 16, tile = true,
    insets = { left = 3, right = 3, top = 3, bottom = 3 }
})
frame:SetBackdropColor(0.05, 0.1, 0.15, 1)
frame:SetBackdropBorderColor(1, 1, 1, 1)
frame:EnableMouse(true)

local model = CreateFrame('PlayerModel', nil, frame)
model:SetPoint('CENTER')
model:SetSize(MODEL_SIZE, MODEL_SIZE)

local function OnMouseWheel(self, delta)
    local distance = self.distance - delta * INCREMENT_ZOOM
    if distance > MAX_ZOOM then
        distance = MAX_ZOOM
    elseif distance < MIN_ZOOM then
        distance = MIN_ZOOM
    end
    self:SetOrientation(distance, self.yaw, self.pitch)
end

local function OnUpdate(self, elapsed)
    local x, y = GetCursorPosition()
    local yaw = self.yaw + (x - self.x) * INCREMENT_RADIAL
    local pitch = self.pitch + (y - self.y) * INCREMENT_RADIAL
    if pitch > PITCH_LIMIT then
        pitch = PITCH_LIMIT
    elseif pitch < -PITCH_LIMIT then
        pitch = -PITCH_LIMIT
    end
    self:SetOrientation(self.distance, yaw, pitch)
    self.x, self.y = x, y
end

local function OnMouseDown(self, button)
    if button ~= 'LeftButton' then return end
    self.x, self.y = GetCursorPosition()
    self:SetScript('OnUpdate', OnUpdate)
end

local function OnMouseUp(self, button)
    self:SetScript('OnUpdate', nil)
    if button == 'MiddleButton' then
        self:SetOrientation(self._distance, self._yaw, self._pitch)
    end
end

function model:Initialize()
    self:EnableMouse(true)
    self:EnableMouseWheel(true)
    self:SetScript('OnMouseDown', OnMouseDown)
    self:SetScript('OnMouseUp', OnMouseUp)
    self:SetScript('OnMouseWheel', OnMouseWheel)
    self:SetScript('OnUpdate', nil)
end

function model:LoadModel(file)
    self:SetModel(file)
    self:SetCustomCamera(1)
    self:SetCameraDistance(1)
    local x, y, z = self:GetCameraPosition()
    self:SetCameraTarget(0, y, z)
    self._distance = sqrt(x * x + y * y + z * z)
    self._yaw = -atan(y / x)
    self._pitch = -atan(z / x)
    self:SetOrientation(self._distance, self._yaw, self._pitch)
end

function model:SetOrientation(distance, yaw, pitch)
    if self:HasCustomCamera() then
        self.distance, self.yaw, self.pitch = distance, yaw, pitch
        self:SetCameraPosition(distance * cos(yaw) * cos(pitch),        -- X
                               distance * sin(-yaw) * cos(pitch),       -- Y
                               distance * sin(-pitch))                  -- Z
    end
end

model:Initialize()
model:LoadModel(MODEL)
Edit: Updated code to reflect some changes in later posts.

Last edited by Vrul : 10-27-13 at 10:05 AM.
  Reply With Quote
10-24-13, 10:56 PM   #17
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by Vrul View Post
The custom camera seems to be limited to keeping the model upright, that's what's causing the sudden flipping. You may just need to cap the pitch to +/- 90 degrees (+/- pi / 2 radians). Here is what I came up with from playing around with the camera stuff today (along with many client crashes):
Code:
local MODEL = "Creature/LasherSunflower/lasher_sunflower.m2"
local MODEL_SIZE = 256
local INCREMENT_ZOOM, MAX_ZOOM, MIN_ZOOM = 0.5, 20, 1

local atan, cos, sin, sqrt, PI = math.atan, math.cos, math.sin, math.sqrt, math.pi
local HALF_PI, INCREMENT_RATIO = PI / 2, PI / MODEL_SIZE

local frame = CreateFrame('Frame', nil, UIParent)
frame:SetPoint('CENTER', UIParent:GetWidth() / 4, UIParent:GetHeight() / 4)
frame:SetSize(MODEL_SIZE + 8, MODEL_SIZE + 8)
frame:SetBackdrop({
    bgFile = [[Interface\BUTTONS\WHITE8X8]],
    edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
    tileSize = 16, tile = true,
    insets = { left = 3, right = 3, top = 3, bottom = 3 }
})
frame:SetBackdropColor(0.05, 0.1, 0.15, 1)
frame:SetBackdropBorderColor(1, 1, 1, 1)
frame:EnableMouse(true)

local model = CreateFrame('PlayerModel', nil, frame)
model:SetPoint('CENTER')
model:SetSize(MODEL_SIZE, MODEL_SIZE)

local function OnMouseWheel(self, delta)
    local distance = self.distance - delta * INCREMENT_ZOOM
    if distance > MAX_ZOOM then
        distance = MAX_ZOOM
    elseif distance < MIN_ZOOM then
        distance = MIN_ZOOM
    end
    self:SetOrientation(distance, self.yaw, self.pitch)
end

local function OnUpdate(self, elapsed)
    local x, y = GetCursorPosition()
    local yaw = (x - self.x) * INCREMENT_RATIO
    if yaw > PI then
        yaw = PI
    elseif yaw < -PI then
        yaw = -PI
    end
    local pitch = (y - self.y) * INCREMENT_RATIO
    if pitch > HALF_PI then
        pitch = HALF_PI
    elseif pitch < -HALF_PI then
        pitch = -HALF_PI
    end
    self:SetOrientation(self.distance, yaw, pitch)
end

local function OnMouseDown(self, button)
    if button ~= 'LeftButton' then return end
    self.x, self.y = GetCursorPosition()
    self:SetScript('OnUpdate', OnUpdate)
end

local function OnMouseUp(self, button)
    self:SetScript('OnUpdate', nil)
    if button == 'MiddleButton' then
        self:SetOrientation(self._distance, self._yaw, self._pitch)
    end
end

function model:Initialize()
    self:EnableMouse(true)
    self:EnableMouseWheel(true)
    self:SetScript('OnMouseDown', OnMouseDown)
    self:SetScript('OnMouseUp', OnMouseUp)
    self:SetScript('OnMouseWheel', OnMouseWheel)
    self:SetScript('OnUpdate', nil)
end

function model:LoadModel(file)
    self:SetModel(file)
    self:SetCustomCamera(1)
    self:SetCameraDistance(1)
    local x, y, z = self:GetCameraPosition()
    self:SetCameraTarget(0, y, z)
    self._distance = sqrt(x * x + y * y + z * z)
    self._yaw = -atan(y / x)
    self._pitch = -atan(z / x)
    self:SetOrientation(self._distance, self._yaw, self._pitch)
end

function model:SetOrientation(distance, yaw, pitch)
    if self:HasCustomCamera() then
        self.distance, self.yaw, self.pitch = distance, yaw, pitch
        local x = distance * cos(yaw) * cos(pitch)
        local y = distance * sin(-yaw) * cos(pitch)
        local z = distance * sin(-pitch)
        self:SetCameraPosition(x, y, z)
    end
end

model:Initialize()
model:LoadModel(MODEL)
Quick question what does the SetOrientation do?

Thats actually really good, any chance to save the positions on mouseup and continue from there in the next click?
Also you could add the model:SetPosition(x, y, z) function to right clicking, then you have pretty much all the model functions in it.

Last edited by Resike : 10-24-13 at 11:04 PM.
  Reply With Quote
10-25-13, 10:58 AM   #18
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Originally Posted by Resike View Post
Quick question what does the SetOrientation do?
It sets the camera position based on the distance from the model, the yaw (rotation about the z-axis), and pitch (rotation about the y-axis). Since you need to know all 3 of those parameters to properly set the camera I figured one function call is better than three that would end up reproducing most of the work of each other.

Originally Posted by Resike View Post
any chance to save the positions on mouseup and continue from there in the next click?
Sure, just change the OnUpdate function to this:
Code:
local function OnUpdate(self)
    local x, y = GetCursorPosition()
    local yaw = self.yaw + (x - self.x) * INCREMENT_RATIO
    local pitch = self.pitch + (y - self.y) * INCREMENT_RATIO
    if pitch > HALF_PI then
        pitch = HALF_PI
    elseif pitch < -HALF_PI then
        pitch = -HALF_PI
    end
    self:SetOrientation(self.distance, yaw, pitch)
    self.x, self.y = x, y
end
Originally Posted by Resike View Post
Also you could add the model:SetPosition(x, y, z) function to right clicking, then you have pretty much all the model functions in it.
Maybe later. I only played around with this to get a break from my current project which I need to get back to.
  Reply With Quote
10-25-13, 11:22 AM   #19
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
I see, well the main reason i wanted this tilting because i want to use it for the project i just started too.
I was trying to make a workaround for models with model:HasCustomCamera() == false, but i failed.
  Reply With Quote
10-25-13, 12:26 PM   #20
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by Vrul View Post
It sets the camera position based on the distance from the model, the yaw (rotation about the z-axis), and pitch (rotation about the y-axis). Since you need to know all 3 of those parameters to properly set the camera I figured one function call is better than three that would end up reproducing most of the work of each other.
Oh my bad, i totally tought it's an API i missed.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Model tilting

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off