[SOLVED] Camera X, Y, Z query

Does anyone know if there is a way to print (to a variable, to a log, or to the screen) the current player’s X, Y, Z position?

In attempting to script a scene with in game assets, it is a nightmare to try to get units and cameras to be and look at exactly where I want them. I spend so much time adjusting the XYZ and relaunching… and repeat to infinity!

It would be nice to just code a hotkey to somehow give me the coordinates of exactly where i am currently and what direction I am looking!

1 Like

That could be really useful and I’m pretty sure no one ever asked about this in the Homeworld community.

My way would just be opening the scene in Max and arrange the scene and camera in there.

I have tried this in Blender. I find it useful using a 3d app to get a layout of what my LEVEL will be like. I even considered scripting the import of LEVEL file and output to LEVEL file of my blender objects… but when calculating the effort to do that against doing it manually I just opted to do it manually this round.

BUT, when making in game cut scenes(like an NIS) for mission maps I need something far more accurate(meaning I am having trouble getting blender to represent the in game 3d space accurately) with a quicker turn around to get the actors and cameras in place easier.

e.g. If I want a fighter to fly between some ships at an angle with the view point turning to look at the side of the capital ship it is flying by and then back to forward looking… well is far easier to visualize what i want with my own movement in game using the assets I already have in game. If there was a function to return the exact coordinates into the LUA trace, I could quickly position the camera against the squadrons, SNAPSHOT, next position, SNAPSHOT, and so on and cut-paste into the (xzy) of my script cameras, add-spheres, camera interpolates and add-squadrons.

SobGroup_GetPosition(< sSobGroupName >) could be used for the position.

SobGroup_GetCoordSys() and SobGroup_GetCentrePosition() could also be used for that I imagine, but there is no documentation on those (they are new to hwrm) and would need some testing.

No idea for the orientation, though.

Edit : oh, you meant the current camera position ? I read too fast, sorry :confused:

I tried GetPostion, then sent it to log with Print. Results were:
"sob_position
table: 066ED6D8 "

I am unsure how or where to find the table results. Does the above output mean something to you?

That helped, thanks!

