Jump to content

GetRotation C++/Lua bug


martyj
 Share

Recommended Posts

I have been testing some camera movement code, and there is a bug with getting the rotation of an Entity

 

OS: Windows 10

LE Version: Beta Branch 4.0 Professional

Graphics Card(s): AMD R9 280x, Nvidia GTX 650 TI

 

App Start

box = Model::Box(2, 2, 2);
box->SetColor(1.0, 0.0, 0.0, 1.0);
box->SetPosition(Vec3(5.0, 3.0, 0.0), true);
box->SetRotation(Vec3(57.250671f, 9.541766, 114.50135), true);

 

App Loop

if (window->KeyHit(Key::L))
{
Vec3 next_rot = Vec3(57.493263f, 9.582211, 114.986526);
Vec3 rot = box->GetRotation(true);
Vec3 diff = next_rot - rot;
box->Turn(diff, true);
//box->SetRotation(next_rot, true); // Will return the same results with GetRotation afterwards
System::Print(next_rot);
System::Print(rot);
System::Print(diff);
System::Print(box->GetRotation(true)); // Bug shows here
}

 

This will print the following

6.png

 

As you can see, the global rotation of the box changes drastically compared to the turn value.

 

I also wrote a Lua script that shows the error

 

--Initialize Steamworks (optional)
Steamworks:Initialize()
--Set the application title
title="RotateTest"
--Create a window
local windowstyle = window.Titlebar
if System:GetProperty("fullscreen")=="1" then windowstyle=windowstyle+window.FullScreen end
window=Window:Create(title,0,0,System:GetProperty("screenwidth","1024"),System:GetProperty("screenheight","768"),windowstyle)
window:HideMouse()
--Create the graphics context
context=Context:Create(window,0)
if context==nil then return end
--Create a world
world=World:Create()
world:SetLightQuality((System:GetProperty("lightquality","1")))
--Load a map
local mapfile = System:GetProperty("map","Maps/start.map")
if Map:Load(mapfile)==false then return end
box=Model:Box(2,2,2)
box:SetColor(1, 0, 0, 1)
box:SetPosition(5.0, 3.0, 0.0, true)
box:SetRotation(Vec3(57.250671, 9.541766, 114.50135), true)
while window:KeyDown(Key.Escape)==false do

--If window has been closed, end the program
if window:Closed() then break end

--Handle map change
if changemapname~=nil then

--Clear all entities
world:Clear()

--Load the next map
Time:Pause()
if Map:Load("Maps/"..changemapname..".map")==false then return end
Time:Resume()

changemapname = nil
end
if window:KeyHit(Key.L) then
next_rot = Vec3(57.493263, 9.582211, 114.986526)
rot = box:GetRotation(true)
diff = next_rot - rot
box:SetRotation(next_rot, true)
System:Print(next_rot)
System:Print(rot)
System:Print(diff)
System:Print(box:GetRotation(true))
end

--Update the app timing
Time:Update()

--Update the world
world:Update()

--Render the world
world:Render()

--Render statistics
context:SetBlendMode(Blend.Alpha)
if DEBUG then
context:SetColor(1,0,0,1)
context:DrawText("Debug Mode",2,2)
context:SetColor(1,1,1,1)
context:DrawStats(2,22)
context:SetBlendMode(Blend.Solid)
else
--Toggle statistics on and off
if (window:KeyHit(Key.F11)) then showstats = not showstats end
if showstats then
context:SetColor(1,1,1,1)
context:DrawText("FPS: "..Math:Round(Time:UPS()),2,2)
end
end

--Refresh the screen
context:Sync(true)

end

Link to comment
Share on other sites

Turn takes in a Vec3 in C++.

 

virtual void Turn(const Vec3& rotation, const bool global = false);//lua

virtual void Turn(const float x, const float y, const float z, const bool global=false);//lua

 

It's not a problem with Turn or SetRotation. The problem is with GetRotation. The object actually appears correctly in the scene when you use SetRotation.

 

The value returned from GetRotation is wrong.

Link to comment
Share on other sites

I reproduced the issue on LE stable, interesting thing is that if you change next_rot.x to 57.2, the value returned from GetRotation looks okay.

 

Also the test script crashes because

local windowstyle = window.Titlebar

W in window should be capitalized

 

I stripped out all the extra stuff, problem can be reproduced with the smaller Main.lua script below:

 

local box=Model:Box(2,2,2)
box:SetColor(1, 0, 0, 1)
box:SetPosition(5.0, 3.0, 0.0, true)
box:SetRotation(Vec3(57.250671, 9.541766, 114.50135), true)

local next_rot = Vec3(57.493263, 9.582211, 114.986526)
local rot = box:GetRotation(true)
local diff = next_rot - rot

box:SetRotation(next_rot, true)

System:Print(next_rot)
System:Print(rot)
System:Print(diff)
System:Print(box:GetRotation(true))

 

EDIT: For the love of god why wont the forum let me capitalize W in window.TitleBar? That probably explains why the original script had the problem in the first place.

Edited by thehankinator
Link to comment
Share on other sites