CODE
local Position = SobGroup_GetCentrePosition(“HumanPlayerSOB”)
print(“Position = {”…Position[1]…", “…Position[2]…”, “…Position[3]…”},")

INLOG
Position = {22000, 5000.703125, -9042.1484375},

1 Like

Sorry, didn’t see your message soon enough, but you seem to have resolved the problem :slight_smile:

So that’s what you wanted after all ? I thought you wanted the camera position after re-reading your first post.

I did, but the sobgroup location is more than i had before. :slight_smile:
Still would love to know the camera location if it can be done… but this I can work with.

Thanks!

Getting the camera location sounds like a good function to have. I wonder how Relic designed their missions?

Maybe they did something in Maya?

It would be nice. I have made missions for other games like C&C. When in the mission editor I can place an actor in a map and face it the direction I want. This gives me a fairly precise picture of what the player will see. And even having that it takes weeks to make a 40 second cut scene (you can check my YouTube of those scenes to see what I am talking about).

Creating a cut scene in homeworld, when doing it via LEVEL script with manually entering the XYZ of were the camera is, and then trying to figure out what direction it is looking in a 3 coordinate space (3d space) is super time consuming. Not to mention getting the camera to move with actors (ships) moving about doing battle.

That being said I did code a function using the code above to take snapshots of locations of my scout ship when I press a key. That will make it a bit easier. sort of a home made WYSIWYG.

It still would nice if there was a way to get the exact camera specs (location, direction and any other properties set) of what the player is currently looking at. This would make it much easier to make good quality cut scenes. :slight_smile:

-B8factor

First, you can get the distance between the camera and a ship, right?
Then, get the distances between the camera and 4 ships whose coordinates are known, with some calculates, tada, you have the coordinate of the camera.

2 Likes

Yeah, I saw the Camera_GetDistanceToSobGroup() function but didn’t think of that. Well done !

AXIS_DISTANCE = 100;

function OnInit()
    Volume_AddSphere("Volume_Map0", {0, 0, 0}, 0.01)
    Volume_AddSphere("Volume_MapX", {AXIS_DISTANCE, 0, 0}, 0.01)
    Volume_AddSphere("Volume_MapY", {0, AXIS_DISTANCE, 0}, 0.01)
    Volume_AddSphere("Volume_MapZ", {0, 0, AXIS_DISTANCE}, 0.01)

    SobGroup_SpawnNewShipInSobGroup(0, "Hgn_StaticProbe", "MAP_0", "SobGroup_Map0", "Volume_Map0")
    SobGroup_SpawnNewShipInSobGroup(0, "Hgn_StaticProbe", "MAP_X", "SobGroup_MapX", "Volume_MapX")
    SobGroup_SpawnNewShipInSobGroup(0, "Hgn_StaticProbe", "MAP_Y", "SobGroup_MapY", "Volume_MapY")
    SobGroup_SpawnNewShipInSobGroup(0, "Hgn_StaticProbe", "MAP_Z", "SobGroup_MapZ", "Volume_MapZ")
    
    SobGroup_SetInvulnerability("SobGroup_Map0", 1)
    SobGroup_SetInvulnerability("SobGroup_MapX", 1)
    SobGroup_SetInvulnerability("SobGroup_MapY", 1)
    SobGroup_SetInvulnerability("SobGroup_MapZ", 1)
end

function Camera_GetPosition()
    local a = Camera_GetDistanceToSobGroup("SobGroup_Map0")
    local b = Camera_GetDistanceToSobGroup("SobGroup_MapX")
    local c = Camera_GetDistanceToSobGroup("SobGroup_MapY")
    local d = Camera_GetDistanceToSobGroup("SobGroup_MapZ")
    
    -- (1) a^2 = x^2 + y^2 + z^2
    -- (2) b^2 = (x-AXIS_DISTANCE)^2 + y^2 + z^2
    -- (3) c^2 = x^2 + (y-AXIS_DISTANCE)^2 + z^2
    -- (4) d^2 = x^2 + y^2 + (z-AXIS_DISTANCE)^2
    
    -- solve for x^2 for future substitutions:
    -- (5) x^2 = a^2 - y^2 - z^2
    
    -- substituting x^2 into (4) gives us:  d^2 = a^2 - z^2 + (z-AXIS_DISTANCE)^2 (the y-term cancels out)
    -- expanding the z term:                d^2 = a^2 - z^2 + z^2 - 2*AXIS_DISTANCE*z + AXIS_DISTANCE*AXIS_DISTANCE
    -- simplifying:                         d^2 = a^2 - 2*AXIS_DISTANCE*z + AXIS_DISTANCE*AXIS_DISTANCE
    -- and solving for z:
    local z = AXIS_DISTANCE*AXIS_DISTANCE + a*a - d*d;
    
    -- substituting x^2 into (3) gives us:  c^2 = a^2 - y^2 + (y-AXIS_DISTANCE)^2 (the z-term cancels out)
    -- expanding the y term:                c^2 = a^2 - y^2 + y^2 - 2*AXIS_DISTANCE*y + AXIS_DISTANCE*AXIS_DISTANCE
    -- simplifying:                         c^2 = a^2 - 2*AXIS_DISTANCE*y + AXIS_DISTANCE*AXIS_DISTANCE
    -- and solving for y:
    local y = AXIS_DISTANCE*AXIS_DISTANCE + a*a - c*c;
    
    -- now plug y and z into (5):
    local x = sqrt(a - y*y - z*z);
    
    -- sqrt actually gives us two values, so now we check with (2)
    if ((b * b) ~= ((x-AXIS_DISTANCE)*(x-AXIS_DISTANCE) + y*y + z*z)) then
        x = -x;
    end
    
    return {x, y, z};
end

Hgn_StaticProbe is just what I decided to call the ship. You can use any ship, just make a copy of it, and set the speed/thruster values in the ship file to 0, and disable movement.

(I haven’t actually tested this code to see if it works…)

Do yo have a GUI button to trigger this command? What about the direction the camera is facing?

Whoops! Pretty big calculation error:

local z = (AXIS_DISTANCE*AXIS_DISTANCE + a*a - d*d) / (2*AXIS_DISTANCE);
local y = (AXIS_DISTANCE*AXIS_DISTANCE + a*a - c*c) / (2*AXIS_DISTANCE);

Forgot to divide…


And:

local x = sqrt(a*a - y*y - z*z);

Forgot I switched from saying a was pre-squared to saying a was not squared.


And figured out how to say “screw you” to the sqrt function (was getting the wrong x value)

local x = (AXIS_DISTANCE*AXIS_DISTANCE + a*a - b*b) / (2*AXIS_DISTANCE);

Complete fixed code:

data:ship/hgn_staticprobe/ copied hgn_probe folder and re-named files.
data:ship/hgn_staticprobe/hgn_staticprobe.ship – modified lines:

-- just in case SobGroup_SetInvulnerability fails
NewShipType.maxhealth=getShipNum(NewShipType, "maxhealth", 100000)
NewShipType.regentime=1
NewShipType.minRegenTime=1

...

NewShipType.thrusterMaxSpeed=0
NewShipType.mainEngineMaxSpeed=0
NewShipType.rotationMaxSpeed=0

...

-- changing these didn't actually seem to affect the sway?
NewShipType.swayUpdateTime=0
NewShipType.swayOffsetRandomX=0
NewShipType.swayOffsetRandomY=0
NewShipType.swayOffsetRandomZ=0
NewShipType.swayBobbingFactor=0
NewShipType.swayRotateFactor=0

...

addAbility(NewShipType,"MoveCommand",0,0);

data:leveldata/multiplayer/lib/camerautils.lua

AXIS_DISTANCE = 10000;

function Camera_Init()
    Volume_AddSphere("Volume_Map0", {0, 0, 0}, 0.01)
    Volume_AddSphere("Volume_MapX", {AXIS_DISTANCE, 0, 0}, 0.01)
    Volume_AddSphere("Volume_MapY", {0, AXIS_DISTANCE, 0}, 0.01)
    Volume_AddSphere("Volume_MapZ", {0, 0, AXIS_DISTANCE}, 0.01)
    
    SobGroup_Create("SobGroup_Map0")
    SobGroup_Create("SobGroup_MapX")
    SobGroup_Create("SobGroup_MapY")
    SobGroup_Create("SobGroup_MapZ")

    SobGroup_SpawnNewShipInSobGroup(0, "Hgn_StaticProbe", "MAP_0", "SobGroup_Map0", "Volume_Map0")
    SobGroup_SpawnNewShipInSobGroup(0, "Hgn_StaticProbe", "MAP_X", "SobGroup_MapX", "Volume_MapX")
    SobGroup_SpawnNewShipInSobGroup(0, "Hgn_StaticProbe", "MAP_Y", "SobGroup_MapY", "Volume_MapY")
    SobGroup_SpawnNewShipInSobGroup(0, "Hgn_StaticProbe", "MAP_Z", "SobGroup_MapZ", "Volume_MapZ")
    
    SobGroup_SetInvulnerability("SobGroup_Map0", 1)
    SobGroup_SetInvulnerability("SobGroup_MapX", 1)
    SobGroup_SetInvulnerability("SobGroup_MapY", 1)
    SobGroup_SetInvulnerability("SobGroup_MapZ", 1)
    
    ATI_LoadTemplates("data:leveldata/multiplayer/lib/camera_ati.lua")
    
    Rule_AddInterval("UpdateCameraPos", 1)
end

function Camera_GetPosition()
    local a = Camera_GetDistanceToSobGroup("SobGroup_Map0")
    local b = Camera_GetDistanceToSobGroup("SobGroup_MapX")
    local c = Camera_GetDistanceToSobGroup("SobGroup_MapY")
    local d = Camera_GetDistanceToSobGroup("SobGroup_MapZ")
    
    local z = (AXIS_DISTANCE*AXIS_DISTANCE + a*a - d*d) / (2*AXIS_DISTANCE);
    local y = (AXIS_DISTANCE*AXIS_DISTANCE + a*a - c*c) / (2*AXIS_DISTANCE);
    local x = (AXIS_DISTANCE*AXIS_DISTANCE + a*a - b*b) / (2*AXIS_DISTANCE);
    
    return { X = x, Y = y, Z = z};
end

function UpdateCameraPos()
    local pos = Camera_GetPosition();
    ATI_Clear()
    ATI_CreateParameters(1)
    ATI_AddString(0, format("campos: %.4f, %.4f, %.4f", pos["X"], pos["Y"], pos["Z"]))
    ATI_Display2D("Message", {0.02, 0.2, 0, 0}, 0)
end

data:leveldata/multiplayer/lib/camera_ati.lua:

SCAR_ATITemplates = {
    Message = {
        {
            stringParam = 0,
            text = {
                colour = {1, 1, 1, 1},
                dropshadow = 1,
                renderFlags = { "justifyLeft" },
                LODs = { 1, "SPSubtitleFont" }
            },
            placement2D = {
                factorX = -0.05,
                factorY = -1,
                minATIArea = 0,
                maxATIArea = 1,
                visibility = {}
            }
        }
    }
}

In data:scripts/rules/deathmatch/deathmatch.lua:

Add dofilepath("data:leveldata/multiplayer/lib/camerautils.lua") after other dofilepaths.
Add Camera_Init() before end of OnInit()

Run the game. See Camera Position displayed.

Also, ships tend to have a random “sway” attached to them, even when stationary, so this isn’t a 100% exact science… But it will get you 99.9% there, which in my book is plenty! :wink:

3 Likes

I’m sure a trigger could be made, yes. I’ll leave that to others.

Direction might be possible, but I doubt it. If it is, it would be really complex…

Edit: Actually, I lied. I just figured out how to do it.

Press key, save camera position.
Zoom In/Out
Press key again, save second camera position.
Calculate difference in positions and normalize vector, keeping in mind if you zoomed out or in.
(If you just zoom in (assuming you’re not already all the way zoomed in), and take the NewPos minus OldPos, you’ll have your direction vector).

Edit: Also regarding the ship sway: Ships don’t sway while the game is paused. Then again, this particular display of the camera position doesn’t update while the game is paused either. I suppose a keybind might be the way to go here, but I’m not sure if the keybind functions are called independently of the game clock ticking…

1 Like

Yup, already thinking key-bind when i got to this post.

In my use of the function I start with a map and then fly a scout around marking position where I want the fleet to be, value written to log (screen is nice touch but i can extract from log with script faster and write to LEVEL file with correct syntax automatically).

Another nice time saver, I can move through the map and mark points for a patrol path or camera path quickly as well. This saves a lot of time over all the guesswork of plotting XYZ manually and running game to see if objects are where I expect them to be.

Now time to make some missions! :slight_smile:

Thanks All!

Ah, you were faster than me, I was also looking to create a trilateration algorithm ^^
Well done :slight_smile:

Your idea for the direction is great too !

Edit :
I suppose the direction thing could be automated by activating sensor mode, taking one measure, deactivating sensor mode, taking another measure. As sensor mode is an “automatic” zoom out, you would have your two points this way. The function to do this should be MainUI_UserEvent(eSensorsManager)

The maths turned out to be a lot more simple than I was expecting…