I suspect you have encountered a case related to Gimbal lock, where the euler is insufficient to describe a rotation. With that roll value, around 57 degrees seems to be the point where the box flips around.

 

This is actually something that caused problems in the Apollo 13 mission:

 

 

You can't add degrees to Eulers on more than one axis. The Entity:Turn command will smoothly change the rotation of the box without these issues. Press the R and T keys to rotate the box:

--Initialize Steamworks (optional)
Steamworks:Initialize()
--Set the application title
title="RotateTest"
--Create a window
local windowstyle = window.Titlebar
if System:GetProperty("fullscreen")=="1" then windowstyle=windowstyle+window.FullScreen end
window=Window:Create(title,0,0,System:GetProperty("screenwidth","1024"),System:GetProperty("screenheight","768"),windowstyle)
window:HideMouse()
--Create the graphics context
context=Context:Create(window,0)
if context==nil then return end
--Create a world
world=World:Create()
world:SetLightQuality((System:GetProperty("lightquality","1")))
--Load a map

local cam = Camera:Create()
cam:SetPosition(0,0,-5)

local mapfile = System:GetProperty("map","Maps/start.map")
if Map:Load(mapfile)==false then return end
box=Model:Box(2,2,2)
box:SetColor(1, 0, 0, 1)
box:SetPosition(5.0, 3.0, 0.0, true)
box:SetRotation(Vec3(47.250671, 9.541766, 114.50135), true)
while window:KeyDown(Key.Escape)==false do

--If window has been closed, end the program
if window:Closed() then break end

--Handle map change
if changemapname~=nil then

--Clear all entities
world:Clear()

--Load the next map
Time:Pause()
--if Map:Load("Maps/"..changemapname..".map")==false then return end
Time:Resume()

changemapname = nil
end

if window:KeyDown(Key.L) then
next_rot = Vec3(57.493263, 9.582211, 114.986526)
rot = box:GetRotation(true)
rot.x = rot.x + 1
diff = next_rot - rot
box:SetRotation(rot, true)
System:Print(next_rot)
System:Print(rot)
System:Print(diff)
System:Print(box:GetRotation(true))
end

if window:KeyDown(Key.T) then
box:Turn(0.1,0,0)
end

if window:KeyDown(Key.R) then
box:Turn(-0.1,0,0)
end

--Update the app timing
Time:Update()

--Update the world
world:Update()

--Render the world
world:Render()

--Render statistics
context:SetBlendMode(Blend.Alpha)
if DEBUG then
context:SetColor(1,0,0,1)
context:DrawText("Debug Mode",2,2)
context:SetColor(1,1,1,1)
context:DrawStats(2,22)
context:SetBlendMode(Blend.Solid)
else
--Toggle statistics on and off
if (window:KeyHit(Key.F11)) then showstats = not showstats end
if showstats then
context:SetColor(1,1,1,1)
context:DrawText("FPS: "..Math:Round(Time:UPS()),2,2)
end
end

--Refresh the screen
context:Sync(true)

end

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I think that is a euler value that is ambiguous.

 

Eulers can't be operated on in an intuitive way when you have roll in the equation. The "real" rotation Leadwerks uses is the object's quaternion, and the eulers are extracted from that. Quaternions are not intuitive in the least, there's actually a whole book on visualizing quaternions:

http://www.amazon.com/Visualizing-Quaternions-Kaufmann-Interactive-Technology/dp/0120884003

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Really the only time you will be manually inputting a rotation it's going to be an axis-aligned value likle [0,0,0], [90,0,0], etc. Otherwise you will be using Turn(). I can't think of any time you would be inputting random numbers like that.

 

If you want to copy one entity's rotation use GetMatrix / SetMatrix or GetQuaterion / SetRotation (with the quat).

 

Basically Quaternion -> Euler is a potentially lossy operation, like JPEG compression.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I am still running into issues even with turning each axis on its own.

 

My case is such that I have a few given Pivots in the game, and I generate multiple points between these pivots to move a camera smoothly between these points. This also rotates the camera based upon the rotation of the points.

 

My test points are kind of uncommon.

 

Vec3 positionstart = Vec3(2, 1, 0)

Vec3 rotationstart = Vec3(0, 0, 0)

 

Vec3 positionend = Vec3(5, 3, 0)

Vec3 rotationend = Vec3(90, 15, 180)

 

Vec3 rot = box->GetRotation(true);
Vec3 new_pos;
Vec3 new_rot;
cur->nextPoint(Time::GetCurrent(), new_pos, new_rot);

Vec3 rotDiff = new_rot - rot;
box->SetPosition(new_pos);
box->Turn(rotDiff.x, 0, 0, true);
box->Turn(0, rotDiff.y, 0, true);
box->Turn(0, 0, rotDiff.z, true);

Link to comment
Share on other sites

So you have predetermined rotations and you want to smoothly interpolate between them?

 

Get the quaternion and use the Quat:Slerp() function. This will provide 100% smooth interpolation between any rotations:

http://www.leadwerks.com/werkspace/page/api-reference/_/quat/quatslerp-r898

 

Then use Entity:SetQuaternion to set the rotation with your quat.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...